Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
15595994 | 880 days ago | Contract Creation | 0 ETH | |||
15589661 | 881 days ago | Contract Creation | 0 ETH | |||
15589661 | 881 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
NounletRegistry
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {ClonesWithImmutableArgs} from "clones-with-immutable-args/src/ClonesWithImmutableArgs.sol"; import {NounletToken} from "./NounletToken.sol"; import {VaultFactory} from "./VaultFactory.sol"; import {INounletRegistry as IRegistry} from "./interfaces/INounletRegistry.sol"; import {IVault} from "./interfaces/IVault.sol"; /// @title NounletRegistry /// @author Tessera /// @notice Registry contract for tracking all fractionalized NounsToken vaults contract NounletRegistry is IRegistry { /// @dev Using clones library with address types using ClonesWithImmutableArgs for address; /// @notice Address of VaultFactory contract address public immutable factory; /// @notice Address of Implementation for NounletToken contract address public immutable implementation; /// @notice Address of NounsToken contract address public immutable nounsToken; /// @notice Address of token royalty beneficiary address public immutable royaltyBeneficiary; /// @notice Mapping of vault address to token address mapping(address => address) public vaultToToken; /// @dev Initializes factory, implementation, and token contracts constructor(address _royaltyBeneficiary, address _nounsToken) { factory = address(new VaultFactory()); implementation = address(new NounletToken()); royaltyBeneficiary = _royaltyBeneficiary; nounsToken = _nounsToken; } /// @notice Burns vault tokens for multiple IDs /// @param _from Address to burn fraction tokens from /// @param _ids Token IDs to burn function batchBurn(address _from, uint256[] memory _ids) external { address info = vaultToToken[msg.sender]; if (info == address(0)) revert UnregisteredVault(msg.sender); NounletToken(info).batchBurn(_from, _ids); } /// @notice Creates a new vault with permissions and plugins /// @param _merkleRoot Hash of merkle root for vault permissions /// @param _plugins Addresses of plugin contracts /// @param _selectors List of function selectors /// @return vault Address of Proxy contract function create( bytes32 _merkleRoot, address[] memory _plugins, bytes4[] memory _selectors, address _descriptor, uint256 _nounId ) external returns (address vault) { address token = implementation.clone( abi.encodePacked(address(this), _descriptor, _nounId, royaltyBeneficiary, nounsToken) ); vault = _deployVault(_merkleRoot, token, _plugins, _selectors); } /// @notice Mints vault token /// @param _to Target address /// @param _id ID of token function mint(address _to, uint256 _id) external { address info = vaultToToken[msg.sender]; if (info == address(0)) revert UnregisteredVault(msg.sender); NounletToken(info).mint(_to, _id, ""); } /// @notice Gets the uri for a given token and ID associated with a vault /// @param _vault Address of the vault /// @param _id ID of the token /// @return URI of token function uri(address _vault, uint256 _id) external view returns (string memory) { address info = vaultToToken[_vault]; return NounletToken(info).uri(_id); } /// @dev Deploys new vault for specified token, sets merkle root, and installs plugins /// @param _merkleRoot Hash of merkle root for vault permissions /// @param _token Address of FERC1155 contract /// @param _plugins Addresses of plugin contracts /// @param _selectors List of function selectors /// @return vault Address of Proxy contract function _deployVault( bytes32 _merkleRoot, address _token, address[] memory _plugins, bytes4[] memory _selectors ) private returns (address vault) { vault = VaultFactory(factory).deploy(_merkleRoot, _plugins, _selectors); vaultToToken[vault] = _token; emit VaultDeployed(vault, _token); } }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title ClonesWithImmutableArgs /// @author wighawag, zefram.eth /// @notice Enables creating clone contracts with immutable args library ClonesWithImmutableArgs { error CreateFail(); /// @notice Creates a clone proxy of the implementation contract, with immutable args /// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length /// @param implementation The implementation contract to clone /// @param data Encoded immutable args /// @return instance The address of the created clone function clone(address implementation, bytes memory data) internal returns (address payable instance) { // unrealistic for memory ptr or data length to exceed 256 bits unchecked { uint256 extraLength = data.length + 2; // +2 bytes for telling how much data there is appended to the call uint256 creationSize = 0x41 + extraLength; uint256 runSize = creationSize - 10; uint256 dataPtr; uint256 ptr; // solhint-disable-next-line no-inline-assembly assembly { ptr := mload(0x40) // ------------------------------------------------------------------------------------------------------------- // CREATION (10 bytes) // ------------------------------------------------------------------------------------------------------------- // 61 runtime | PUSH2 runtime (r) | r | – mstore( ptr, 0x6100000000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x01), shl(240, runSize)) // size of the contract running bytecode (16 bits) // creation size = 0a // 3d | RETURNDATASIZE | 0 r | – // 81 | DUP2 | r 0 r | – // 60 creation | PUSH1 creation (c) | c r 0 r | – // 3d | RETURNDATASIZE | 0 c r 0 r | – // 39 | CODECOPY | 0 r | [0-runSize): runtime code // f3 | RETURN | | [0-runSize): runtime code // ------------------------------------------------------------------------------------------------------------- // RUNTIME (55 bytes + extraLength) // ------------------------------------------------------------------------------------------------------------- // 3d | RETURNDATASIZE | 0 | – // 3d | RETURNDATASIZE | 0 0 | – // 3d | RETURNDATASIZE | 0 0 0 | – // 3d | RETURNDATASIZE | 0 0 0 0 | – // 36 | CALLDATASIZE | cds 0 0 0 0 | – // 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | – // 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | – // 37 | CALLDATACOPY | 0 0 0 0 | [0, cds) = calldata // 61 | PUSH2 extra | extra 0 0 0 0 | [0, cds) = calldata mstore( add(ptr, 0x03), 0x3d81600a3d39f33d3d3d3d363d3d376100000000000000000000000000000000 ) mstore(add(ptr, 0x13), shl(240, extraLength)) // 60 0x37 | PUSH1 0x37 | 0x37 extra 0 0 0 0 | [0, cds) = calldata // 0x37 (55) is runtime size - data // 36 | CALLDATASIZE | cds 0x37 extra 0 0 0 0 | [0, cds) = calldata // 39 | CODECOPY | 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 36 | CALLDATASIZE | cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 61 extra | PUSH2 extra | extra cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData mstore( add(ptr, 0x15), 0x6037363936610000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x1b), shl(240, extraLength)) // 01 | ADD | cds+extra 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 73 addr | PUSH20 0x123… | addr 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData mstore( add(ptr, 0x1d), 0x013d730000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x20), shl(0x60, implementation)) // 5a | GAS | gas addr 0 cds 0 0 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // f4 | DELEGATECALL | success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | rds success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3d | RETURNDATASIZE | rds rds success 0 0 | [0, cds) = calldata, [cds, cds+0x37) = extraData // 93 | SWAP4 | 0 rds success 0 rds | [0, cds) = calldata, [cds, cds+0x37) = extraData // 80 | DUP1 | 0 0 rds success 0 rds | [0, cds) = calldata, [cds, cds+0x37) = extraData // 3e | RETURNDATACOPY | success 0 rds | [0, rds) = return data (there might be some irrelevant leftovers in memory [rds, cds+0x37) when rds < cds+0x37) // 60 0x35 | PUSH1 0x35 | 0x35 sucess 0 rds | [0, rds) = return data // 57 | JUMPI | 0 rds | [0, rds) = return data // fd | REVERT | – | [0, rds) = return data // 5b | JUMPDEST | 0 rds | [0, rds) = return data // f3 | RETURN | – | [0, rds) = return data mstore( add(ptr, 0x34), 0x5af43d3d93803e603557fd5bf300000000000000000000000000000000000000 ) } // ------------------------------------------------------------------------------------------------------------- // APPENDED DATA (Accessible from extcodecopy) // (but also send as appended data to the delegatecall) // ------------------------------------------------------------------------------------------------------------- extraLength -= 2; uint256 counter = extraLength; uint256 copyPtr = ptr + 0x41; // solhint-disable-next-line no-inline-assembly assembly { dataPtr := add(data, 32) } for (; counter >= 32; counter -= 32) { // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, mload(dataPtr)) } copyPtr += 32; dataPtr += 32; } uint256 mask = ~(256**(32 - counter) - 1); // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, and(mload(dataPtr), mask)) } copyPtr += counter; // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, shl(240, extraLength)) } // solhint-disable-next-line no-inline-assembly assembly { instance := create(0, ptr, creationSize) } if (instance == address(0)) { revert CreateFail(); } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {Clone} from "clones-with-immutable-args/src/Clone.sol"; import {ERC1155B, ERC1155BCheckpointable} from "./utils/ERC1155BCheckpointable.sol"; import {PermitBase} from "./utils/PermitBase.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {INounletToken as INounlet} from "./interfaces/INounletToken.sol"; import {INounsDescriptor as IDescriptor} from "./interfaces/INounsDescriptor.sol"; import {INounsSeeder} from "./interfaces/INounsSeeder.sol"; import {INounsToken as INouns} from "./interfaces/INounsToken.sol"; /// @title NounletToken /// @author Tessera /// @notice An ERC-1155B implementation for Fractional Nouns contract NounletToken is Clone, ERC1155BCheckpointable, INounlet, PermitBase { /// @dev Using strings library with uint256 types using Strings for uint256; /// @notice Percentage amount for royalties uint96 public constant ROYALTY_PERCENT = 200; /// @notice Mapping of token ID to Nounlet seed mapping(uint256 => INounsSeeder.Seed) public seeds; /// @notice Mapping of token type approvals owner => operator => tokenId => approval status mapping(address => mapping(address => mapping(uint256 => bool))) public isApproved; /// @dev Modifier for restricting function calls modifier onlyAuthorized(address _sender) { if (msg.sender != _sender) revert InvalidSender(_sender, msg.sender); _; } /// @notice Mints new fractions for an ID /// @param _to Address to mint fraction tokens to /// @param _id Token ID to mint /// @param _data Extra calldata to include in the mint function mint( address _to, uint256 _id, bytes calldata _data ) external onlyAuthorized(NOUNLET_REGISTRY()) { seeds[_id] = generateSeed(_id); _mint(_to, _id, _data); } /// @notice Burns fractions for multiple IDs /// @param _from Address to burn fraction tokens from /// @param _ids Token IDs to burn function batchBurn(address _from, uint256[] calldata _ids) external onlyAuthorized(NOUNLET_REGISTRY()) { _batchBurn(_from, _ids); } /// @notice Permit function that approves an operator for token type with a valid signature /// @param _owner Address of the owner of the token type /// @param _operator Address of the spender of the token type /// @param _id ID of the token type /// @param _approved Approval status for the token type /// @param _deadline Expiration of the signature /// @param _v The recovery ID (129th byte and chain ID) of the signature used to recover the signer /// @param _r The first 64 bytes of the signature /// @param _s Bytes 64-128 of the signature function permit( address _owner, address _operator, uint256 _id, bool _approved, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external { if (block.timestamp > _deadline) revert SignatureExpired(block.timestamp, _deadline); // cannot realistically overflow on human timescales unchecked { bytes32 structHash = _computePermitStructHash( _owner, _operator, _id, _approved, _deadline ); bytes32 digest = _computeDigest(_computeDomainSeparator(), structHash); address signer = ecrecover(digest, _v, _r, _s); if (signer == address(0) || signer != _owner) revert InvalidSignature(signer, _owner); } isApproved[_owner][_operator][_id] = _approved; emit SingleApproval(_owner, _operator, _id, _approved); } /// @notice Permit function that approves an operator for all token types with a valid signature /// @param _owner Address of the owner of the token type /// @param _operator Address of the spender of the token type /// @param _approved Approval status for the token type /// @param _deadline Expiration of the signature /// @param _v The recovery ID (129th byte and chain ID) of the signature used to recover the signer /// @param _r The first 64 bytes of the signature /// @param _s Bytes 64-128 of the signature function permitAll( address _owner, address _operator, bool _approved, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external { if (block.timestamp > _deadline) revert SignatureExpired(block.timestamp, _deadline); // cannot realistically overflow on human timescales unchecked { bytes32 structHash = _computePermitAllStructHash( _owner, _operator, _approved, _deadline ); bytes32 digest = _computeDigest(_computeDomainSeparator(), structHash); address signer = ecrecover(digest, _v, _r, _s); if (signer == address(0) || signer != _owner) revert InvalidSignature(signer, _owner); } isApprovedForAll[_owner][_operator] = _approved; emit ApprovalForAll(_owner, _operator, _approved); } /// @notice Scoped approvals allow us to eliminate some of the risks associated with setting the approval for an entire collection /// @param _operator Address of spender account /// @param _id ID of the token type /// @param _approved Approval status for operator(spender) account function setApprovalFor( address _operator, uint256 _id, bool _approved ) external { isApproved[msg.sender][_operator][_id] = _approved; emit SingleApproval(msg.sender, _operator, _id, _approved); } /// @notice Returns the royalty amount for a given token /// @param _salePrice Price of token sold on secondary market function royaltyInfo( uint256, /* _id */ uint256 _salePrice ) external pure returns (address beneficiary, uint256 royaltyAmount) { beneficiary = ROYALTY_BENEFICIARY(); royaltyAmount = (_salePrice * uint256(ROYALTY_PERCENT)) / 10000; } /// @notice Transfers multiple token types /// @param _from Source address /// @param _to Destination address /// @param _ids IDs of each token type /// @param _amounts Transfer amounts per token type /// @param _data Additional calldata function safeBatchTransferFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data ) public override(ERC1155BCheckpointable, INounlet) { super.safeBatchTransferFrom(_from, _to, _ids, _amounts, _data); } /// @notice Transfers a single token type /// @param _from Source address /// @param _to Destination address /// @param _id ID of the token type /// @param _amount Transfer amount /// @param _data Additional calldata function safeTransferFrom( address _from, address _to, uint256 _id, uint256 _amount, bytes calldata _data ) public override(ERC1155BCheckpointable, INounlet) { require( msg.sender == _from || isApprovedForAll[_from][msg.sender] || isApproved[_from][msg.sender][_id], "NOT_AUTHORIZED" ); super.safeTransferFrom(_from, _to, _id, _amount, _data); } function batchTransferFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data ) public override(ERC1155BCheckpointable, INounlet) { super.batchTransferFrom(_from, _to, _ids, _amounts, _data); } /// @notice Transfers a single token type /// @param _from Source address /// @param _to Destination address /// @param _id ID of the token type /// @param _amount Transfer amount /// @param _data Additional calldata function transferFrom( address _from, address _to, uint256 _id, uint256 _amount, bytes calldata _data ) public override(ERC1155BCheckpointable, INounlet) { require( msg.sender == _from || isApprovedForAll[_from][msg.sender] || isApproved[_from][msg.sender][_id], "NOT_AUTHORIZED" ); super.transferFrom(_from, _to, _id, _amount, _data); } /// @notice Returns the URI of a token type /// @param _id ID of the token type function uri(uint256 _id) public view override(ERC1155B, INounlet) returns (string memory) { string memory nounId = NOUNS_TOKEN_ID().toString(); string memory name = string(abi.encodePacked("Nounlet #", _id.toString())); string memory description = string( abi.encodePacked("Noun ", nounId, " is collectively owned by a 100 member DAO") ); return IDescriptor(NOUNS_DESCRIPTOR()).genericDataURI(name, description, seeds[_id]); } function contractURI() public view returns (string memory) { return string(abi.encodePacked("https://nounlets.wtf/api/noun/", NOUNS_TOKEN_ID().toString())); } function owner() public view returns (address) { return ROYALTY_BENEFICIARY(); } /// @notice Generates a random seed for a given token /// @param _id ID of the token type function generateSeed(uint256 _id) public view returns (INounsSeeder.Seed memory) { address descriptor = NOUNS_DESCRIPTOR(); INounsSeeder.Seed memory noun = INouns(NOUNS_TOKEN()).seeds(NOUNS_TOKEN_ID()); uint256 pseudorandomness = uint256( keccak256(abi.encodePacked(blockhash(block.number - 1), _id)) ); uint256 backgroundCount = IDescriptor(descriptor).backgroundCount(); uint256 bodyCount = IDescriptor(descriptor).bodyCount(); uint256 accessoryCount = IDescriptor(descriptor).accessoryCount(); uint256 glassesCount = IDescriptor(descriptor).glassesCount(); return INounsSeeder.Seed({ background: uint48((pseudorandomness) % backgroundCount), body: uint48((pseudorandomness >> 48) % bodyCount), accessory: uint48((pseudorandomness >> 96) % accessoryCount), head: uint48(noun.head), glasses: uint48((pseudorandomness >> 192) % glassesCount) }); } /// @dev Returns true if this contract implements the interface defined by the given identifier function supportsInterface(bytes4 _interfaceId) public view virtual returns (bool) { return (_interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 _interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 _interfaceId == 0x2a55205a); // ERC165 Interface ID for ERC2981 } /// @notice Address of NounletRegistry contract /// @dev ClonesWithImmutableArgs appends this value to the end of the initial bytecode at index 0 function NOUNLET_REGISTRY() public pure returns (address) { return _getArgAddress(0); } /// @notice Address of NounsDescriptor contract /// @dev ClonesWithImmutableArgs appends this value to the end of the initial bytecode at index 20 function NOUNS_DESCRIPTOR() public pure returns (address) { return _getArgAddress(20); } /// @notice ID of the NounsToken /// @dev ClonesWithImmutableArgs appends this value to the end of the initial bytecode at index 40 function NOUNS_TOKEN_ID() public pure returns (uint256) { return _getArgUint256(40); } /// @notice Address of the royalty beneficiary /// @dev ClonesWithImmutableArgs appends this value to the end of the initial bytecode at index 72 function ROYALTY_BENEFICIARY() public pure returns (address) { return _getArgAddress(72); } function NOUNS_TOKEN() public pure returns (address) { return _getArgAddress(92); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {Create2ClonesWithImmutableArgs} from "clones-with-immutable-args/src/Create2ClonesWithImmutableArgs.sol"; import {IVaultFactory} from "./interfaces/IVaultFactory.sol"; import {Vault} from "./Vault.sol"; /// @title Vault Factory /// @author Tessera /// @notice Factory contract for deploying fractional vaults contract VaultFactory is IVaultFactory { /// @dev Use clones library for address types using Create2ClonesWithImmutableArgs for address; /// @notice Address of Vault proxy contract address public implementation; /// @dev Internal mapping to track the next seed to be used by an EOA mapping(address => bytes32) internal nextSeeds; /// @notice Initializes implementation contract constructor() { implementation = address(new Vault()); } /// @notice Deploys new vault for sender /// @param _merkleRoot Merkle root of deployed vault /// @param _plugins Addresses of plugin contracts /// @param _selectors List of function selectors /// @return vault Address of deployed vault function deploy( bytes32 _merkleRoot, address[] calldata _plugins, bytes4[] calldata _selectors ) external returns (address payable vault) { vault = deployFor(_merkleRoot, msg.sender, _plugins, _selectors); } /// @notice Gets pre-computed address of vault deployed by given account /// @param _deployer Address of vault deployer /// @param _merkleRoot Merkle root of deployed vault /// @return vault Address of next vault function getNextAddress(address _deployer, bytes32 _merkleRoot) external view returns (address vault) { bytes32 salt = keccak256(abi.encode(_deployer, nextSeeds[_deployer])); (uint256 creationPtr, uint256 creationSize) = implementation.cloneCreationCode( abi.encodePacked(_merkleRoot, _deployer, address(this)) ); bytes32 creationHash; assembly { creationHash := keccak256(creationPtr, creationSize) } bytes32 data = keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, creationHash)); vault = address(uint160(uint256(data))); } /// @notice Gets next seed value of given account /// @param _deployer Address of vault deployer /// @return Value of next seed function getNextSeed(address _deployer) external view returns (bytes32) { return nextSeeds[_deployer]; } /// @notice Deploys new vault for given address /// @param _merkleRoot Merkle root of deployed vault /// @param _owner Address of vault owner /// @param _plugins Addresses of plugin contracts /// @param _selectors List of function selectors /// @return vault Address of deployed vault function deployFor( bytes32 _merkleRoot, address _owner, address[] calldata _plugins, bytes4[] calldata _selectors ) public returns (address payable vault) { bytes32 seed = nextSeeds[tx.origin]; // Prevent front-running the salt by hashing the concatenation of tx.origin and the user-provided seed. bytes32 salt = keccak256(abi.encode(tx.origin, seed)); bytes memory data = abi.encodePacked(_merkleRoot, _owner, address(this)); vault = implementation.clone(salt, data); // Increment the seed. unchecked { nextSeeds[tx.origin] = bytes32(uint256(seed) + 1); } Vault(vault).setPlugins(_plugins, _selectors); // Log the vault via en event. emit DeployVault(tx.origin, msg.sender, _owner, seed, salt, vault); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @dev Interface for NounletRegistry contract interface INounletRegistry { /// @dev Emitted when the caller is not a registered vault error UnregisteredVault(address _sender); /// @dev Event log for deploying vault /// @param _vault Address of the vault /// @param _token Address of the token event VaultDeployed(address indexed _vault, address indexed _token); function batchBurn(address _from, uint256[] memory _ids) external; function create( bytes32 _merkleRoot, address[] memory _plugins, bytes4[] memory _selectors, address _descriptor, uint256 _nounId ) external returns (address vault); function factory() external view returns (address); function implementation() external view returns (address); function mint(address _to, uint256 _id) external; function nounsToken() external view returns (address); function royaltyBeneficiary() external view returns (address); function uri(address _vault, uint256 _id) external view returns (string memory); function vaultToToken(address) external view returns (address token); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @dev Interface for Vault proxy contract interface IVault { /// @dev Emitted when execution reverted with no reason error ExecutionReverted(); /// @dev Emitted when ownership of the proxy has been renounced error Initialized(address _owner, address _newOwner, uint256 _nonce); /// @dev Emitted when there is no implementation stored in methods for a function signature error MethodNotFound(); /// @dev Emitted when length of input arrays don't match error ArrayMismatch(uint256 _pluginsLength, uint256 _selectorsLength); /// @dev Emitted when a plugin selector would overwrite an existing plugin error InvalidSelector(bytes4 _selector); /// @dev Emitted when the caller is not the owner error NotAuthorized(address _caller, address _target, bytes4 _selector); /// @dev Emitted when the caller is not the owner error NotOwner(address _owner, address _caller); /// @dev Emitted when the owner is changed during the DELEGATECALL error OwnerChanged(address _originalOwner, address _newOwner); /// @dev Emitted when passing an EOA or an undeployed contract as the target error TargetInvalid(address _target); /// @dev Event log for executing transactions /// @param _target Address of target contract /// @param _data Transaction data being executed /// @param _response Return data of delegatecall event Execute(address indexed _target, bytes _data, bytes _response); /// @dev Event log for installing plugins /// @param _selectors List of function selectors /// @param _plugins List of plugin contracts event UpdatedPlugins(bytes4[] _selectors, address[] _plugins); function execute( address _target, bytes memory _data, bytes32[] memory _proof ) external payable returns (bool success, bytes memory response); function setPlugins(address[] memory _plugins, bytes4[] memory _selectors) external; function methods(bytes4) external view returns (address); function MERKLE_ROOT() external view returns (bytes32); function OWNER() external view returns (address); function FACTORY() external view returns (address); }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title Clone /// @author zefram.eth /// @notice Provides helper functions for reading immutable args from calldata contract Clone { /// @notice Reads an immutable arg with type address /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgAddress(uint256 argOffset) internal pure returns (address arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0x60, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint256 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads an immutable arg with type bytes32 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgBytes32(uint256 argOffset) internal pure returns (bytes32 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := calldataload(add(offset, argOffset)) } } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgUint256Array(uint256 argOffset, uint64 arrLen) internal pure returns (uint256[] memory arr) { uint256 offset = _getImmutableArgsOffset(); uint256 el; arr = new uint256[](arrLen); for (uint64 i = 0; i < arrLen; i++) { assembly { // solhint-disable-next-line no-inline-assembly el := calldataload(add(add(offset, argOffset), mul(i, 32))) } arr[i] = el; } return arr; } /// @notice Reads a uint256 array stored in the immutable args. /// @param argOffset The offset of the arg in the packed data /// @param arrLen Number of elements in the array /// @return arr The array function _getArgBytes32Array(uint256 argOffset, uint64 arrLen) internal pure returns (bytes32[] memory arr) { uint256 offset = _getImmutableArgsOffset(); bytes32 el; arr = new bytes32[](arrLen); for (uint64 i = 0; i < arrLen; i++) { assembly { // solhint-disable-next-line no-inline-assembly el := calldataload(add(add(offset, argOffset), mul(i, 32))) } arr[i] = el; } return arr; } /// @notice Reads an immutable arg with type uint64 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xc0, calldataload(add(offset, argOffset))) } } /// @notice Reads an immutable arg with type uint8 /// @param argOffset The offset of the arg in the packed data /// @return arg The arg value function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) { uint256 offset = _getImmutableArgsOffset(); // solhint-disable-next-line no-inline-assembly assembly { arg := shr(0xf8, calldataload(add(offset, argOffset))) } } /// @return offset The offset of the packed immutable args in calldata function _getImmutableArgsOffset() internal pure returns (uint256 offset) { // solhint-disable-next-line no-inline-assembly assembly { offset := sub( calldatasize(), add(shr(240, calldataload(sub(calldatasize(), 2))), 2) ) } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import "./ERC1155B.sol"; import "@rari-capital/solmate/src/utils/SafeCastLib.sol"; import "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol"; abstract contract ERC1155BCheckpointable is ERC1155B { using SafeCastLib for uint256; /// @notice Defines decimals as per ERC-20 convention to make integrations with 3rd party governance platforms easier uint8 public constant decimals = 0; uint96 public totalSupply; uint96 public constant maxSupply = type(uint96).max; /// delegator -> delegatee mapping(address => address) private _delegates; /// delegator -> #votes mapping(address => uint96) public _ballots; /// delegatee -> #checkpoints mapping(address => uint32) public numCheckpoints; /// delegatee -> checkpoint# -> checkpoint(fromBlock,#votes) mapping(address => mapping(uint32 => Checkpoint)) public checkpoints; struct Checkpoint { uint32 fromBlock; uint96 votes; } /// @dev Event log for changing of delegate by user /// @param _delegator Address of delegator /// @param _fromDelegate Address of previous delegate /// @param _toDelegate Address of new delegate event DelegateChanged( address indexed _delegator, address indexed _fromDelegate, address indexed _toDelegate ); /// @dev Event log for moving of delegates /// @param _delegate Address of the delegate /// @param _previousBalance Previous balance of votes /// @param _newBalance Updated balance of votes event DelegateVotesChanged( address indexed _delegate, uint256 _previousBalance, uint256 _newBalance ); function delegate(address delegatee) external { return _delegate(msg.sender, delegatee); } function getCurrentVotes(address account) external view returns (uint96) { uint32 pos = numCheckpoints[account]; return pos != 0 ? checkpoints[account][pos - 1].votes : 0; } function getPriorVotes(address account, uint256 blockNumber) public view virtual returns (uint256) { require(block.number > blockNumber, "UNDETERMINED"); uint32 pos = numCheckpoints[account]; if (pos == 0) return 0; if (checkpoints[account][pos - 1].fromBlock <= blockNumber) return checkpoints[account][pos - 1].votes; if (checkpoints[account][0].fromBlock > blockNumber) return 0; uint32 lower; uint32 upper = pos - 1; while (upper > lower) { uint32 center = upper - (upper - lower) / 2; Checkpoint memory cp = checkpoints[account][center]; if (cp.fromBlock == blockNumber) return cp.votes; cp.fromBlock < blockNumber ? lower = center : upper = center - 1; } return checkpoints[account][lower].votes; } function votesToDelegate(address delegator) public view returns (uint96) { return _ballots[delegator]; } /** * @notice Overrides the standard `Comp.sol` delegates mapping to return * the delegator's own address if they haven't delegated. * This avoids having to delegate to oneself. */ function delegates(address delegator) public view returns (address) { address current = _delegates[delegator]; return current == address(0) ? delegator : current; } function safeTransferFrom( address src, address dst, uint256 id, uint256, bytes calldata data ) public virtual override { _ballots[src]--; _ballots[dst]++; _moveDelegates(delegates(src), delegates(dst), 1); super.safeTransferFrom(src, dst, id, 1, data); } function safeBatchTransferFrom( address src, address dst, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual override { uint96 amount = ids.length.safeCastTo96(); _ballots[src] -= amount; _ballots[dst] += amount; _moveDelegates(delegates(src), delegates(dst), amount); super.safeBatchTransferFrom(src, dst, ids, amounts, data); } function transferFrom( address src, address dst, uint256 id, uint256, bytes calldata data ) public virtual override { _ballots[src]--; _ballots[dst]++; _moveDelegates(delegates(src), delegates(dst), 1); super.transferFrom(src, dst, id, 1, data); } function batchTransferFrom( address src, address dst, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual override { uint96 amount = ids.length.safeCastTo96(); _ballots[src] -= amount; _ballots[dst] += amount; _moveDelegates(delegates(src), delegates(dst), amount); super.batchTransferFrom(src, dst, ids, amounts, data); } function _mint( address dst, uint256 id, bytes memory data ) internal virtual override { totalSupply++; _ballots[dst]++; _moveDelegates(address(0), delegates(dst), 1); super._mint(dst, id, data); } function _batchMint( address dst, uint256[] memory ids, bytes memory data ) internal virtual override { uint96 amount = ids.length.safeCastTo96(); totalSupply += amount; _ballots[dst] += amount; _moveDelegates(address(0), delegates(dst), amount); super._batchMint(dst, ids, data); } function _burn(uint256 id) internal virtual override { totalSupply--; _ballots[msg.sender]--; _moveDelegates(delegates(msg.sender), address(0), 1); super._burn(id); } function _batchBurn(address src, uint256[] memory ids) internal virtual override { uint96 amount = ids.length.safeCastTo96(); totalSupply -= amount; _ballots[src] -= amount; _moveDelegates(delegates(src), address(0), amount); super._batchBurn(src, ids); } function _delegate(address delegator, address delegatee) internal { /// @notice differs from `_delegate()` in `Comp.sol` to use `delegates` override method to simulate auto-delegation address currentDelegate = delegates(delegator); _delegates[delegator] = delegatee; uint96 amount = votesToDelegate(delegator); _moveDelegates(currentDelegate, delegatee, amount); emit DelegateChanged(delegator, currentDelegate, delegatee); } function _moveDelegates( address src, address dst, uint96 amount ) internal { if (src != dst && amount > 0) { if (src != address(0)) { uint96 srcOld; uint32 srcPos = numCheckpoints[src]; srcOld = srcPos != 0 ? checkpoints[src][srcPos - 1].votes : 0; uint96 srcNew = srcOld - amount; _writeCheckpoint(src, srcPos, srcOld, srcNew); } if (dst != address(0)) { uint32 dstPos = numCheckpoints[dst]; uint96 dstOld; dstOld = dstPos != 0 ? checkpoints[dst][dstPos - 1].votes : 0; uint96 dstNew = dstOld + amount; _writeCheckpoint(dst, dstPos, dstOld, dstNew); } } } function _writeCheckpoint( address delegatee, uint32 pos, uint96 oldVotes, uint96 newVotes ) internal { uint32 blockNumber = block.number.safeCastTo32(); if (pos > 0 && checkpoints[delegatee][pos - 1].fromBlock == blockNumber) { checkpoints[delegatee][pos - 1].votes = newVotes; } else { checkpoints[delegatee][pos] = Checkpoint(blockNumber, newVotes); numCheckpoints[delegatee] = pos + 1; } emit DelegateVotesChanged(delegatee, oldVotes, newVotes); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import "../constants/Permit.sol"; /// @title PermitBase /// @author Tessera /// @notice Utility contract for computing permit signature approvals for FERC1155 tokens abstract contract PermitBase { /// @notice Mapping of token owner to nonce value mapping(address => uint256) public nonces; /// @dev Computes hash of permit struct /// @param _owner Address of the owner of the token type /// @param _operator Address of the spender of the token type /// @param _id ID of the token type /// @param _approved Approval status for the token type /// @param _deadline Expiration of the signature function _computePermitStructHash( address _owner, address _operator, uint256 _id, bool _approved, uint256 _deadline ) internal returns (bytes32) { return keccak256( abi.encode( PERMIT_TYPEHASH, _owner, _operator, _id, _approved, nonces[_owner]++, _deadline ) ); } /// @dev Computes hash of permit all struct /// @param _owner Address of the owner of the token type /// @param _operator Address of the spender of the token type /// @param _approved Approval status for the token type /// @param _deadline Expiration of the signature function _computePermitAllStructHash( address _owner, address _operator, bool _approved, uint256 _deadline ) internal returns (bytes32) { return keccak256( abi.encode( PERMIT_ALL_TYPEHASH, _owner, _operator, _approved, nonces[_owner]++, _deadline ) ); } /// @dev Computes domain separator to prevent signature collisions /// @return Hash of the contract-specific fields function _computeDomainSeparator() internal view returns (bytes32) { return keccak256( abi.encode( DOMAIN_TYPEHASH, keccak256(bytes(NAME)), keccak256(bytes(VERSION)), block.chainid, address(this) ) ); } /// @dev Computes digest of domain separator and struct hash /// @param _domainSeparator Hash of contract-specific fields /// @param _structHash Hash of signature fields struct /// @return Hash of the signature digest function _computeDigest(bytes32 _domainSeparator, bytes32 _structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", _domainSeparator, _structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {INounsSeeder} from "./INounsSeeder.sol"; /// @dev Checkpoint information struct Checkpoint { // Timestamp of checkpoint creation uint64 fromTimestamp; // Amount of votes uint192 votes; } /// @dev Interface for NounletToken contract interface INounletToken is IERC165 { /// @dev Emitted when deadline for signature has passed error SignatureExpired(uint256 _timestamp, uint256 _deadline); /// @dev Emitted when caller is not required address error InvalidSender(address _required, address _provided); /// @dev Emitted when owner signature is invalid error InvalidSignature(address _signer, address _owner); /// @dev Event log for approving a spender of a token type /// @param _owner Address of the owner of the token type /// @param _operator Address of the spender of the token type /// @param _id ID of the token type /// @param _approved Approval status for the token type event SingleApproval( address indexed _owner, address indexed _operator, uint256 _id, bool _approved ); function NOUNLET_REGISTRY() external pure returns (address); function NOUNS_DESCRIPTOR() external pure returns (address); function NOUNS_TOKEN_ID() external pure returns (uint256); function ROYALTY_BENEFICIARY() external pure returns (address); function batchBurn(address _from, uint256[] memory _ids) external; function generateSeed(uint256 _id) external view returns (INounsSeeder.Seed memory); function isApproved( address, address, uint256 ) external view returns (bool); function mint( address _to, uint256 _id, bytes memory _data ) external; function permit( address _owner, address _operator, uint256 _id, bool _approved, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external; function permitAll( address _owner, address _operator, bool _approved, uint256 _deadline, uint8 _v, bytes32 _r, bytes32 _s ) external; function royaltyInfo(uint256 _id, uint256 _salePrice) external view returns (address receiver, uint256 royaltyAmount); function safeTransferFrom( address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data ) external; function safeBatchTransferFrom( address _from, address _to, uint256[] memory _ids, uint256[] memory _amounts, bytes memory _data ) external; function transferFrom( address _from, address _to, uint256 _id, uint256 _amount, bytes memory _data ) external; function batchTransferFrom( address _from, address _to, uint256[] calldata _ids, uint256[] calldata _amounts, bytes calldata _data ) external; function setApprovalFor( address _operator, uint256 _id, bool _approved ) external; function supportsInterface(bytes4 _interfaceId) external view returns (bool); function uri(uint256 _id) external view returns (string memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Common interface for NounsDescriptor versions, as used by NounsToken and NounsSeeder. /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.13; import {INounsSeeder} from "./INounsSeeder.sol"; interface INounsDescriptor { function tokenURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); function dataURI(uint256 tokenId, INounsSeeder.Seed memory seed) external view returns (string memory); function backgroundCount() external view returns (uint256); function bodyCount() external view returns (uint256); function accessoryCount() external view returns (uint256); function headCount() external view returns (uint256); function glassesCount() external view returns (uint256); function genericDataURI( string calldata name, string calldata description, INounsSeeder.Seed memory seed ) external view returns (string memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsSeeder /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.13; import {INounsDescriptor} from "./INounsDescriptor.sol"; interface INounsSeeder { struct Seed { uint48 background; uint48 body; uint48 accessory; uint48 head; uint48 glasses; } function generateSeed(uint256 nounId, INounsDescriptor descriptor) external view returns (Seed memory); }
// SPDX-License-Identifier: GPL-3.0 /// @title Interface for NounsToken /********************************* * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░██░░░████░░██░░░████░░░ * * ░░██████░░░████████░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░██░░██░░░████░░██░░░████░░░ * * ░░░░░░█████████░░█████████░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * * ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ * *********************************/ pragma solidity ^0.8.13; import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import {INounsDescriptor} from "./INounsDescriptor.sol"; import {INounsSeeder} from "./INounsSeeder.sol"; interface INounsToken is IERC721 { event DescriptorLocked(); event DescriptorUpdated(INounsDescriptor descriptor); event NounBurned(uint256 indexed tokenId); event NounCreated(uint256 indexed tokenId, INounsSeeder.Seed seed); event NoundersDAOUpdated(address noundersDAO); event MinterLocked(); event MinterUpdated(address minter); event SeederLocked(); event SeederUpdated(INounsSeeder seeder); function burn(uint256 tokenId) external; function dataURI(uint256 tokenId) external returns (string memory); function delegate(address delegatee) external; function descriptor() external returns (INounsDescriptor); function lockDescriptor() external; function lockMinter() external; function lockSeeder() external; function mint() external returns (uint256); function minter() external returns (address); function seeds(uint256) external view returns (INounsSeeder.Seed memory); function setDescriptor(INounsDescriptor descriptor) external; function setMinter(address minter) external; function setNoundersDAO(address noundersDAO) external; function setSeeder(INounsSeeder seeder) external; }
// SPDX-License-Identifier: BSD pragma solidity ^0.8.4; /// @title ClonesWithImmutableArgs /// @author wighawag, zefram.eth /// @notice Enables creating clone contracts with immutable args library Create2ClonesWithImmutableArgs { error CreateFail(); function cloneCreationCode(address implementation, bytes memory data) internal pure returns (uint256 ptr, uint256 creationSize) { // unchecked is safe because it is unrealistic for memory ptr or data length to exceed 256 bits unchecked { uint256 extraLength = data.length + 2; // +2 bytes for telling how much data there is appended to the call creationSize = 0x43 + extraLength; uint256 runSize = creationSize - 11; uint256 dataPtr; // solhint-disable-next-line no-inline-assembly assembly { ptr := mload(0x40) // ------------------------------------------------------------------------------------------------------------- // CREATION (11 bytes) // ------------------------------------------------------------------------------------------------------------- // 3d | RETURNDATASIZE | 0 | – // 61 runtime | PUSH2 runtime (r) | r 0 | – mstore( ptr, 0x3d61000000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x02), shl(240, runSize)) // size of the contract running bytecode (16 bits) // creation size = 0b // 80 | DUP1 | r r 0 | – // 60 creation | PUSH1 creation (c) | c r r 0 | – // 3d | RETURNDATASIZE | 0 c r r 0 | – // 39 | CODECOPY | r 0 | [0-2d]: runtime code // 81 | DUP2 | 0 c 0 | [0-2d]: runtime code // f3 | RETURN | 0 | [0-2d]: runtime code mstore( add(ptr, 0x04), 0x80600b3d3981f300000000000000000000000000000000000000000000000000 ) // ------------------------------------------------------------------------------------------------------------- // RUNTIME // ------------------------------------------------------------------------------------------------------------- // 36 | CALLDATASIZE | cds | – // 3d | RETURNDATASIZE | 0 cds | – // 3d | RETURNDATASIZE | 0 0 cds | – // 37 | CALLDATACOPY | – | [0, cds] = calldata // 61 | PUSH2 extra | extra | [0, cds] = calldata mstore( add(ptr, 0x0b), 0x363d3d3761000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x10), shl(240, extraLength)) // 60 0x38 | PUSH1 0x38 | 0x38 extra | [0, cds] = calldata // 0x38 (56) is runtime size - data // 36 | CALLDATASIZE | cds 0x38 extra | [0, cds] = calldata // 39 | CODECOPY | _ | [0, cds] = calldata // 3d | RETURNDATASIZE | 0 | [0, cds] = calldata // 3d | RETURNDATASIZE | 0 0 | [0, cds] = calldata // 3d | RETURNDATASIZE | 0 0 0 | [0, cds] = calldata // 36 | CALLDATASIZE | cds 0 0 0 | [0, cds] = calldata // 61 extra | PUSH2 extra | extra cds 0 0 0 | [0, cds] = calldata mstore( add(ptr, 0x12), 0x603836393d3d3d36610000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x1b), shl(240, extraLength)) // 01 | ADD | cds+extra 0 0 0 | [0, cds] = calldata // 3d | RETURNDATASIZE | 0 cds 0 0 0 | [0, cds] = calldata // 73 addr | PUSH20 0x123… | addr 0 cds 0 0 0 | [0, cds] = calldata mstore( add(ptr, 0x1d), 0x013d730000000000000000000000000000000000000000000000000000000000 ) mstore(add(ptr, 0x20), shl(0x60, implementation)) // 5a | GAS | gas addr 0 cds 0 0 0 | [0, cds] = calldata // f4 | DELEGATECALL | success 0 | [0, cds] = calldata // 3d | RETURNDATASIZE | rds success 0 | [0, cds] = calldata // 82 | DUP3 | 0 rds success 0 | [0, cds] = calldata // 80 | DUP1 | 0 0 rds success 0 | [0, cds] = calldata // 3e | RETURNDATACOPY | success 0 | [0, rds] = return data (there might be some irrelevant leftovers in memory [rds, cds] when rds < cds) // 90 | SWAP1 | 0 success | [0, rds] = return data // 3d | RETURNDATASIZE | rds 0 success | [0, rds] = return data // 91 | SWAP2 | success 0 rds | [0, rds] = return data // 60 0x36 | PUSH1 0x36 | 0x36 sucess 0 rds | [0, rds] = return data // 57 | JUMPI | 0 rds | [0, rds] = return data // fd | REVERT | – | [0, rds] = return data // 5b | JUMPDEST | 0 rds | [0, rds] = return data // f3 | RETURN | – | [0, rds] = return data mstore( add(ptr, 0x34), 0x5af43d82803e903d91603657fd5bf30000000000000000000000000000000000 ) } // ------------------------------------------------------------------------------------------------------------- // APPENDED DATA (Accessible from extcodecopy) // (but also send as appended data to the delegatecall) // ------------------------------------------------------------------------------------------------------------- extraLength -= 2; uint256 counter = extraLength; uint256 copyPtr; assembly { copyPtr := add(ptr, 0x43) } // solhint-disable-next-line no-inline-assembly assembly { dataPtr := add(data, 32) } for (; counter >= 32; counter -= 32) { // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, mload(dataPtr)) } copyPtr += 32; dataPtr += 32; } uint256 mask = ~(256**(32 - counter) - 1); // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, and(mload(dataPtr), mask)) } copyPtr += counter; // solhint-disable-next-line no-inline-assembly assembly { mstore(copyPtr, shl(240, extraLength)) } } } /// @notice Creates a clone proxy of the implementation contract, with immutable args /// @dev data cannot exceed 65535 bytes, since 2 bytes are used to store the data length /// @param implementation The implementation contract to clone /// @param data Encoded immutable args /// @return instance The address of the created clone function clone( address implementation, bytes32 salt, bytes memory data ) internal returns (address payable instance) { (uint256 creationPtr, uint256 creationSize) = cloneCreationCode( implementation, data ); // solhint-disable-next-line no-inline-assembly assembly { instance := create2(0, creationPtr, creationSize, salt) } // if the create failed, the instance address won't be set if (instance == address(0)) { revert CreateFail(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @dev Interface for VaultFactory contract interface IVaultFactory { /// @dev Event log for deploying vault /// @param _origin Address of transaction origin /// @param _deployer Address of sender /// @param _owner Address of vault owner /// @param _seed Value of seed /// @param _salt Value of salt /// @param _vault Address of deployed vault event DeployVault( address indexed _origin, address indexed _deployer, address indexed _owner, bytes32 _seed, bytes32 _salt, address _vault ); function deploy( bytes32 _merkleRoot, address[] memory _plugins, bytes4[] memory _selectors ) external returns (address payable vault); function deployFor( bytes32 _merkleRoot, address _owner, address[] memory _plugins, bytes4[] memory _selectors ) external returns (address payable vault); function getNextAddress(address _deployer, bytes32 _merkleRoot) external view returns (address vault); function getNextSeed(address _deployer) external view returns (bytes32); function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {IVault} from "./interfaces/IVault.sol"; import {Clone} from "clones-with-immutable-args/src/Clone.sol"; import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import {NFTReceiver} from "./utils/NFTReceiver.sol"; /// @title Vault /// @author Tessera /// @notice Proxy contract for storing fractionalized assets contract Vault is Clone, IVault, NFTReceiver { address immutable original; /// @dev Minimum reserve of gas units uint256 private constant MIN_GAS_RESERVE = 5_000; bytes4 private constant FALLBACK_SELECTOR = bytes4(0); uint256 private constant MERKLE_ROOT_POSITION = 0; uint256 private constant OWNER_POSITION = 32; uint256 private constant FACTORY_POSITION = 52; /// @notice Mapping of function selector to plugin address mapping(bytes4 => address) public methods; constructor() { original = address(this); } /// @dev Callback for receiving Ether when the calldata is empty receive() external payable {} /// @dev Callback for handling plugin transactions /// @param _data Transaction data /// @return response Return data from executing plugin // prettier-ignore fallback(bytes calldata _data) external payable returns (bytes memory response) { if (msg.sig != FALLBACK_SELECTOR){ address plugin = methods[msg.sig]; if (plugin == address(0)) revert MethodNotFound(); (,response) = _execute(plugin, _data); } } /// @notice Executes vault transactions through delegatecall /// @param _target Target address /// @param _data Transaction data /// @param _proof Merkle proof of permission hash /// @return success Result status of delegatecall /// @return response Return data of delegatecall function execute( address _target, bytes calldata _data, bytes32[] calldata _proof ) external payable returns (bool success, bytes memory response) { bytes4 selector; assembly { selector := calldataload(_data.offset) } // Generate leaf node by hashing module, target and function selector. bytes32 leaf = keccak256(abi.encode(msg.sender, _target, selector)); // Check that the caller is either a module with permission to call or the owner. if (!MerkleProof.verify(_proof, MERKLE_ROOT(), leaf)) { if (msg.sender != OWNER()) revert NotAuthorized(msg.sender, _target, selector); } (success, response) = _execute(_target, _data); } /// @notice Installs plugin by setting function selector to contract address /// @param _plugins Addresses of plugin contracts /// @param _selectors List of function selectors function setPlugins(address[] memory _plugins, bytes4[] memory _selectors) external { address owner = OWNER(); if (owner != msg.sender) { /// allows the factory to install plugins on deployment if (FACTORY() != msg.sender) revert NotOwner(owner, msg.sender); } uint256 pluginsLength = _plugins.length; uint256 selectorsLength = _selectors.length; bytes4 selector; if (pluginsLength != selectorsLength) revert ArrayMismatch(pluginsLength, selectorsLength); uint256 i; for (; i < selectorsLength; ) { selector = _selectors[i]; if (methods[selector] != address(0)) revert InvalidSelector(selector); methods[selector] = _plugins[i]; unchecked { ++i; } } emit UpdatedPlugins(_selectors, _plugins); } /// @notice Getter for merkle root stored as an immutable argument function MERKLE_ROOT() public pure returns (bytes32) { return _getArgBytes32(MERKLE_ROOT_POSITION); } /// @notice Getter for owner of vault function OWNER() public pure returns (address) { return _getArgAddress(OWNER_POSITION); } /// @notice Getter for factory of vault function FACTORY() public pure returns (address) { return _getArgAddress(FACTORY_POSITION); } /// @notice Executes plugin transactions through delegatecall /// @param _target Target address /// @param _data Transaction data /// @return success Result status of delegatecall /// @return response Return data of delegatecall function _execute(address _target, bytes calldata _data) internal returns (bool success, bytes memory response) { require(original != address(this), "only delegate call"); if (_target.code.length == 0) revert TargetInvalid(_target); // Reserve some gas to ensure that the function has enough to finish the execution uint256 stipend = gasleft() - MIN_GAS_RESERVE; // Delegate call to the target contract (success, response) = _target.delegatecall{gas: stipend}(_data); // Revert if execution was unsuccessful if (!success) { if (response.length == 0) revert ExecutionReverted(); _revertedWithReason(response); } } /// @notice Reverts transaction with reason /// @param _response Unsucessful return response of the delegate call function _revertedWithReason(bytes memory _response) internal pure { assembly { let returndata_size := mload(_response) revert(add(32, _response), returndata_size) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0; import {ERC1155TokenReceiver} from "@rari-capital/solmate/src/tokens/ERC1155.sol"; /// @notice Minimalist and gas efficient ERC1155 implementation optimized for single supply ids. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC1155B.sol) abstract contract ERC1155B { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// ERC1155B STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public ownerOf; function balanceOf(address owner, uint256 id) public view virtual returns (uint256 bal) { address idOwner = ownerOf[id]; assembly { // We avoid branching by using assembly to take // the bool output of eq() and use it as a uint. bal := eq(idOwner, owner) } } /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); require(from == ownerOf[id], "WRONG_FROM"); // Can only transfer from the owner. // Can only transfer 1 with ERC1155B. require(amount == 1, "INVALID_AMOUNT"); ownerOf[id] = to; emit TransferSingle(msg.sender, from, to, id, amount); if (to.code.length != 0) { require( ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } else require(to != address(0), "INVALID_RECIPIENT"); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < ids.length; i++) { id = ids[i]; amount = amounts[i]; // Can only transfer from the owner. require(from == ownerOf[id], "WRONG_FROM"); // Can only transfer 1 with ERC1155B. require(amount == 1, "INVALID_AMOUNT"); ownerOf[id] = to; } } emit TransferBatch(msg.sender, from, to, ids, amounts); if (to.code.length != 0) { require( ERC1155TokenReceiver(to).onERC1155BatchReceived( msg.sender, from, ids, amounts, data ) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } else require(to != address(0), "INVALID_RECIPIENT"); } function transferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata /*data*/ ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); require(from == ownerOf[id], "WRONG_FROM"); // Can only transfer from the owner. // Can only transfer 1 with ERC1155B. require(amount == 1, "INVALID_AMOUNT"); ownerOf[id] = to; emit TransferSingle(msg.sender, from, to, id, amount); } function batchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata /*data*/ ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < ids.length; i++) { id = ids[i]; amount = amounts[i]; // Can only transfer from the owner. require(from == ownerOf[id], "WRONG_FROM"); // Can only transfer 1 with ERC1155B. require(amount == 1, "INVALID_AMOUNT"); ownerOf[id] = to; } } emit TransferBatch(msg.sender, from, to, ids, amounts); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf(owners[i], ids[i]); } } } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, bytes memory data ) internal virtual { // Minting twice would effectively be a force transfer. require(ownerOf[id] == address(0), "ALREADY_MINTED"); ownerOf[id] = to; emit TransferSingle(msg.sender, address(0), to, id, 1); if (to.code.length != 0) { require( ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, 1, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchMint( address to, uint256[] memory ids, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. // Generate an amounts array locally to use in the event below. uint256[] memory amounts = new uint256[](idsLength); uint256 id; // Storing outside the loop saves ~7 gas per iteration. // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < idsLength; ++i) { id = ids[i]; // Minting twice would effectively be a force transfer. require(ownerOf[id] == address(0), "ALREADY_MINTED"); ownerOf[id] = to; amounts[i] = 1; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); if (to.code.length != 0) { require( ERC1155TokenReceiver(to).onERC1155BatchReceived( msg.sender, address(0), ids, amounts, data ) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } else require(to != address(0), "INVALID_RECIPIENT"); } function _batchBurn(address from, uint256[] memory ids) internal virtual { // Burning unminted tokens makes no sense. require(from != address(0), "INVALID_FROM"); uint256 idsLength = ids.length; // Saves MLOADs. // Generate an amounts array locally to use in the event below. uint256[] memory amounts = new uint256[](idsLength); uint256 id; // Storing outside the loop saves ~7 gas per iteration. // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < idsLength; ++i) { id = ids[i]; require(ownerOf[id] == from, "WRONG_FROM"); ownerOf[id] = address(0); amounts[i] = 1; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn(uint256 id) internal virtual { address owner = ownerOf[id]; require(owner != address(0), "NOT_MINTED"); ownerOf[id] = address(0); emit TransferSingle(msg.sender, owner, address(0), id, 1); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Safe unsigned integer casting library that reverts on overflow. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { function safeCastTo248(uint256 x) internal pure returns (uint248 y) { require(x < 1 << 248); y = uint248(x); } function safeCastTo224(uint256 x) internal pure returns (uint224 y) { require(x < 1 << 224); y = uint224(x); } function safeCastTo192(uint256 x) internal pure returns (uint192 y) { require(x < 1 << 192); y = uint192(x); } function safeCastTo160(uint256 x) internal pure returns (uint160 y) { require(x < 1 << 160); y = uint160(x); } function safeCastTo128(uint256 x) internal pure returns (uint128 y) { require(x < 1 << 128); y = uint128(x); } function safeCastTo96(uint256 x) internal pure returns (uint96 y) { require(x < 1 << 96); y = uint96(x); } function safeCastTo64(uint256 x) internal pure returns (uint64 y) { require(x < 1 << 64); y = uint64(x); } function safeCastTo32(uint256 x) internal pure returns (uint32 y) { require(x < 1 << 32); y = uint32(x); } function safeCastTo24(uint256 x) internal pure returns (uint24 y) { require(x < 1 << 24); y = uint24(x); } function safeCastTo8(uint256 x) internal pure returns (uint8 y) { require(x < 1 << 8); y = uint8(x); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; /// @dev Name of the NounletToken contract string constant NAME = "NounletToken"; /// @dev Version number of the NounletToken contract string constant VERSION = "1"; /// @dev The EIP-712 typehash for the contract's domain bytes32 constant DOMAIN_TYPEHASH = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); /// @dev The EIP-712 typehash for the permit struct used by the contract bytes32 constant PERMIT_TYPEHASH = keccak256( "Permit(address owner,address operator,uint256 tokenId,bool approved,uint256 nonce,uint256 deadline)" ); /// @dev The EIP-712 typehash for the permit all struct used by the contract bytes32 constant PERMIT_ALL_TYPEHASH = keccak256( "PermitAll(address owner,address operator,bool approved,uint256 nonce,uint256 deadline)" );
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`, * consuming from one or the other at each step according to the instructions given by * `proofFlags`. * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof} * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.13; import {ERC721TokenReceiver} from "@rari-capital/solmate/src/tokens/ERC721.sol"; import {ERC1155TokenReceiver} from "@rari-capital/solmate/src/tokens/ERC1155.sol"; /// @title NFT Receiver /// @author Tessera /// @notice Plugin contract for handling receipts of non-fungible tokens contract NFTReceiver is ERC721TokenReceiver, ERC1155TokenReceiver { /// @notice Handles the receipt of a single ERC721 token function onERC721Received( address, address, uint256, bytes calldata ) external virtual override returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } /// @notice Handles the receipt of a single ERC1155 token type function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual override returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } /// @notice Handles the receipt of multiple ERC1155 token types function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual override returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
{ "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@rari-capital/solmate/src/=lib/solmate/src/", "base64-sol/=lib/base64/", "base64/=lib/base64/", "clones-with-immutable-args/=lib/clones-with-immutable-args/", "ds-test/=lib/clones-with-immutable-args/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "nouns-contracts/=lib/nouns-monorepo/packages/nouns-contracts/", "nouns-monorepo/=lib/nouns-monorepo/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_royaltyBeneficiary","type":"address"},{"internalType":"address","name":"_nounsToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CreateFail","type":"error"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"UnregisteredVault","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_vault","type":"address"},{"indexed":true,"internalType":"address","name":"_token","type":"address"}],"name":"VaultDeployed","type":"event"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256[]","name":"_ids","type":"uint256[]"}],"name":"batchBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"address[]","name":"_plugins","type":"address[]"},{"internalType":"bytes4[]","name":"_selectors","type":"bytes4[]"},{"internalType":"address","name":"_descriptor","type":"address"},{"internalType":"uint256","name":"_nounId","type":"uint256"}],"name":"create","outputs":[{"internalType":"address","name":"vault","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nounsToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyBeneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_vault","type":"address"},{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"vaultToToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
61010060405234801561001157600080fd5b5060405162005f4538038062005f45833981016040819052610032916100e5565b60405161003e906100ad565b604051809103906000f08015801561005a573d6000803e3d6000fd5b506001600160a01b0316608052604051610073906100bb565b604051809103906000f08015801561008f573d6000803e3d6000fd5b506001600160a01b0390811660a05291821660e0521660c052610118565b6115908062000d0a83390190565b613cab806200229a83390190565b80516001600160a01b03811681146100e057600080fd5b919050565b600080604083850312156100f857600080fd5b610101836100c9565b915061010f602084016100c9565b90509250929050565b60805160a05160c05160e051610b9c6200016e60003960008181610169015261034d0152600081816101b7015261037701526000818161012f01526103c401526000818161019001526105950152610b9c6000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80635c60da1b116100665780635c60da1b1461012a5780637bad238014610151578063a41c385e14610164578063c45a01551461018b578063ced9481f146101b257600080fd5b806328205a931461009857806340c10f19146100c157806342d19ef4146100d657806342f495a414610117575b600080fd5b6100ab6100a636600461069a565b6101d9565b6040516100b891906106f6565b60405180910390f35b6100d46100cf36600461069a565b610268565b005b6100ff6100e4366004610729565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100ff61012536600461083a565b61031c565b6100ff7f000000000000000000000000000000000000000000000000000000000000000081565b6100d461015f366004610920565b610403565b6100ff7f000000000000000000000000000000000000000000000000000000000000000081565b6100ff7f000000000000000000000000000000000000000000000000000000000000000081565b6100ff7f000000000000000000000000000000000000000000000000000000000000000081565b6001600160a01b03828116600090815260208190526040908190205490516303a24d0760e21b81526004810184905260609291909116908190630e89341c90602401600060405180830381865afa158015610238573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261026091908101906109c6565b949350505050565b336000908152602081905260409020546001600160a01b0316806102a657604051630601cb1560e11b81523360048201526024015b60405180910390fd5b6040516394d008ef60e01b81526001600160a01b0384811660048301526024820184905260606044830152600060648301528216906394d008ef906084015b600060405180830381600087803b1580156102ff57600080fd5b505af1158015610313573d6000803e3d6000fd5b50505050505050565b6040516bffffffffffffffffffffffff1930606090811b8216602084015284811b82166034840152604883018490527f0000000000000000000000000000000000000000000000000000000000000000811b821660688401527f0000000000000000000000000000000000000000000000000000000000000000901b16607c82015260009081906103ea9060900160408051601f198184030181529190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690610469565b90506103f88782888861057b565b979650505050505050565b336000908152602081905260409020546001600160a01b03168061043c57604051630601cb1560e11b815233600482015260240161029d565b60405162f75a4760e71b81526001600160a01b03821690637bad2380906102e59086908690600401610a5a565b8051604051606160f81b81526039820160f081811b60018401526f3d81600a3d39f33d3d3d3d363d3d376160801b600384015260028401901b601383018190526560373639366160d01b6015840152601b83015262013d7360e81b601d830152606085901b6020808401919091526c5af43d3d93803e603557fd5bf360981b60348401526000939260438401929186019084604182015b6020821061051f5783518152602093840193601f199092019101610500565b835160001960208490036101000a0119908116825260f088901b91830191825286846000f098506001600160a01b03891661056d57604051631d7fde3160e31b815260040160405180910390fd5b505050505050505092915050565b6040516389c9caa360e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906389c9caa3906105ce90889087908790600401610ab0565b6020604051808303816000875af11580156105ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106119190610b49565b6001600160a01b0381811660008181526020819052604080822080546001600160a01b031916948a16948517905551939450919290917f09d75e12e349f79020715b0ea7b2c707e8acf1889b6d6f1337fce7f4e1b9e5c791a3949350505050565b6001600160a01b038116811461068757600080fd5b50565b803561069581610672565b919050565b600080604083850312156106ad57600080fd5b82356106b881610672565b946020939093013593505050565b60005b838110156106e15781810151838201526020016106c9565b838111156106f0576000848401525b50505050565b60208152600082518060208401526107158160408501602087016106c6565b601f01601f19169190910160400192915050565b60006020828403121561073b57600080fd5b813561074681610672565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561078c5761078c61074d565b604052919050565b600067ffffffffffffffff8211156107ae576107ae61074d565b5060051b60200190565b600082601f8301126107c957600080fd5b813560206107de6107d983610794565b610763565b82815260059290921b840181019181810190868411156107fd57600080fd5b8286015b8481101561082f5780356001600160e01b0319811681146108225760008081fd5b8352918301918301610801565b509695505050505050565b600080600080600060a0868803121561085257600080fd5b8535945060208087013567ffffffffffffffff8082111561087257600080fd5b818901915089601f83011261088657600080fd5b81356108946107d982610794565b81815260059190911b8301840190848101908c8311156108b357600080fd5b938501935b828510156108da5784356108cb81610672565b825293850193908501906108b8565b9850505060408901359250808311156108f257600080fd5b5050610900888289016107b8565b93505061090f6060870161068a565b949793965091946080013592915050565b6000806040838503121561093357600080fd5b823561093e81610672565b915060208381013567ffffffffffffffff81111561095b57600080fd5b8401601f8101861361096c57600080fd5b803561097a6107d982610794565b81815260059190911b8201830190838101908883111561099957600080fd5b928401925b828410156109b75783358252928401929084019061099e565b80955050505050509250929050565b6000602082840312156109d857600080fd5b815167ffffffffffffffff808211156109f057600080fd5b818401915084601f830112610a0457600080fd5b815181811115610a1657610a1661074d565b610a29601f8201601f1916602001610763565b9150808252856020828501011115610a4057600080fd5b610a518160208401602086016106c6565b50949350505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b81811015610aa357845183529383019391830191600101610a87565b5090979650505050505050565b6000606082018583526020606081850152818651808452608086019150828801935060005b81811015610afa5784516001600160a01b031683529383019391830191600101610ad5565b50508481036040860152855180825290820192508186019060005b81811015610b3b5782516001600160e01b03191685529383019391830191600101610b15565b509298975050505050505050565b600060208284031215610b5b57600080fd5b81516107468161067256fea2646970667358221220494a7d6d15dcbd19f3650c486f39b7c960455246c7f18d8e065a639e5a189ef864736f6c634300080d0033608060405234801561001057600080fd5b5060405161001d9061005f565b604051809103906000f080158015610039573d6000803e3d6000fd5b50600080546001600160a01b0319166001600160a01b039290921691909117905561006c565b610de7806107a983390190565b61072e8061007b6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806337a6be161461005c5780635c60da1b146100985780637d9ec9ff146100c357806389c9caa3146100d6578063f6133770146100e9575b600080fd5b61008561006a3660046104c1565b6001600160a01b031660009081526001602052604090205490565b6040519081526020015b60405180910390f35b6000546100ab906001600160a01b031681565b6040516001600160a01b03909116815260200161008f565b6100ab6100d13660046104e3565b6100fc565b6100ab6100e4366004610559565b6101ef565b6100ab6100f73660046105d3565b610209565b6001600160a01b0382166000818152600160209081526040808320548151808401959095528482015280518085038201815260608086019092528051920191909120608084018590526001600160601b031986831b811660a08601523090921b90911660b48401529091829081906101939060c80160408051601f198184030181529190526000546001600160a01b03169061036f565b9020604080516001600160f81b03196020808301919091523060601b6001600160601b03191660218301526035820196909652605580820193909352815180820390930183526075019052805193019290922095945050505050565b60006101ff863387878787610209565b9695505050505050565b326000818152600160209081526040808320548151808401959095528482018190528151808603830181526060808701845281519190940120608086018c90526001600160601b03198b851b811660a08801523090941b90931660b4860152815180860360a801815260c8909501909152825492939092610294906001600160a01b0316838361045a565b3260009081526001602081905260409182902090860190555163167937cf60e21b81529094506001600160a01b038516906359e4df3c906102df908b908b908b908b9060040161065d565b600060405180830381600087803b1580156102f957600080fd5b505af115801561030d573d6000803e3d6000fd5b505060408051868152602081018690526001600160a01b03888116828401529151918d16935033925032917fc836d877ec2901a6c3f2e17c94bf617570a3664e9c75f6a9c5e48696cde1343d9181900360600190a45050509695505050505050565b8051604051613d6160f01b8152603a820160f081811b6002848101919091526680600b3d3981f360c81b600485015264363d3d376160d81b600b8501528401901b6010830181905268603836393d3d3d366160b81b6012840152601b83015262013d7360e81b601d830152606085901b6020808401919091526e5af43d82803e903d91603657fd5bf360881b603484015291926045810192909190850182604386015b602082106104315782518152602092830192601f199092019101610412565b915160001960208390036101000a011916825260f09390931b9201919091525090939092509050565b6000806000610469868561036f565b915091508481836000f592506001600160a01b03831661049c57604051631d7fde3160e31b815260040160405180910390fd5b50509392505050565b80356001600160a01b03811681146104bc57600080fd5b919050565b6000602082840312156104d357600080fd5b6104dc826104a5565b9392505050565b600080604083850312156104f657600080fd5b6104ff836104a5565b946020939093013593505050565b60008083601f84011261051f57600080fd5b50813567ffffffffffffffff81111561053757600080fd5b6020830191508360208260051b850101111561055257600080fd5b9250929050565b60008060008060006060868803121561057157600080fd5b85359450602086013567ffffffffffffffff8082111561059057600080fd5b61059c89838a0161050d565b909650945060408801359150808211156105b557600080fd5b506105c28882890161050d565b969995985093965092949392505050565b600080600080600080608087890312156105ec57600080fd5b863595506105fc602088016104a5565b9450604087013567ffffffffffffffff8082111561061957600080fd5b6106258a838b0161050d565b9096509450606089013591508082111561063e57600080fd5b5061064b89828a0161050d565b979a9699509497509295939492505050565b6040808252810184905260008560608301825b8781101561069e576001600160a01b03610689846104a5565b16825260209283019290910190600101610670565b5083810360208581019190915285825291508590820160005b868110156106eb5782356001600160e01b031981168082146106d857600080fd5b83525091830191908301906001016106b7565b509897505050505050505056fea26469706673582212203e9a1fae09801964d07c9a0ead099f7dc2e3a71830cf231ba7b345163bc3cac264736f6c634300080d003360a060405234801561001057600080fd5b5030608052608051610db7610030600039600061028e0152610db76000f3fe60806040526004361061008a5760003560e01c806359e4df3c1161005957806359e4df3c146101b2578063601b8af3146101d45780636b039451146101f5578063bc197c811461022b578063f23a6e611461025a57610091565b8063117803e314610103578063150b7a02146101355780632dd310001461017a57806351e75e8b1461018f57610091565b3661009157005b600036606082356001600160e01b031916156100f857600080356001600160e01b0319168152602081905260409020546001600160a01b0316806100e8576040516301b1e26160e21b815260040160405180910390fd5b6100f3818585610287565b925050505b915050805190602001f35b34801561010f57600080fd5b506101186103e0565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561014157600080fd5b506101616101503660046107d4565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161012c565b34801561018657600080fd5b506101186103f1565b34801561019b57600080fd5b506101a46103fd565b60405190815260200161012c565b3480156101be57600080fd5b506101d26101cd366004610938565b610409565b005b6101e76101e2366004610a3d565b6105ad565b60405161012c929190610aad565b34801561020157600080fd5b50610118610210366004610b0c565b6000602081905290815260409020546001600160a01b031681565b34801561023757600080fd5b50610161610246366004610b27565b63bc197c8160e01b98975050505050505050565b34801561026657600080fd5b50610161610275366004610be2565b63f23a6e6160e01b9695505050505050565b60006060307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316036102fd5760405162461bcd60e51b81526020600482015260126024820152711bdb9b1e4819195b1959d85d194818d85b1b60721b60448201526064015b60405180910390fd5b846001600160a01b03163b600003610333576040516305fc177f60e01b81526001600160a01b03861660048201526024016102f4565b60006113885a6103439190610c70565b9050856001600160a01b0316818686604051610360929190610c87565b6000604051808303818686f4925050503d806000811461039c576040519150601f19603f3d011682016040523d82523d6000602084013e6103a1565b606091505b509093509150826103d75781516000036103ce5760405163f21e646b60e01b815260040160405180910390fd5b6103d78261068a565b50935093915050565b60006103ec6020610693565b905090565b60006103ec6034610693565b60006103ec60006106b8565b60006104136103e0565b90506001600160a01b0381163314610466573361042e6103f1565b6001600160a01b03161461046657604051631194af8760e11b81526001600160a01b03821660048201523360248201526044016102f4565b825182516000818314610496576040516302a7fbbb60e21b815260048101849052602481018390526044016102f4565b60005b8281101561056b578581815181106104b3576104b3610c97565b6020908102919091018101516001600160e01b031981166000908152918290526040909120549092506001600160a01b03161561050f576040516312ba286f60e01b81526001600160e01b0319831660048201526024016102f4565b86818151811061052157610521610c97565b6020908102919091018101516001600160e01b03198416600090815291829052604090912080546001600160a01b0319166001600160a01b03909216919091179055600101610499565b7fa5cc5eda71539c8269d42d17b901a4f0ad8b0049bc072740431f853ee3bebfbe868860405161059c929190610cad565b60405180910390a150505050505050565b6000606060008635905060003389836040516020016105ce93929190610d3b565b60405160208183030381529060405280519060200120905061062c86868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061062692506103fd915050565b836106da565b61066f576106386103e0565b6001600160a01b0316336001600160a01b03161461066f57338983604051632054e00b60e21b81526004016102f493929190610d3b565b61067a898989610287565b909a909950975050505050505050565b80518082602001fd5b6000806106aa600119368181013560f01c90030190565b929092013560601c92915050565b6000806106cf600119368181013560f01c90030190565b929092013592915050565b6000826106e785846106f0565b14949350505050565b600081815b8451811015610735576107218286838151811061071457610714610c97565b602002602001015161073d565b91508061072d81610d68565b9150506106f5565b509392505050565b6000818310610759576000828152602084905260409020610768565b60008381526020839052604090205b9392505050565b80356001600160a01b038116811461078657600080fd5b919050565b60008083601f84011261079d57600080fd5b50813567ffffffffffffffff8111156107b557600080fd5b6020830191508360208285010111156107cd57600080fd5b9250929050565b6000806000806000608086880312156107ec57600080fd5b6107f58661076f565b94506108036020870161076f565b935060408601359250606086013567ffffffffffffffff81111561082657600080fd5b6108328882890161078b565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561088257610882610843565b604052919050565b600067ffffffffffffffff8211156108a4576108a4610843565b5060051b60200190565b80356001600160e01b03198116811461078657600080fd5b600082601f8301126108d757600080fd5b813560206108ec6108e78361088a565b610859565b82815260059290921b8401810191818101908684111561090b57600080fd5b8286015b8481101561092d57610920816108ae565b835291830191830161090f565b509695505050505050565b6000806040838503121561094b57600080fd5b823567ffffffffffffffff8082111561096357600080fd5b818501915085601f83011261097757600080fd5b813560206109876108e78361088a565b82815260059290921b840181019181810190898411156109a657600080fd5b948201945b838610156109cb576109bc8661076f565b825294820194908201906109ab565b965050860135925050808211156109e157600080fd5b506109ee858286016108c6565b9150509250929050565b60008083601f840112610a0a57600080fd5b50813567ffffffffffffffff811115610a2257600080fd5b6020830191508360208260051b85010111156107cd57600080fd5b600080600080600060608688031215610a5557600080fd5b610a5e8661076f565b9450602086013567ffffffffffffffff80821115610a7b57600080fd5b610a8789838a0161078b565b90965094506040880135915080821115610aa057600080fd5b50610832888289016109f8565b821515815260006020604081840152835180604085015260005b81811015610ae357858101830151858201606001528201610ac7565b81811115610af5576000606083870101525b50601f01601f191692909201606001949350505050565b600060208284031215610b1e57600080fd5b610768826108ae565b60008060008060008060008060a0898b031215610b4357600080fd5b610b4c8961076f565b9750610b5a60208a0161076f565b9650604089013567ffffffffffffffff80821115610b7757600080fd5b610b838c838d016109f8565b909850965060608b0135915080821115610b9c57600080fd5b610ba88c838d016109f8565b909650945060808b0135915080821115610bc157600080fd5b50610bce8b828c0161078b565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215610bfb57600080fd5b610c048761076f565b9550610c126020880161076f565b94506040870135935060608701359250608087013567ffffffffffffffff811115610c3c57600080fd5b610c4889828a0161078b565b979a9699509497509295939492505050565b634e487b7160e01b600052601160045260246000fd5b600082821015610c8257610c82610c5a565b500390565b8183823760009101908152919050565b634e487b7160e01b600052603260045260246000fd5b604080825283519082018190526000906020906060840190828701845b82811015610cf05781516001600160e01b03191684529284019290840190600101610cca565b5050508381038285015284518082528583019183019060005b81811015610d2e5783516001600160a01b031683529284019291840191600101610d09565b5090979650505050505050565b6001600160a01b0393841681529190921660208201526001600160e01b0319909116604082015260600190565b600060018201610d7a57610d7a610c5a565b506001019056fea26469706673582212204cfcd32bda90c2285b16c6c2d1358bf1d5f223b33f99f063ecea320ca2fb3f3164736f6c634300080d0033608060405234801561001057600080fd5b50613c8b806100206000396000f3fe608060405234801561001057600080fd5b50600436106102475760003560e01c80637bad23801161013b578063e5af48d8116100b8578063f0503e801161007c578063f0503e801461063b578063f06e6c9c146106c9578063f1127ed8146106dc578063f242432a14610743578063f72c86891461075657600080fd5b8063e5af48d81461059a578063e6d956bd146105ce578063e8a3d485146105d6578063e9580e91146105de578063e985e9c51461061057600080fd5b8063a22cb465116100ff578063a22cb4651461054b578063b4b5ea571461055e578063cdcd897e14610571578063cfa8fb4214610579578063d5abeb011461058c57600080fd5b80637bad2380146104f55780637ecebe00146105085780638da5cb5b1461052857806394d008ef146105305780639aad008b1461054357600080fd5b8063424611c3116101c9578063605105f01161018d578063605105f0146104635780636352211e1461047657806365d505931461049f5780636fcfff45146104a7578063782d6fe1146104e257600080fd5b8063424611c3146103b45780634e1273f41461041557806352ce836a14610435578063587cde1e1461043d5780635c19a95c1461045057600080fd5b806325d95e5b1161021057806325d95e5b146103175780632a55205a146103405780632ccd9ed4146103725780632eb2c2d614610387578063313ce5671461039a57600080fd5b8062fdd58e1461024c57806301ffc9a7146102895780630e89341c146102ac57806318160ddd146102cc57806322fd1393146102f7575b600080fd5b61027661025a366004612ecb565b6000908152600160205260409020546001600160a01b03161490565b6040519081526020015b60405180910390f35b61029c610297366004612f0b565b610769565b6040519015158152602001610280565b6102bf6102ba366004612f28565b6107bb565b6040516102809190612f99565b6002546102df906001600160601b031681565b6040516001600160601b039091168152602001610280565b6102ff6108b6565b6040516001600160a01b039091168152602001610280565b6102df610325366004612fac565b6004602052600090815260409020546001600160601b031681565b61035361034e366004612fc7565b6108c7565b604080516001600160a01b039093168352602083019190915201610280565b61038561038036600461300a565b6108f5565b005b610385610395366004613113565b610ac2565b6103a2600081565b60405160ff9091168152602001610280565b6103c76103c2366004612f28565b610adc565b6040516102809190815165ffffffffffff9081168252602080840151821690830152604080840151821690830152606080840151821690830152608092830151169181019190915260a00190565b6104286104233660046131ce565b610df1565b6040516102809190613275565b610276610eef565b6102ff61044b366004612fac565b610efb565b61038561045e366004612fac565b610f2d565b610385610471366004613288565b610f3a565b6102ff610484366004612f28565b6001602052600090815260409020546001600160a01b031681565b6102ff610fda565b6104cd6104b5366004612fac565b60056020526000908152604090205463ffffffff1681565b60405163ffffffff9091168152602001610280565b6102766104f0366004612ecb565b610fe6565b610385610503366004613300565b61125a565b610276610516366004612fac565b60076020526000908152604090205481565b6102ff6112df565b61038561053e366004613353565b6112e9565b6102ff61142b565b6103856105593660046133a1565b611437565b6102df61056c366004612fac565b6114a1565b6102df60c881565b6103856105873660046133cb565b611520565b6102df6001600160601b0381565b61029c6105a836600461343c565b600960209081526000938452604080852082529284528284209052825290205460ff1681565b6102ff611697565b6102bf6116a3565b6102df6105ec366004612fac565b6001600160a01b03166000908152600460205260409020546001600160601b031690565b61029c61061e366004613478565b600060208181529281526040808220909352908152205460ff1681565b610690610649366004612f28565b60086020526000908152604090205465ffffffffffff8082169166010000000000008104821691600160601b8204811691600160901b8104821691600160c01b9091041685565b6040805165ffffffffffff968716815294861660208601529285169284019290925283166060830152909116608082015260a001610280565b6103856106d7366004613113565b6116d4565b61071f6106ea3660046134a2565b600660209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6040805163ffffffff90931683526001600160601b03909116602083015201610280565b610385610751366004613288565b6116e4565b6103856107643660046134e2565b61177c565b60006301ffc9a760e01b6001600160e01b03198316148061079a5750636cdb3d1360e11b6001600160e01b03198316145b806107b5575063152a902d60e11b6001600160e01b03198316145b92915050565b606060006107cf6107ca610eef565b6117f5565b905060006107dc846117f5565b6040516020016107ec919061351e565b6040516020818303038152906040529050600082604051602001610810919061354f565b60405160208183030381529060405290506108296108b6565b6000868152600860205260409081902090516387db11bd60e01b81526001600160a01b0392909216916387db11bd9161086891869186916004016135b6565b600060405180830381865afa158015610885573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108ad919081019061363b565b95945050505050565b60006108c260146118fe565b905090565b6000806108d2610fda565b91506127106108e260c8856136fe565b6108ec9190613733565b90509250929050565b8342111561092457604051630f88f04960e41b8152426004820152602481018590526044015b60405180910390fd5b60006109338989898989611923565b905060006109836109426119d6565b8360405161190160f01b6020820152602281018390526042810182905260009060620160405160208183030381529060405280519060200120905092915050565b6040805160008082526020820180845284905260ff89169282019290925260608101879052608081018690529192509060019060a0016020604051602081039080840390855afa1580156109db573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580610a1057508a6001600160a01b0316816001600160a01b031614155b15610a41576040516310b5d43760e21b81526001600160a01b0380831660048301528c16602482015260440161091b565b5050506001600160a01b038881166000818152600960209081526040808320948c168084529482528083208b8452825291829020805460ff19168a151590811790915582518b8152918201527f9fe4c80ed54641e7463c240ea1212aa79c810413295452fae0729f7056107677910160405180910390a35050505050505050565b610ad28888888888888888611aa9565b5050505050505050565b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905290610b0f6108b6565b90506000610b1b611697565b6001600160a01b031663f0503e80610b31610eef565b6040518263ffffffff1660e01b8152600401610b4f91815260200190565b60a060405180830381865afa158015610b6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b90919061375d565b90506000610b9f6001436137eb565b604080519140602083015281018690526060016040516020818303038152906040528051906020012060001c90506000836001600160a01b0316634531c0a86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c319190613802565b90506000846001600160a01b031663eba818066040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c979190613802565b90506000856001600160a01b0316634daebac26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfd9190613802565b90506000866001600160a01b0316634479cef26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d639190613802565b90506040518060a001604052808587610d7c919061381b565b65ffffffffffff168152602001610d9785603089901c61381b565b65ffffffffffff168152602001610db284606089901c61381b565b65ffffffffffff90811682526060890151166020820152604001610dda8360c089901c61381b565b65ffffffffffff1690529998505050505050505050565b6060838214610e125760405162461bcd60e51b815260040161091b9061382f565b8367ffffffffffffffff811115610e2b57610e2b613625565b604051908082528060200260200182016040528015610e54578160200160208202803683370190505b50905060005b84811015610ee657610ec1868683818110610e7757610e77613858565b9050602002016020810190610e8c9190612fac565b858584818110610e9e57610e9e613858565b905060200201356000908152600160205260409020546001600160a01b03161490565b828281518110610ed357610ed3613858565b6020908102919091010152600101610e5a565b50949350505050565b60006108c26028611b8f565b6001600160a01b038082166000908152600360205260408120549091168015610f245780610f26565b825b9392505050565b610f373382611bb1565b50565b336001600160a01b0387161480610f7257506001600160a01b03861660009081526020818152604080832033845290915290205460ff165b80610fa857506001600160a01b0386166000908152600960209081526040808320338452825280832087845290915290205460ff165b610fc45760405162461bcd60e51b815260040161091b9061386e565b610fd2868686868686611c5b565b505050505050565b60006108c260486118fe565b60008143116110265760405162461bcd60e51b815260206004820152600c60248201526b15539111551154935253915160a21b604482015260640161091b565b6001600160a01b03831660009081526005602052604081205463ffffffff16908190036110575760009150506107b5565b6001600160a01b0384166000908152600660205260408120849161107c600185613896565b63ffffffff908116825260208201929092526040016000205416116110ef576001600160a01b0384166000908152600660205260408120906110bf600184613896565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b031691506107b59050565b6001600160a01b038416600090815260066020908152604080832083805290915290205463ffffffff1683101561112a5760009150506107b5565b600080611138600184613896565b90505b8163ffffffff168163ffffffff161115611215576000600261115d8484613896565b61116791906138bb565b6111719083613896565b6001600160a01b038816600090815260066020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b0316918101919091529192508790036111e757602001516001600160601b031694506107b59350505050565b805163ffffffff16871161120857611200600183613896565b92508261120d565b819350835b50505061113b565b506001600160a01b038516600090815260066020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b61126261142b565b336001600160a01b0382161461129c5760405163708986dd60e11b81526001600160a01b038216600482015233602482015260440161091b565b6112d984848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250611d2092505050565b50505050565b60006108c2610fda565b6112f161142b565b336001600160a01b0382161461132b5760405163708986dd60e11b81526001600160a01b038216600482015233602482015260440161091b565b61133484610adc565b600085815260086020908152604091829020835181548584015186860151606088015160809098015165ffffffffffff9485166bffffffffffffffffffffffff1990941693909317660100000000000092851692909202919091176bffffffffffffffffffffffff60601b1916600160601b9184169190910265ffffffffffff60901b191617600160901b968316969096029590951765ffffffffffff60c01b1916600160c01b9190951602939093179092558051601f850183900483028101830190915283815261142491879187918790879081908401838280828437600092019190915250611dde92505050565b5050505050565b60006108c260006118fe565b336000818152602081815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6001600160a01b03811660009081526005602052604081205463ffffffff168082036114ce576000610f26565b6001600160a01b0383166000908152600660205260408120906114f2600184613896565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03169392505050565b8342111561154a57604051630f88f04960e41b81524260048201526024810185905260440161091b565b600061155888888888611e7d565b905060006115676109426119d6565b6040805160008082526020820180845284905260ff89169282019290925260608101879052608081018690529192509060019060a0016020604051602081039080840390855afa1580156115bf573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615806115f45750896001600160a01b0316816001600160a01b031614155b15611625576040516310b5d43760e21b81526001600160a01b0380831660048301528b16602482015260440161091b565b5050506001600160a01b03878116600081815260208181526040808320948b1680845294825291829020805460ff19168a151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050505050565b60006108c2605c6118fe565b60606116b06107ca610eef565b6040516020016116c091906138de565b604051602081830303815290604052905090565b610ad28888888888888888611f28565b336001600160a01b038716148061171c57506001600160a01b03861660009081526020818152604080832033845290915290205460ff165b8061175257506001600160a01b0386166000908152600960209081526040808320338452825280832087845290915290205460ff165b61176e5760405162461bcd60e51b815260040161091b9061386e565b610fd2868686868686611ff4565b3360008181526009602090815260408083206001600160a01b038816808552908352818420878552835292819020805460ff19168615159081179091558151878152928301529192917f9fe4c80ed54641e7463c240ea1212aa79c810413295452fae0729f7056107677910160405180910390a3505050565b60608160000361181c5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115611846578061183081613923565b915061183f9050600a83613733565b9150611820565b60008167ffffffffffffffff81111561186157611861613625565b6040519080825280601f01601f19166020018201604052801561188b576020820181803683370190505b5090505b84156118f6576118a06001836137eb565b91506118ad600a8661381b565b6118b890603061393c565b60f81b8183815181106118cd576118cd613858565b60200101906001600160f81b031916908160001a9053506118ef600a86613733565b945061188f565b949350505050565b600080611915600119368181013560f01c90030190565b929092013560601c92915050565b6001600160a01b038516600090815260076020526040812080547faff3e7017d0a41834e125c9c80495a73609c1859f670a0c126d99a1acf4b4e689188918891889188918761197183613923565b909155506040805160208101979097526001600160a01b03958616908701529390921660608501526080840152151560a083015260c082015260e081018390526101000160405160208183030381529060405280519060200120905095945050505050565b604080518082018252600c81526b2737bab73632ba2a37b5b2b760a11b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f858e7172149b3b6c6900fc4a783983cd40694c091bd06cbafdf9a9ad15fcd669818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b6000611ab4866120a9565b6001600160a01b038a16600090815260046020526040812080549293508392909190611aea9084906001600160601b0316613954565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038a16600090815260046020526040812080548594509092611b3591859116613974565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550611b74611b658a610efb565b611b6e8a610efb565b836120bf565b611b84898989898989898961223c565b505050505050505050565b600080611ba6600119368181013560f01c90030190565b929092013592915050565b6000611bbc83610efb565b6001600160a01b03848116600090815260036020908152604080832080546001600160a01b031916948816949094179093556004905220549091506001600160601b0316611c0b8284836120bf565b826001600160a01b0316826001600160a01b0316856001600160a01b03167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a450505050565b6001600160a01b038616600090815260046020526040812080546001600160601b031691611c888361399f565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038716600090815260046020526040812080549092169250611cd0836139c2565b91906101000a8154816001600160601b0302191690836001600160601b0316021790555050611d11611d0187610efb565b611d0a87610efb565b60016120bf565b610fd2868686600186866124c9565b6000611d2c82516120a9565b600280549192508291600090611d4c9084906001600160601b0316613954565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038516600090815260046020526040812080548594509092611d9791859116613954565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550611dcf611dc784610efb565b6000836120bf565b611dd983836125ea565b505050565b600280546001600160601b0316906000611df7836139c2565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038516600090815260046020526040812080549092169250611e3f836139c2565b91906101000a8154816001600160601b0302191690836001600160601b0316021790555050611e726000611d0a85610efb565b611dd9838383612785565b6001600160a01b038416600090815260076020526040812080547f200d2483757e19728fc8a3511298158c1b74dd131c7be00c4904e11665b42cd1918791879187919086611eca83613923565b909155506040805160208101969096526001600160a01b03948516908601529290911660608401521515608083015260a082015260c0810183905260e001604051602081830303815290604052805190602001209050949350505050565b6000611f33866120a9565b6001600160a01b038a16600090815260046020526040812080549293508392909190611f699084906001600160601b0316613954565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038a16600090815260046020526040812080548594509092611fb491859116613974565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550611fe4611b658a610efb565b611b84898989898989898961291c565b6001600160a01b038616600090815260046020526040812080546001600160601b0316916120218361399f565b82546101009290920a6001600160601b038181021990931691831602179091556001600160a01b038716600090815260046020526040812080549092169250612069836139c2565b91906101000a8154816001600160601b0302191690836001600160601b031602179055505061209a611d0187610efb565b610fd286868660018686612ac8565b6000600160601b82106120bb57600080fd5b5090565b816001600160a01b0316836001600160a01b0316141580156120ea57506000816001600160601b0316115b15611dd9576001600160a01b03831615612197576001600160a01b03831660009081526005602052604081205463ffffffff1680820361212b576000612177565b6001600160a01b03851660009081526006602052604081209061214f600184613896565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b915060006121858484613954565b905061219386838584612cbe565b5050505b6001600160a01b03821615611dd9576001600160a01b03821660009081526005602052604081205463ffffffff16908181036121d4576000612220565b6001600160a01b0384166000908152600660205260408120906121f8600185613896565b63ffffffff168152602081019190915260400160002054600160201b90046001600160601b03165b9050600061222e8483613974565b9050610fd285848484612cbe565b84831461225b5760405162461bcd60e51b815260040161091b9061382f565b336001600160a01b038916148061229357506001600160a01b03881660009081526020818152604080832033845290915290205460ff165b6122af5760405162461bcd60e51b815260040161091b9061386e565b60008060005b87811015612380578888828181106122cf576122cf613858565b9050602002013592508686828181106122ea576122ea613858565b600086815260016020908152604090912054910292909201359350506001600160a01b038c81169116146123305760405162461bcd60e51b815260040161091b906139e8565b816001146123505760405162461bcd60e51b815260040161091b90613a0c565b600083815260016020819052604090912080546001600160a01b0319166001600160a01b038d16179055016122b5565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b6040516123d49493929190613a6a565b60405180910390a46001600160a01b0389163b156124975760405163bc197c8160e01b808252906001600160a01b038b169063bc197c81906124289033908f908e908e908e908e908e908e90600401613aba565b6020604051808303816000875af1158015612447573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246b9190613b1e565b6001600160e01b031916146124925760405162461bcd60e51b815260040161091b90613b3b565b6124bd565b6001600160a01b0389166124bd5760405162461bcd60e51b815260040161091b90613b65565b50505050505050505050565b336001600160a01b038716148061250157506001600160a01b03861660009081526020818152604080832033845290915290205460ff165b61251d5760405162461bcd60e51b815260040161091b9061386e565b6000848152600160205260409020546001600160a01b038781169116146125565760405162461bcd60e51b815260040161091b906139e8565b826001146125765760405162461bcd60e51b815260040161091b90613a0c565b60008481526001602090815260409182902080546001600160a01b0319166001600160a01b038981169182179092558351888152928301879052929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a4505050505050565b6001600160a01b03821661262f5760405162461bcd60e51b815260206004820152600c60248201526b494e56414c49445f46524f4d60a01b604482015260640161091b565b805160008167ffffffffffffffff81111561264c5761264c613625565b604051908082528060200260200182016040528015612675578160200160208202803683370190505b5090506000805b838110156127255784818151811061269657612696613858565b602090810291909101810151600081815260019092526040909120549092506001600160a01b038781169116146126df5760405162461bcd60e51b815260040161091b906139e8565b600082815260016020819052604090912080546001600160a01b0319169055835184908390811061271257612712613858565b602090810291909101015260010161267c565b5060006001600160a01b0316856001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8786604051612776929190613b90565b60405180910390a45050505050565b6000828152600160205260409020546001600160a01b0316156127db5760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b604482015260640161091b565b600082815260016020818152604080842080546001600160a01b0319166001600160a01b03891690811790915581518781529283019390935291929133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0383163b156128f65760405163f23a6e6160e01b808252906001600160a01b0385169063f23a6e619061288c90339060009088906001908990600401613bb5565b6020604051808303816000875af11580156128ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128cf9190613b1e565b6001600160e01b03191614611dd95760405162461bcd60e51b815260040161091b90613b3b565b6001600160a01b038316611dd95760405162461bcd60e51b815260040161091b90613b65565b84831461293b5760405162461bcd60e51b815260040161091b9061382f565b336001600160a01b038916148061297357506001600160a01b03881660009081526020818152604080832033845290915290205460ff165b61298f5760405162461bcd60e51b815260040161091b9061386e565b60008060005b87811015612a60578888828181106129af576129af613858565b9050602002013592508686828181106129ca576129ca613858565b600086815260016020908152604090912054910292909201359350506001600160a01b038c8116911614612a105760405162461bcd60e51b815260040161091b906139e8565b81600114612a305760405162461bcd60e51b815260040161091b90613a0c565b600083815260016020819052604090912080546001600160a01b0319166001600160a01b038d1617905501612995565b50886001600160a01b03168a6001600160a01b0316336001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb8b8b8b8b604051612ab49493929190613a6a565b60405180910390a450505050505050505050565b336001600160a01b0387161480612b0057506001600160a01b03861660009081526020818152604080832033845290915290205460ff165b612b1c5760405162461bcd60e51b815260040161091b9061386e565b6000848152600160205260409020546001600160a01b03878116911614612b555760405162461bcd60e51b815260040161091b906139e8565b82600114612b755760405162461bcd60e51b815260040161091b90613a0c565b60008481526001602090815260409182902080546001600160a01b0319166001600160a01b038981169182179092558351888152928301879052929089169133917fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62910160405180910390a46001600160a01b0385163b15612c985760405163f23a6e6160e01b808252906001600160a01b0387169063f23a6e6190612c299033908b908a908a908a908a90600401613bef565b6020604051808303816000875af1158015612c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6c9190613b1e565b6001600160e01b03191614612c935760405162461bcd60e51b815260040161091b90613b3b565b610fd2565b6001600160a01b038516610fd25760405162461bcd60e51b815260040161091b90613b65565b6000612cc943612e9d565b905060008463ffffffff16118015612d2357506001600160a01b038516600090815260066020526040812063ffffffff831691612d07600188613896565b63ffffffff908116825260208201929092526040016000205416145b15612d97576001600160a01b03851660009081526006602052604081208391612d4d600188613896565b63ffffffff168152602081019190915260400160002080546001600160601b0392909216600160201b026fffffffffffffffffffffffff0000000019909216919091179055612e48565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000908152600682528681208b8616825290915294909420925183549451909116600160201b026fffffffffffffffffffffffffffffffff19909416911617919091179055612e17846001613c36565b6001600160a01b0386166000908152600560205260409020805463ffffffff191663ffffffff929092169190911790555b604080516001600160601b038086168252841660208201526001600160a01b038716917fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724910160405180910390a25050505050565b6000600160201b82106120bb57600080fd5b80356001600160a01b0381168114612ec657600080fd5b919050565b60008060408385031215612ede57600080fd5b612ee783612eaf565b946020939093013593505050565b6001600160e01b031981168114610f3757600080fd5b600060208284031215612f1d57600080fd5b8135610f2681612ef5565b600060208284031215612f3a57600080fd5b5035919050565b60005b83811015612f5c578181015183820152602001612f44565b838111156112d95750506000910152565b60008151808452612f85816020860160208601612f41565b601f01601f19169290920160200192915050565b602081526000610f266020830184612f6d565b600060208284031215612fbe57600080fd5b610f2682612eaf565b60008060408385031215612fda57600080fd5b50508035926020909101359150565b80358015158114612ec657600080fd5b803560ff81168114612ec657600080fd5b600080600080600080600080610100898b03121561302757600080fd5b61303089612eaf565b975061303e60208a01612eaf565b96506040890135955061305360608a01612fe9565b94506080890135935061306860a08a01612ff9565b925060c0890135915060e089013590509295985092959890939650565b60008083601f84011261309757600080fd5b50813567ffffffffffffffff8111156130af57600080fd5b6020830191508360208260051b85010111156130ca57600080fd5b9250929050565b60008083601f8401126130e357600080fd5b50813567ffffffffffffffff8111156130fb57600080fd5b6020830191508360208285010111156130ca57600080fd5b60008060008060008060008060a0898b03121561312f57600080fd5b61313889612eaf565b975061314660208a01612eaf565b9650604089013567ffffffffffffffff8082111561316357600080fd5b61316f8c838d01613085565b909850965060608b013591508082111561318857600080fd5b6131948c838d01613085565b909650945060808b01359150808211156131ad57600080fd5b506131ba8b828c016130d1565b999c989b5096995094979396929594505050565b600080600080604085870312156131e457600080fd5b843567ffffffffffffffff808211156131fc57600080fd5b61320888838901613085565b9096509450602087013591508082111561322157600080fd5b5061322e87828801613085565b95989497509550505050565b600081518084526020808501945080840160005b8381101561326a5781518752958201959082019060010161324e565b509495945050505050565b602081526000610f26602083018461323a565b60008060008060008060a087890312156132a157600080fd5b6132aa87612eaf565b95506132b860208801612eaf565b94506040870135935060608701359250608087013567ffffffffffffffff8111156132e257600080fd5b6132ee89828a016130d1565b979a9699509497509295939492505050565b60008060006040848603121561331557600080fd5b61331e84612eaf565b9250602084013567ffffffffffffffff81111561333a57600080fd5b61334686828701613085565b9497909650939450505050565b6000806000806060858703121561336957600080fd5b61337285612eaf565b935060208501359250604085013567ffffffffffffffff81111561339557600080fd5b61322e878288016130d1565b600080604083850312156133b457600080fd5b6133bd83612eaf565b91506108ec60208401612fe9565b600080600080600080600060e0888a0312156133e657600080fd5b6133ef88612eaf565b96506133fd60208901612eaf565b955061340b60408901612fe9565b94506060880135935061342060808901612ff9565b925060a0880135915060c0880135905092959891949750929550565b60008060006060848603121561345157600080fd5b61345a84612eaf565b925061346860208501612eaf565b9150604084013590509250925092565b6000806040838503121561348b57600080fd5b61349483612eaf565b91506108ec60208401612eaf565b600080604083850312156134b557600080fd5b6134be83612eaf565b9150602083013563ffffffff811681146134d757600080fd5b809150509250929050565b6000806000606084860312156134f757600080fd5b61350084612eaf565b92506020840135915061351560408501612fe9565b90509250925092565b684e6f756e6c6574202360b81b815260008251613542816009850160208701612f41565b9190910160090192915050565b6402737bab7160dd1b81526000825161356f816005850160208701612f41565b7f20697320636f6c6c6563746976656c79206f776e6564206279206120313030206005939091019283015250696d656d6265722044414f60b01b6025820152602f01919050565b60e0815260006135c960e0830186612f6d565b82810360208401526135db8186612f6d565b915050825465ffffffffffff8082166040850152808260301c166060850152808260601c166080850152808260901c1660a0850152808260c01c1660c08501525050949350505050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561364d57600080fd5b815167ffffffffffffffff8082111561366557600080fd5b818401915084601f83011261367957600080fd5b81518181111561368b5761368b613625565b604051601f8201601f19908116603f011681019083821181831017156136b3576136b3613625565b816040528281528760208487010111156136cc57600080fd5b6136dd836020830160208801612f41565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615613718576137186136e8565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826137425761374261371d565b500490565b805165ffffffffffff81168114612ec657600080fd5b600060a0828403121561376f57600080fd5b60405160a0810181811067ffffffffffffffff8211171561379257613792613625565b60405261379e83613747565b81526137ac60208401613747565b60208201526137bd60408401613747565b60408201526137ce60608401613747565b60608201526137df60808401613747565b60808201529392505050565b6000828210156137fd576137fd6136e8565b500390565b60006020828403121561381457600080fd5b5051919050565b60008261382a5761382a61371d565b500690565b6020808252600f908201526e0988a9c8ea890be9a92a69a82a8869608b1b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6020808252600e908201526d1393d517d055551213d49256915160921b604082015260600190565b600063ffffffff838116908316818110156138b3576138b36136e8565b039392505050565b600063ffffffff808416806138d2576138d261371d565b92169190910492915050565b7f68747470733a2f2f6e6f756e6c6574732e7774662f6170692f6e6f756e2f000081526000825161391681601e850160208701612f41565b91909101601e0192915050565b600060018201613935576139356136e8565b5060010190565b6000821982111561394f5761394f6136e8565b500190565b60006001600160601b03838116908316818110156138b3576138b36136e8565b60006001600160601b03808316818516808303821115613996576139966136e8565b01949350505050565b60006001600160601b038216806139b8576139b86136e8565b6000190192915050565b60006001600160601b038083168181036139de576139de6136e8565b6001019392505050565b6020808252600a908201526957524f4e475f46524f4d60b01b604082015260600190565b6020808252600e908201526d1253959053125117d05353d5539560921b604082015260600190565b81835260006001600160fb1b03831115613a4d57600080fd5b8260051b8083602087013760009401602001938452509192915050565b604081526000613a7e604083018688613a34565b82810360208401526136dd818587613a34565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0389811682528816602082015260a060408201819052600090613ae7908301888a613a34565b8281036060840152613afa818789613a34565b90508281036080840152613b0f818587613a91565b9b9a5050505050505050505050565b600060208284031215613b3057600080fd5b8151610f2681612ef5565b60208082526010908201526f155394d0519157d49150d2541251539560821b604082015260600190565b6020808252601190820152701253959053125117d49150d25412515395607a1b604082015260600190565b604081526000613ba3604083018561323a565b82810360208401526108ad818561323a565b6001600160a01b03868116825285166020820152604081018490526060810183905260a0608082018190526000906136dd90830184612f6d565b6001600160a01b03878116825286166020820152604081018590526060810184905260a060808201819052600090613c2a9083018486613a91565b98975050505050505050565b600063ffffffff808316818516808303821115613996576139966136e856fea2646970667358221220c76eed755390a93817edef0a2b7e8bb8dbf5b27e5a678158bd47b287cfc20eb364736f6c634300080d0033000000000000000000000000e626d419dd60be8038c46381ad171a0b3d22ed250000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc03
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c80635c60da1b116100665780635c60da1b1461012a5780637bad238014610151578063a41c385e14610164578063c45a01551461018b578063ced9481f146101b257600080fd5b806328205a931461009857806340c10f19146100c157806342d19ef4146100d657806342f495a414610117575b600080fd5b6100ab6100a636600461069a565b6101d9565b6040516100b891906106f6565b60405180910390f35b6100d46100cf36600461069a565b610268565b005b6100ff6100e4366004610729565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020016100b8565b6100ff61012536600461083a565b61031c565b6100ff7f00000000000000000000000026f0ecef411fb856b267b0f2fb21ee694fc056e981565b6100d461015f366004610920565b610403565b6100ff7f000000000000000000000000e626d419dd60be8038c46381ad171a0b3d22ed2581565b6100ff7f0000000000000000000000003f0741f8766aa66b86b927a3ef5147955d94292881565b6100ff7f0000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc0381565b6001600160a01b03828116600090815260208190526040908190205490516303a24d0760e21b81526004810184905260609291909116908190630e89341c90602401600060405180830381865afa158015610238573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261026091908101906109c6565b949350505050565b336000908152602081905260409020546001600160a01b0316806102a657604051630601cb1560e11b81523360048201526024015b60405180910390fd5b6040516394d008ef60e01b81526001600160a01b0384811660048301526024820184905260606044830152600060648301528216906394d008ef906084015b600060405180830381600087803b1580156102ff57600080fd5b505af1158015610313573d6000803e3d6000fd5b50505050505050565b6040516bffffffffffffffffffffffff1930606090811b8216602084015284811b82166034840152604883018490527f000000000000000000000000e626d419dd60be8038c46381ad171a0b3d22ed25811b821660688401527f0000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc03901b16607c82015260009081906103ea9060900160408051601f198184030181529190526001600160a01b037f00000000000000000000000026f0ecef411fb856b267b0f2fb21ee694fc056e91690610469565b90506103f88782888861057b565b979650505050505050565b336000908152602081905260409020546001600160a01b03168061043c57604051630601cb1560e11b815233600482015260240161029d565b60405162f75a4760e71b81526001600160a01b03821690637bad2380906102e59086908690600401610a5a565b8051604051606160f81b81526039820160f081811b60018401526f3d81600a3d39f33d3d3d3d363d3d376160801b600384015260028401901b601383018190526560373639366160d01b6015840152601b83015262013d7360e81b601d830152606085901b6020808401919091526c5af43d3d93803e603557fd5bf360981b60348401526000939260438401929186019084604182015b6020821061051f5783518152602093840193601f199092019101610500565b835160001960208490036101000a0119908116825260f088901b91830191825286846000f098506001600160a01b03891661056d57604051631d7fde3160e31b815260040160405180910390fd5b505050505050505092915050565b6040516389c9caa360e01b81526000906001600160a01b037f0000000000000000000000003f0741f8766aa66b86b927a3ef5147955d94292816906389c9caa3906105ce90889087908790600401610ab0565b6020604051808303816000875af11580156105ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106119190610b49565b6001600160a01b0381811660008181526020819052604080822080546001600160a01b031916948a16948517905551939450919290917f09d75e12e349f79020715b0ea7b2c707e8acf1889b6d6f1337fce7f4e1b9e5c791a3949350505050565b6001600160a01b038116811461068757600080fd5b50565b803561069581610672565b919050565b600080604083850312156106ad57600080fd5b82356106b881610672565b946020939093013593505050565b60005b838110156106e15781810151838201526020016106c9565b838111156106f0576000848401525b50505050565b60208152600082518060208401526107158160408501602087016106c6565b601f01601f19169190910160400192915050565b60006020828403121561073b57600080fd5b813561074681610672565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561078c5761078c61074d565b604052919050565b600067ffffffffffffffff8211156107ae576107ae61074d565b5060051b60200190565b600082601f8301126107c957600080fd5b813560206107de6107d983610794565b610763565b82815260059290921b840181019181810190868411156107fd57600080fd5b8286015b8481101561082f5780356001600160e01b0319811681146108225760008081fd5b8352918301918301610801565b509695505050505050565b600080600080600060a0868803121561085257600080fd5b8535945060208087013567ffffffffffffffff8082111561087257600080fd5b818901915089601f83011261088657600080fd5b81356108946107d982610794565b81815260059190911b8301840190848101908c8311156108b357600080fd5b938501935b828510156108da5784356108cb81610672565b825293850193908501906108b8565b9850505060408901359250808311156108f257600080fd5b5050610900888289016107b8565b93505061090f6060870161068a565b949793965091946080013592915050565b6000806040838503121561093357600080fd5b823561093e81610672565b915060208381013567ffffffffffffffff81111561095b57600080fd5b8401601f8101861361096c57600080fd5b803561097a6107d982610794565b81815260059190911b8201830190838101908883111561099957600080fd5b928401925b828410156109b75783358252928401929084019061099e565b80955050505050509250929050565b6000602082840312156109d857600080fd5b815167ffffffffffffffff808211156109f057600080fd5b818401915084601f830112610a0457600080fd5b815181811115610a1657610a1661074d565b610a29601f8201601f1916602001610763565b9150808252856020828501011115610a4057600080fd5b610a518160208401602086016106c6565b50949350505050565b6001600160a01b038316815260406020808301829052835191830182905260009184820191906060850190845b81811015610aa357845183529383019391830191600101610a87565b5090979650505050505050565b6000606082018583526020606081850152818651808452608086019150828801935060005b81811015610afa5784516001600160a01b031683529383019391830191600101610ad5565b50508481036040860152855180825290820192508186019060005b81811015610b3b5782516001600160e01b03191685529383019391830191600101610b15565b509298975050505050505050565b600060208284031215610b5b57600080fd5b81516107468161067256fea2646970667358221220494a7d6d15dcbd19f3650c486f39b7c960455246c7f18d8e065a639e5a189ef864736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e626d419dd60be8038c46381ad171a0b3d22ed250000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc03
-----Decoded View---------------
Arg [0] : _royaltyBeneficiary (address): 0xE626d419Dd60BE8038C46381ad171A0b3d22ed25
Arg [1] : _nounsToken (address): 0x9C8fF314C9Bc7F6e59A9d9225Fb22946427eDC03
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000e626d419dd60be8038c46381ad171a0b3d22ed25
Arg [1] : 0000000000000000000000009c8ff314c9bc7f6e59a9d9225fb22946427edc03
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.