Source Code
Latest 25 from a total of 6,865 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Override ... | 18052195 | 767 days ago | IN | 0 ETH | 0.00288959 | ||||
Create Override ... | 18045244 | 768 days ago | IN | 0 ETH | 0.00303639 | ||||
Create Override ... | 17552235 | 837 days ago | IN | 0 ETH | 0.00338031 | ||||
Create Override ... | 17245738 | 880 days ago | IN | 0 ETH | 0.01779377 | ||||
Create Override ... | 17245721 | 880 days ago | IN | 0 ETH | 0.0173267 | ||||
Create Override ... | 17245712 | 880 days ago | IN | 0 ETH | 0.01890186 | ||||
Create Override ... | 17245392 | 880 days ago | IN | 0 ETH | 0.02616503 | ||||
Create Override ... | 17245229 | 880 days ago | IN | 0 ETH | 0.03396139 | ||||
Create Override ... | 17245087 | 880 days ago | IN | 0 ETH | 0.0235511 | ||||
Create Override ... | 17244840 | 880 days ago | IN | 0 ETH | 0.02818634 | ||||
Create Override ... | 17244679 | 880 days ago | IN | 0 ETH | 0.02467464 | ||||
Create Override ... | 17244129 | 880 days ago | IN | 0 ETH | 0.02173196 | ||||
Create Override ... | 17243957 | 880 days ago | IN | 0 ETH | 0.01591243 | ||||
Create Override ... | 17243945 | 880 days ago | IN | 0 ETH | 0.01504552 | ||||
Create Override ... | 17243844 | 880 days ago | IN | 0 ETH | 0.01728357 | ||||
Create Override ... | 17243841 | 880 days ago | IN | 0 ETH | 0.01464364 | ||||
Create Override ... | 17243838 | 880 days ago | IN | 0 ETH | 0.01575431 | ||||
Create Override ... | 17243814 | 880 days ago | IN | 0 ETH | 0.01574711 | ||||
Create Override ... | 17243767 | 880 days ago | IN | 0 ETH | 0.01655609 | ||||
Create Override ... | 17243486 | 880 days ago | IN | 0 ETH | 0.01719289 | ||||
Create Override ... | 17243300 | 880 days ago | IN | 0 ETH | 0.0174861 | ||||
Create Override ... | 17243300 | 880 days ago | IN | 0 ETH | 0.01835829 | ||||
Create Override ... | 17243173 | 880 days ago | IN | 0 ETH | 0.02224509 | ||||
Create Override ... | 17242925 | 880 days ago | IN | 0 ETH | 0.01685006 | ||||
Create Override ... | 17241832 | 880 days ago | IN | 0 ETH | 0.02035281 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Method | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|---|
0x3d602d80 | 18052195 | 767 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 18045244 | 768 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17552235 | 837 days ago | Contract Creation | 0 ETH | |||
Transfer | 17343989 | 866 days ago | 0.30712163 ETH | ||||
0x3d602d80 | 17245738 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17245721 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17245712 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17245392 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17245229 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17245087 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17244840 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17244679 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17244129 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243957 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243945 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243844 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243841 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243838 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243814 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243767 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243486 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243300 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243300 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17243173 | 880 days ago | Contract Creation | 0 ETH | |||
0x3d602d80 | 17242925 | 880 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
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 Name:
EIP2981RoyaltyOverrideFactory
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/proxy/Clones.sol"; import { EIP2981RoyaltyOverrideCloneable } from "./RoyaltyOverrideCloneable.sol"; import { EIP2981MultiReceiverRoyaltyOverrideCloneable } from "./MultiReceiverRoyaltyOverrideCloneable.sol"; import { IRoyaltyRegistry } from "../IRoyaltyRegistry.sol"; import { Recipient } from "./IRoyaltySplitter.sol"; /** * Clone Factory for EIP2981 reference override implementation */ contract EIP2981RoyaltyOverrideFactory { address public immutable SINGLE_RECIPIENT_ORIGIN_ADDRESS; address public immutable MULTI_RECIPIENT_ORIGIN_ADDRESS; address payable public immutable ROYALTY_SPLITTER_ORIGIN_ADDRESS; error InvalidRoyaltyRegistryAddress(); uint256 constant INVALID_ROYALTY_REGISTRY_ADDRESS_SELECTOR = 0x1c491d3; event EIP2981RoyaltyOverrideCreated(address newEIP2981RoyaltyOverride); constructor(address singleOrigin, address multiOrigin, address payable royaltySplitterOrigin) { SINGLE_RECIPIENT_ORIGIN_ADDRESS = singleOrigin; MULTI_RECIPIENT_ORIGIN_ADDRESS = multiOrigin; ROYALTY_SPLITTER_ORIGIN_ADDRESS = royaltySplitterOrigin; } function createOverrideAndRegister( address royaltyRegistry, address tokenAddress, EIP2981RoyaltyOverrideCloneable.TokenRoyalty calldata defaultRoyalty ) public returns (address) { address clone = Clones.clone(SINGLE_RECIPIENT_ORIGIN_ADDRESS); EIP2981RoyaltyOverrideCloneable(clone).initialize(defaultRoyalty, msg.sender); emit EIP2981RoyaltyOverrideCreated(clone); registerOverride(royaltyRegistry, tokenAddress, clone); return clone; } function createOverrideAndRegister( address royaltyRegistry, address tokenAddress, uint16 defaultBps, Recipient[] calldata defaultRecipients ) public returns (address) { address clone = Clones.clone(MULTI_RECIPIENT_ORIGIN_ADDRESS); EIP2981MultiReceiverRoyaltyOverrideCloneable(clone).initialize( ROYALTY_SPLITTER_ORIGIN_ADDRESS, defaultBps, defaultRecipients, msg.sender ); emit EIP2981RoyaltyOverrideCreated(clone); registerOverride(royaltyRegistry, tokenAddress, clone); return clone; } function registerOverride(address royaltyRegistry, address tokenAddress, address lookupAddress) internal { // encode setRoyaltyLookupAddress call with tokenAddress and lookupAddress and also append msg.sender to calldata. // Including the original msg.sender allows the registry to securely verify the caller is the owner of the token bytes memory data = abi.encodeWithSelector( IRoyaltyRegistry.setRoyaltyLookupAddress.selector, tokenAddress, lookupAddress, msg.sender ); // check success and return data, and bubble up original revert reason if call was unsuccessful ///@solidity memory-safe-assembly assembly { // clear first word of scratch space, where we will store one word of returndata // if the call results in no returndata is available, this would not be overwritten otherwise mstore(0, 0) let success := call(gas(), royaltyRegistry, 0, add(data, 0x20), mload(data), 0, 0x20) // check if call succeeded if iszero(success) { // copy all of returndata to memory starting at 0; we don't have to worry about dirtying memory since // we are reverting. returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } // check if returned boolean is true, since a successful call does not guarantee a successful execution let returned := mload(0) if iszero(eq(returned, 1)) { mstore(0, INVALID_ROYALTY_REGISTRY_ADDRESS_SELECTOR) revert(0x1c, 4) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @dev Royalty registry interface */ interface IRoyaltyRegistry is IERC165 { event RoyaltyOverride(address owner, address tokenAddress, address royaltyAddress); /** * Override the location of where to look up royalty information for a given token contract. * Allows for backwards compatibility and implementation of royalty logic for contracts that did not previously support them. * * @param tokenAddress - The token address you wish to override * @param royaltyAddress - The royalty override address */ function setRoyaltyLookupAddress(address tokenAddress, address royaltyAddress) external returns (bool); /** * Returns royalty address location. Returns the tokenAddress by default, or the override if it exists * * @param tokenAddress - The token address you are looking up the royalty for */ function getRoyaltyLookupAddress(address tokenAddress) external view returns (address); /** * Returns the token address that an overrideAddress is set for. * Note: will not be accurate if the override was created before this function was added. * * @param overrideAddress - The override address you are looking up the token for */ function getOverrideLookupTokenAddress(address overrideAddress) external view returns (address); /** * Whether or not the message sender can override the royalty address for the given token address * * @param tokenAddress - The token address you are looking up the royalty for */ function overrideAllowed(address tokenAddress) external view returns (bool); }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.0; /** * @notice A library for manipulation of byte arrays. */ library BytesLibrary { /** * @dev Replace the address at the given location in a byte array if the contents at that location * match the expected address. */ function replaceAtIf(bytes memory data, uint256 startLocation, address expectedAddress, address newAddress) internal pure { bytes memory expectedData = abi.encodePacked(expectedAddress); bytes memory newData = abi.encodePacked(newAddress); // An address is 20 bytes long for (uint256 i = 0; i < 20; i++) { uint256 dataLocation = startLocation + i; require(data[dataLocation] == expectedData[i], "Bytes: Data provided does not include the expectedAddress"); data[dataLocation] = newData[i]; } } /** * @dev Checks if the call data starts with the given function signature. */ function startsWith(bytes memory callData, bytes4 functionSig) internal pure returns (bool) { // A signature is 4 bytes long if (callData.length < 4) { return false; } for (uint256 i = 0; i < 4; i++) { if (callData[i] != functionSig[i]) { return false; } } return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import "./IRoyaltySplitter.sol"; /** * Multi-receiver EIP2981 reference override implementation */ interface IEIP2981MultiReceiverRoyaltyOverride is IERC165 { event TokenRoyaltyRemoved(uint256 tokenId); event TokenRoyaltySet(uint256 tokenId, uint16 royaltyBPS, Recipient[] recipients); event DefaultRoyaltySet(uint16 royaltyBPS, Recipient[] recipients); struct TokenRoyaltyConfig { uint256 tokenId; uint16 royaltyBPS; Recipient[] recipients; } /** * @dev Set per token royalties. Passing a recipient of address(0) will delete any existing configuration */ function setTokenRoyalties(TokenRoyaltyConfig[] calldata royalties) external; /** * @dev Get all token royalty configurations */ function getTokenRoyalties() external view returns (TokenRoyaltyConfig[] memory); /** * @dev Get the default royalty */ function getDefaultRoyalty() external view returns (uint16 bps, Recipient[] memory); /** * @dev Set a default royalty configuration. Will be used if no token specific configuration is set */ function setDefaultRoyalty(uint16 bps, Recipient[] calldata recipients) external; /** * @dev Helper function to get all splits contracts */ function getAllSplits() external view returns (address payable[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * Simple EIP2981 reference override implementation */ interface IEIP2981RoyaltyOverride is IERC165 { event TokenRoyaltyRemoved(uint256 tokenId); event TokenRoyaltySet(uint256 tokenId, address recipient, uint16 bps); event DefaultRoyaltySet(address recipient, uint16 bps); struct TokenRoyalty { address recipient; uint16 bps; } struct TokenRoyaltyConfig { uint256 tokenId; address recipient; uint16 bps; } /** * @dev Set per token royalties. Passing a recipient of address(0) will delete any existing configuration */ function setTokenRoyalties(TokenRoyaltyConfig[] calldata royalties) external; /** * @dev Get the number of token specific overrides. Used to enumerate over all configurations */ function getTokenRoyaltiesCount() external view returns (uint256); /** * @dev Get a token royalty configuration by index. Use in conjunction with getTokenRoyaltiesCount to get all per token configurations */ function getTokenRoyaltyByIndex(uint256 index) external view returns (TokenRoyaltyConfig memory); /** * @dev Set a default royalty configuration. Will be used if no token specific configuration is set */ function setDefaultRoyalty(TokenRoyalty calldata royalty) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; struct Recipient { address payable recipient; uint16 bps; } interface IRoyaltySplitter is IERC165 { /** * @dev Set the splitter recipients. Total bps must total 10000. */ function setRecipients(Recipient[] calldata recipients) external; /** * @dev Get the splitter recipients; */ function getRecipients() external view returns (Recipient[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./MultiReceiverRoyaltyOverrideCore.sol"; import "./IRoyaltySplitter.sol"; import "../IRoyaltyRegistry.sol"; /** * Simple EIP2981 reference override implementation */ contract EIP2981MultiReceiverRoyaltyOverrideCloneable is EIP2981MultiReceiverRoyaltyMultiReceiverOverrideCore, OwnableUpgradeable { function initialize( address payable royaltySplitterCloneable, uint16 defaultBps, Recipient[] memory defaultRecipients, address initialOwner ) public initializer { _transferOwnership(initialOwner); _royaltySplitterCloneable = royaltySplitterCloneable; // Initialize with default royalties _setDefaultRoyalty(defaultBps, defaultRecipients); } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-setTokenRoyalties}. */ function setTokenRoyalties(TokenRoyaltyConfig[] calldata royaltyConfigs) external override onlyOwner { _setTokenRoyalties(royaltyConfigs); } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-setDefaultRoyalty}. */ function setDefaultRoyalty(uint16 bps, Recipient[] calldata recipients) external override onlyOwner { _setDefaultRoyalty(bps, recipients); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "@openzeppelin/contracts/proxy/Clones.sol"; import "./IMultiReceiverRoyaltyOverride.sol"; import "./RoyaltySplitter.sol"; import "./IRoyaltySplitter.sol"; import "../specs/IEIP2981.sol"; /** * Multi-receiver EIP2981 reference override implementation */ abstract contract EIP2981MultiReceiverRoyaltyMultiReceiverOverrideCore is IEIP2981, IEIP2981MultiReceiverRoyaltyOverride, ERC165 { uint16 private _defaultRoyaltyBPS; address payable private _defaultRoyaltySplitter; mapping(uint256 => address payable) private _tokenRoyaltiesSplitter; mapping(uint256 => uint16) private _tokenRoyaltiesBPS; uint256[] private _tokensWithRoyalties; // Address of cloneable splitter contract address internal _royaltySplitterCloneable; function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165, IERC165) returns (bool) { return interfaceId == type(IEIP2981).interfaceId || interfaceId == type(IEIP2981MultiReceiverRoyaltyOverride).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Sets token royalties. When you override this in the implementation contract * ensure that you access restrict it to the contract owner or admin */ function _setTokenRoyalties(TokenRoyaltyConfig[] memory royaltyConfigs) internal { for (uint256 i; i < royaltyConfigs.length; i++) { TokenRoyaltyConfig memory royaltyConfig = royaltyConfigs[i]; require(royaltyConfig.royaltyBPS < 10000, "Invalid bps"); Recipient[] memory recipients = royaltyConfig.recipients; address payable splitterAddress = _tokenRoyaltiesSplitter[royaltyConfig.tokenId]; if (recipients.length == 0) { if (splitterAddress != address(0)) { IRoyaltySplitter(splitterAddress).setRecipients(recipients); } delete _tokenRoyaltiesBPS[royaltyConfig.tokenId]; emit TokenRoyaltyRemoved(royaltyConfig.tokenId); } else { if (splitterAddress == address(0)) { splitterAddress = payable(Clones.clone(_royaltySplitterCloneable)); RoyaltySplitter(splitterAddress).initialize(recipients); _tokenRoyaltiesSplitter[royaltyConfig.tokenId] = splitterAddress; _tokensWithRoyalties.push(royaltyConfig.tokenId); } else { IRoyaltySplitter(splitterAddress).setRecipients(recipients); } _tokenRoyaltiesBPS[royaltyConfig.tokenId] = royaltyConfig.royaltyBPS; emit TokenRoyaltySet(royaltyConfig.tokenId, royaltyConfig.royaltyBPS, recipients); } } } /** * @dev Sets default royalty. When you override this in the implementation contract * ensure that you access restrict it to the contract owner or admin */ function _setDefaultRoyalty(uint16 bps, Recipient[] memory recipients) internal { require(bps < 10000, "Invalid bps"); if (_defaultRoyaltySplitter == address(0)) { _defaultRoyaltySplitter = payable(Clones.clone(_royaltySplitterCloneable)); RoyaltySplitter(_defaultRoyaltySplitter).initialize(recipients); } else { IRoyaltySplitter(_defaultRoyaltySplitter).setRecipients(recipients); } _defaultRoyaltyBPS = bps; emit DefaultRoyaltySet(bps, recipients); } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-getTokenRoyalties}. */ function getTokenRoyalties() external view override returns (TokenRoyaltyConfig[] memory royaltyConfigs) { royaltyConfigs = new TokenRoyaltyConfig[](_tokensWithRoyalties.length); for (uint256 i; i < _tokensWithRoyalties.length; ++i) { TokenRoyaltyConfig memory royaltyConfig; uint256 tokenId = _tokensWithRoyalties[i]; address splitterAddress = _tokenRoyaltiesSplitter[tokenId]; if (splitterAddress != address(0)) { royaltyConfig.recipients = IRoyaltySplitter(splitterAddress).getRecipients(); } royaltyConfig.tokenId = tokenId; royaltyConfig.royaltyBPS = _tokenRoyaltiesBPS[tokenId]; royaltyConfigs[i] = royaltyConfig; } } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-getDefaultRoyalty}. */ function getDefaultRoyalty() external view override returns (uint16 bps, Recipient[] memory recipients) { if (_defaultRoyaltySplitter != address(0)) { recipients = IRoyaltySplitter(_defaultRoyaltySplitter).getRecipients(); } return (_defaultRoyaltyBPS, recipients); } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-royaltyInfo}. */ function royaltyInfo(uint256 tokenId, uint256 value) public view override returns (address, uint256) { if (_tokenRoyaltiesSplitter[tokenId] != address(0)) { return (_tokenRoyaltiesSplitter[tokenId], value * _tokenRoyaltiesBPS[tokenId] / 10000); } if (_defaultRoyaltySplitter != address(0) && _defaultRoyaltyBPS != 0) { return (_defaultRoyaltySplitter, value * _defaultRoyaltyBPS / 10000); } return (address(0), 0); } /** * @dev See {IEIP2981MultiReceiverRoyaltyOverride-getAllSplits}. */ function getAllSplits() external view override returns (address payable[] memory splits) { uint256 startingIndex; uint256 endingIndex = _tokensWithRoyalties.length; if (_defaultRoyaltySplitter != address(0)) { splits = new address payable[](1+_tokensWithRoyalties.length); splits[0] = _defaultRoyaltySplitter; startingIndex = 1; ++endingIndex; } else { // unreachable in practice splits = new address payable[](_tokensWithRoyalties.length); } for (uint256 i = startingIndex; i < endingIndex; ++i) { splits[i] = _tokenRoyaltiesSplitter[_tokensWithRoyalties[i - startingIndex]]; } } function getRecipients() public view returns (Recipient[] memory) { return RoyaltySplitter(_defaultRoyaltySplitter).getRecipients(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "./RoyaltyOverrideCore.sol"; /** * Simple EIP2981 reference override implementation */ contract EIP2981RoyaltyOverrideCloneable is EIP2981RoyaltyOverrideCore, OwnableUpgradeable { function initialize(TokenRoyalty calldata _defaultRoyalty, address initialOwner) public initializer { _transferOwnership(initialOwner); _setDefaultRoyalty(_defaultRoyalty); } /** * @dev See {IEIP2981RoyaltyOverride-setTokenRoyalties}. */ function setTokenRoyalties(TokenRoyaltyConfig[] calldata royaltyConfigs) external override onlyOwner { _setTokenRoyalties(royaltyConfigs); } /** * @dev See {IEIP2981RoyaltyOverride-setDefaultRoyalty}. */ function setDefaultRoyalty(TokenRoyalty calldata royalty) external override onlyOwner { _setDefaultRoyalty(royalty); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @author: manifold.xyz import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import "./IRoyaltyOverride.sol"; import "../specs/IEIP2981.sol"; /** * Simple EIP2981 reference override implementation */ abstract contract EIP2981RoyaltyOverrideCore is IEIP2981, IEIP2981RoyaltyOverride, ERC165 { using EnumerableSet for EnumerableSet.UintSet; TokenRoyalty public defaultRoyalty; mapping(uint256 => TokenRoyalty) private _tokenRoyalties; EnumerableSet.UintSet private _tokensWithRoyalties; function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165, IERC165) returns (bool) { return interfaceId == type(IEIP2981).interfaceId || interfaceId == type(IEIP2981RoyaltyOverride).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Sets token royalties. When you override this in the implementation contract * ensure that you access restrict it to the contract owner or admin */ function _setTokenRoyalties(TokenRoyaltyConfig[] memory royaltyConfigs) internal { for (uint256 i = 0; i < royaltyConfigs.length; i++) { TokenRoyaltyConfig memory royaltyConfig = royaltyConfigs[i]; require(royaltyConfig.bps < 10000, "Invalid bps"); if (royaltyConfig.recipient == address(0)) { delete _tokenRoyalties[royaltyConfig.tokenId]; _tokensWithRoyalties.remove(royaltyConfig.tokenId); emit TokenRoyaltyRemoved(royaltyConfig.tokenId); } else { _tokenRoyalties[royaltyConfig.tokenId] = TokenRoyalty(royaltyConfig.recipient, royaltyConfig.bps); _tokensWithRoyalties.add(royaltyConfig.tokenId); emit TokenRoyaltySet(royaltyConfig.tokenId, royaltyConfig.recipient, royaltyConfig.bps); } } } /** * @dev Sets default royalty. When you override this in the implementation contract * ensure that you access restrict it to the contract owner or admin */ function _setDefaultRoyalty(TokenRoyalty memory royalty) internal { require(royalty.bps < 10000, "Invalid bps"); defaultRoyalty = TokenRoyalty(royalty.recipient, royalty.bps); emit DefaultRoyaltySet(royalty.recipient, royalty.bps); } /** * @dev See {IEIP2981RoyaltyOverride-getTokenRoyaltiesCount}. */ function getTokenRoyaltiesCount() external view override returns (uint256) { return _tokensWithRoyalties.length(); } /** * @dev See {IEIP2981RoyaltyOverride-getTokenRoyaltyByIndex}. */ function getTokenRoyaltyByIndex(uint256 index) external view override returns (TokenRoyaltyConfig memory) { uint256 tokenId = _tokensWithRoyalties.at(index); TokenRoyalty memory royalty = _tokenRoyalties[tokenId]; return TokenRoyaltyConfig(tokenId, royalty.recipient, royalty.bps); } /** * @dev See {IEIP2981RoyaltyOverride-royaltyInfo}. */ function royaltyInfo(uint256 tokenId, uint256 value) public view override returns (address, uint256) { if (_tokenRoyalties[tokenId].recipient != address(0)) { return (_tokenRoyalties[tokenId].recipient, value * _tokenRoyalties[tokenId].bps / 10000); } if (defaultRoyalty.recipient != address(0) && defaultRoyalty.bps != 0) { return (defaultRoyalty.recipient, value * defaultRoyalty.bps / 10000); } return (address(0), 0); } }
// SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "@openzeppelin/contracts/proxy/Clones.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "../libraries/BytesLibrary.sol"; import "./IRoyaltySplitter.sol"; interface IERC20Approve { function approve(address spender, uint256 amount) external returns (bool); function increaseAllowance(address spender, uint256 amount) external returns (bool); } /** * Cloneable and configurable royalty splitter contract */ contract RoyaltySplitter is Initializable, OwnableUpgradeable, IRoyaltySplitter, ERC165 { using BytesLibrary for bytes; using AddressUpgradeable for address payable; using AddressUpgradeable for address; using SafeMath for uint256; uint256 internal constant BASIS_POINTS = 10000; uint256 constant IERC20_APPROVE_SELECTOR = 0x095ea7b300000000000000000000000000000000000000000000000000000000; uint256 constant SELECTOR_MASK = 0xffffffff00000000000000000000000000000000000000000000000000000000; Recipient[] private _recipients; event PercentSplitCreated(address indexed contractAddress); event PercentSplitShare(address indexed recipient, uint256 percentInBasisPoints); event ETHTransferred(address indexed account, uint256 amount); event ERC20Transferred(address indexed erc20Contract, address indexed account, uint256 amount); function supportsInterface(bytes4 interfaceId) public view virtual override (ERC165, IERC165) returns (bool) { return interfaceId == type(IRoyaltySplitter).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Requires that the msg.sender is one of the recipients in this split. */ modifier onlyRecipient() { for (uint256 i = 0; i < _recipients.length; i++) { if (_recipients[i].recipient == msg.sender) { _; return; } } revert("Split: Can only be called by one of the recipients"); } /** * @notice Called once to configure the contract after the initial deployment. * @dev This will be called by `createSplit` after deploying the proxy so it should never be called directly. */ function initialize(Recipient[] calldata recipients) public initializer { __Ownable_init(); _setRecipients(recipients); } /** * @dev Set the splitter recipients. Total bps must total 10000. */ function setRecipients(Recipient[] calldata recipients) external override onlyOwner { _setRecipients(recipients); } function _setRecipients(Recipient[] calldata recipients) private { delete _recipients; if (recipients.length == 0) { return; } uint256 totalBPS; for (uint256 i; i < recipients.length; ++i) { totalBPS += recipients[i].bps; _recipients.push(recipients[i]); } require(totalBPS == BASIS_POINTS, "Total bps must be 10000"); } /** * @dev Get the splitter recipients; */ function getRecipients() external view override returns (Recipient[] memory) { return _recipients; } /** * @notice Forwards any ETH received to the recipients in this split. * @dev Each recipient increases the gas required to split * and contract recipients may significantly increase the gas required. */ receive() external payable { _splitETH(msg.value); } /** * @notice Allows any ETH stored by the contract to be split among recipients. * @dev Normally ETH is forwarded as it comes in, but a balance in this contract * is possible if it was sent before the contract was created or if self destruct was used. */ function splitETH() public { _splitETH(address(this).balance); } function _splitETH(uint256 value) internal { if (value > 0) { uint256 totalSent; uint256 amountToSend; unchecked { for (uint256 i = _recipients.length - 1; i > 0; i--) { Recipient memory recipient = _recipients[i]; amountToSend = (value * recipient.bps) / BASIS_POINTS; totalSent += amountToSend; recipient.recipient.sendValue(amountToSend); emit ETHTransferred(recipient.recipient, amountToSend); } // Favor the 1st recipient if there are any rounding issues amountToSend = value - totalSent; } _recipients[0].recipient.sendValue(amountToSend); emit ETHTransferred(_recipients[0].recipient, amountToSend); } } /** * @notice Anyone can call this function to split all available tokens at the provided address between the recipients. * @dev This contract is built to split ETH payments. The ability to attempt to split ERC20 tokens is here * just in case tokens were also sent so that they don't get locked forever in the contract. */ function splitERC20Tokens(IERC20 erc20Contract) public { require(_splitERC20Tokens(erc20Contract), "Split: ERC20 split failed"); } function _splitERC20Tokens(IERC20 erc20Contract) internal returns (bool) { try erc20Contract.balanceOf(address(this)) returns (uint256 balance) { if (balance == 0) { return false; } uint256 amountToSend; uint256 totalSent; unchecked { for (uint256 i = _recipients.length - 1; i > 0; i--) { Recipient memory recipient = _recipients[i]; bool success; (success, amountToSend) = balance.tryMul(recipient.bps); amountToSend /= BASIS_POINTS; totalSent += amountToSend; try erc20Contract.transfer(recipient.recipient, amountToSend) { emit ERC20Transferred(address(erc20Contract), recipient.recipient, amountToSend); } catch { return false; } } // Favor the 1st recipient if there are any rounding issues amountToSend = balance - totalSent; } try erc20Contract.transfer(_recipients[0].recipient, amountToSend) { emit ERC20Transferred(address(erc20Contract), _recipients[0].recipient, amountToSend); } catch { return false; } return true; } catch { return false; } } /** * @notice Allows the split recipients to make an arbitrary contract call. * @dev This is provided to allow recovering from unexpected scenarios, * such as receiving an NFT at this address. * * It will first attempt a fair split of ERC20 tokens before proceeding. * * This contract is built to split ETH payments. The ability to attempt to make other calls is here * just in case other assets were also sent so that they don't get locked forever in the contract. */ function proxyCall(address payable target, bytes calldata callData) external onlyRecipient { require( !callData.startsWith(IERC20Approve.approve.selector) && !callData.startsWith(IERC20Approve.increaseAllowance.selector), "Split: ERC20 tokens must be split" ); try this.splitERC20Tokens(IERC20(target)) { } catch { } target.functionCall(callData); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * EIP-2981 */ interface IEIP2981 { /** * bytes4(keccak256("royaltyInfo(uint256,uint256)")) == 0x2a55205a * * => 0x2a55205a = 0x2a55205a */ function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/Clones.sol) pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(0, 0x09, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(0, 0x09, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := keccak256(add(ptr, 0x43), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress(address implementation, bytes32 salt) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ``` * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
{ "remappings": [ "@manifoldxyz/libraries-solidity/=lib/libraries-solidity/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "create2-helpers/=lib/create2-helpers/src/", "create2-scripts/=lib/create2-helpers/script/", "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "libraries-solidity/=lib/libraries-solidity/contracts/", "openzeppelin-contracts/=lib/create2-helpers/lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 1000000 }, "metadata": { "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"singleOrigin","type":"address"},{"internalType":"address","name":"multiOrigin","type":"address"},{"internalType":"address payable","name":"royaltySplitterOrigin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidRoyaltyRegistryAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newEIP2981RoyaltyOverride","type":"address"}],"name":"EIP2981RoyaltyOverrideCreated","type":"event"},{"inputs":[],"name":"MULTI_RECIPIENT_ORIGIN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROYALTY_SPLITTER_ORIGIN_ADDRESS","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SINGLE_RECIPIENT_ORIGIN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"royaltyRegistry","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"components":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"bps","type":"uint16"}],"internalType":"struct IEIP2981RoyaltyOverride.TokenRoyalty","name":"defaultRoyalty","type":"tuple"}],"name":"createOverrideAndRegister","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"royaltyRegistry","type":"address"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint16","name":"defaultBps","type":"uint16"},{"components":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint16","name":"bps","type":"uint16"}],"internalType":"struct Recipient[]","name":"defaultRecipients","type":"tuple[]"}],"name":"createOverrideAndRegister","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e060405234801561001057600080fd5b5060405161084938038061084983398101604081905261002f91610064565b6001600160a01b0392831660805290821660a0521660c0526100b1565b6001600160a01b038116811461006157600080fd5b50565b60008060006060848603121561007957600080fd5b83516100848161004c565b60208501519093506100958161004c565b60408501519092506100a68161004c565b809150509250925092565b60805160a05160c0516107576100f26000396000818160c101526102bb0152600081816071015261024a01526000818160fb015261013801526107576000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80638d872a52116100505780638d872a52146100e3578063e83f61e5146100f6578063f50c89561461011d57600080fd5b806315913ed11461006c57806375acd170146100bc575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100937f000000000000000000000000000000000000000000000000000000000000000081565b6100936100f1366004610537565b610130565b6100937f000000000000000000000000000000000000000000000000000000000000000081565b61009361012b3660046105ba565b610242565b60008061015c7f000000000000000000000000000000000000000000000000000000000000000061037c565b6040517f207d7e9800000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063207d7e98906101b39086903390600401610663565b600060405180830381600087803b1580156101cd57600080fd5b505af11580156101e1573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f6ace5835f14486bead350c58a6ce67b18fec46c58b809b749b08541cf74580259250602001905060405180910390a161023a858583610448565b949350505050565b60008061026e7f000000000000000000000000000000000000000000000000000000000000000061037c565b6040517f6f1c65d200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690636f1c65d2906102eb907f00000000000000000000000000000000000000000000000000000000000000009089908990899033906004016106b2565b600060405180830381600087803b15801561030557600080fd5b505af1158015610319573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f6ace5835f14486bead350c58a6ce67b18fec46c58b809b749b08541cf74580259250602001905060405180910390a1610372878783610448565b9695505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f0905073ffffffffffffffffffffffffffffffffffffffff8116610443576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660248301528316604482015233606480830191909152825180830390910181526084909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f26bd89820000000000000000000000000000000000000000000000000000000017815260008080528351909182885af1806104f1573d6000803e3d6000fd5b506000516001811461050b576301c491d36000526004601cfd5b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461053457600080fd5b50565b6000806000838503608081121561054d57600080fd5b843561055881610512565b9350602085013561056881610512565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561059a57600080fd5b506040840190509250925092565b803561ffff8116811461044357600080fd5b6000806000806000608086880312156105d257600080fd5b85356105dd81610512565b945060208601356105ed81610512565b93506105fb604087016105a8565b9250606086013567ffffffffffffffff8082111561061857600080fd5b818801915088601f83011261062c57600080fd5b81358181111561063b57600080fd5b8960208260061b850101111561065057600080fd5b9699959850939650602001949392505050565b60608101833561067281610512565b73ffffffffffffffffffffffffffffffffffffffff808216845261ffff61069b602088016105a8565b166020850152808516604085015250509392505050565b60006080820173ffffffffffffffffffffffffffffffffffffffff8089168452602061ffff808a168287015260406080818801528489865260a0880190508a955060005b8a81101561072e57863561070981610512565b86168252836107198887016105a8565b168286015295820195908201906001016106f6565b508096505050505080851660608501525050969550505050505056fea164736f6c6343000811000a0000000000000000000000005fb96dac4dc7886affa2860df4caa9ddfd0c9798000000000000000000000000a9376f59aff8a8a7673688a588724e1b0513619800000000000000000000000074b2a6ecc225dc85af74b5ea12c8f26fba86c571
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100675760003560e01c80638d872a52116100505780638d872a52146100e3578063e83f61e5146100f6578063f50c89561461011d57600080fd5b806315913ed11461006c57806375acd170146100bc575b600080fd5b6100937f000000000000000000000000a9376f59aff8a8a7673688a588724e1b0513619881565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6100937f00000000000000000000000074b2a6ecc225dc85af74b5ea12c8f26fba86c57181565b6100936100f1366004610537565b610130565b6100937f0000000000000000000000005fb96dac4dc7886affa2860df4caa9ddfd0c979881565b61009361012b3660046105ba565b610242565b60008061015c7f0000000000000000000000005fb96dac4dc7886affa2860df4caa9ddfd0c979861037c565b6040517f207d7e9800000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063207d7e98906101b39086903390600401610663565b600060405180830381600087803b1580156101cd57600080fd5b505af11580156101e1573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f6ace5835f14486bead350c58a6ce67b18fec46c58b809b749b08541cf74580259250602001905060405180910390a161023a858583610448565b949350505050565b60008061026e7f000000000000000000000000a9376f59aff8a8a7673688a588724e1b0513619861037c565b6040517f6f1c65d200000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff821690636f1c65d2906102eb907f00000000000000000000000074b2a6ecc225dc85af74b5ea12c8f26fba86c5719089908990899033906004016106b2565b600060405180830381600087803b15801561030557600080fd5b505af1158015610319573d6000803e3d6000fd5b505060405173ffffffffffffffffffffffffffffffffffffffff841681527f6ace5835f14486bead350c58a6ce67b18fec46c58b809b749b08541cf74580259250602001905060405180910390a1610372878783610448565b9695505050505050565b6000763d602d80600a3d3981f3363d3d373d3d3d363d730000008260601b60e81c176000526e5af43d82803e903d91602b57fd5bf38260781b17602052603760096000f0905073ffffffffffffffffffffffffffffffffffffffff8116610443576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b6040805173ffffffffffffffffffffffffffffffffffffffff84811660248301528316604482015233606480830191909152825180830390910181526084909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f26bd89820000000000000000000000000000000000000000000000000000000017815260008080528351909182885af1806104f1573d6000803e3d6000fd5b506000516001811461050b576301c491d36000526004601cfd5b5050505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461053457600080fd5b50565b6000806000838503608081121561054d57600080fd5b843561055881610512565b9350602085013561056881610512565b925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201121561059a57600080fd5b506040840190509250925092565b803561ffff8116811461044357600080fd5b6000806000806000608086880312156105d257600080fd5b85356105dd81610512565b945060208601356105ed81610512565b93506105fb604087016105a8565b9250606086013567ffffffffffffffff8082111561061857600080fd5b818801915088601f83011261062c57600080fd5b81358181111561063b57600080fd5b8960208260061b850101111561065057600080fd5b9699959850939650602001949392505050565b60608101833561067281610512565b73ffffffffffffffffffffffffffffffffffffffff808216845261ffff61069b602088016105a8565b166020850152808516604085015250509392505050565b60006080820173ffffffffffffffffffffffffffffffffffffffff8089168452602061ffff808a168287015260406080818801528489865260a0880190508a955060005b8a81101561072e57863561070981610512565b86168252836107198887016105a8565b168286015295820195908201906001016106f6565b508096505050505080851660608501525050969550505050505056fea164736f6c6343000811000a
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000005fb96dac4dc7886affa2860df4caa9ddfd0c9798000000000000000000000000a9376f59aff8a8a7673688a588724e1b0513619800000000000000000000000074b2a6ecc225dc85af74b5ea12c8f26fba86c571
-----Decoded View---------------
Arg [0] : singleOrigin (address): 0x5Fb96DAc4DC7886afFa2860df4caa9ddFd0C9798
Arg [1] : multiOrigin (address): 0xa9376F59AFf8A8A7673688A588724E1B05136198
Arg [2] : royaltySplitterOrigin (address): 0x74b2a6eCc225dc85af74b5Ea12C8f26Fba86c571
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000005fb96dac4dc7886affa2860df4caa9ddfd0c9798
Arg [1] : 000000000000000000000000a9376f59aff8a8a7673688a588724e1b05136198
Arg [2] : 00000000000000000000000074b2a6ecc225dc85af74b5ea12c8f26fba86c571
Deployed Bytecode Sourcemap
510:3500:9:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;617:55;;;;;;;;190:42:22;178:55;;;160:74;;148:2;133:18;617:55:9;;;;;;;678:64;;;;;1229:509;;;;;;:::i;:::-;;:::i;555:56::-;;;;;1744:588;;;;;;:::i;:::-;;:::i;1229:509::-;1427:7;1446:13;1462:45;1475:31;1462:12;:45::i;:::-;1517:77;;;;;1446:61;;-1:-1:-1;1517:49:9;;;;;;:77;;1567:14;;1583:10;;1517:77;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1609:36:9;;190:42:22;178:55;;160:74;;1609:36:9;;-1:-1:-1;148:2:22;133:18;;-1:-1:-1;1609:36:9;;;;;;;1655:54;1672:15;1689:12;1703:5;1655:16;:54::i;:::-;1726:5;1229:509;-1:-1:-1;;;;1229:509:9:o;1744:588::-;1939:7;1958:13;1974:44;1987:30;1974:12;:44::i;:::-;2028:160;;;;;1958:60;;-1:-1:-1;2028:62:9;;;;;;:160;;2104:31;;2137:10;;2149:17;;;;2168:10;;2028:160;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2203:36:9;;190:42:22;178:55;;160:74;;2203:36:9;;-1:-1:-1;148:2:22;133:18;;-1:-1:-1;2203:36:9;;;;;;;2249:54;2266:15;2283:12;2297:5;2249:16;:54::i;:::-;2320:5;1744:588;-1:-1:-1;;;;;;1744:588:9:o;973:759:16:-;1030:16;1362:48;1344:14;1338:4;1334:25;1328:4;1324:36;1321:90;1315:4;1308:104;1569:32;1552:14;1546:4;1542:25;1539:63;1533:4;1526:77;1644:4;1638;1635:1;1628:21;1616:33;-1:-1:-1;1676:22:16;;;1668:57;;;;;;;4377:2:22;1668:57:16;;;4359:21:22;4416:2;4396:18;;;4389:30;4455:24;4435:18;;;4428:52;4497:18;;1668:57:16;;;;;;;;973:759;;;:::o;2338:1670:9:-;2717:136;;;4738:42:22;4807:15;;;2717:136:9;;;4789:34:22;4859:15;;4839:18;;;4832:43;2833:10:9;4891:18:22;;;;4884:43;;;;2717:136:9;;;;;;;;;;4701:18:22;;;;2717:136:9;;;;;;;;;;;2753:49;2717:136;;;-1:-1:-1;3232:12:9;;;3321:11;;-1:-1:-1;;;3284:15:9;3277:5;3272:70;3405:7;3395:288;;3608:16;3605:1;3602;3587:38;3652:16;3649:1;3642:27;3395:288;;3834:1;3828:8;3872:1;3862:8;3859:15;3849:143;;3904:41;3901:1;3894:52;3976:1;3970:4;3963:15;3849:143;;3019:983;2338:1670;;;:::o;492:154:22:-;578:42;571:5;567:54;560:5;557:65;547:93;;636:1;633;626:12;547:93;492:154;:::o;651:608::-;759:6;767;775;819:9;810:7;806:23;849:3;845:2;841:12;838:32;;;866:1;863;856:12;838:32;905:9;892:23;924:31;949:5;924:31;:::i;:::-;974:5;-1:-1:-1;1031:2:22;1016:18;;1003:32;1044:33;1003:32;1044:33;:::i;:::-;1096:7;-1:-1:-1;1196:2:22;1127:66;1119:75;;1115:84;1112:104;;;1212:1;1209;1202:12;1112:104;;1250:2;1239:9;1235:18;1225:28;;651:608;;;;;:::o;1264:159::-;1331:20;;1391:6;1380:18;;1370:29;;1360:57;;1413:1;1410;1403:12;1428:992;1568:6;1576;1584;1592;1600;1653:3;1641:9;1632:7;1628:23;1624:33;1621:53;;;1670:1;1667;1660:12;1621:53;1709:9;1696:23;1728:31;1753:5;1728:31;:::i;:::-;1778:5;-1:-1:-1;1835:2:22;1820:18;;1807:32;1848:33;1807:32;1848:33;:::i;:::-;1900:7;-1:-1:-1;1926:37:22;1959:2;1944:18;;1926:37;:::i;:::-;1916:47;;2014:2;2003:9;1999:18;1986:32;2037:18;2078:2;2070:6;2067:14;2064:34;;;2094:1;2091;2084:12;2064:34;2132:6;2121:9;2117:22;2107:32;;2177:7;2170:4;2166:2;2162:13;2158:27;2148:55;;2199:1;2196;2189:12;2148:55;2239:2;2226:16;2265:2;2257:6;2254:14;2251:34;;;2281:1;2278;2271:12;2251:34;2334:7;2329:2;2319:6;2316:1;2312:14;2308:2;2304:23;2300:32;2297:45;2294:65;;;2355:1;2352;2345:12;2294:65;1428:992;;;;-1:-1:-1;1428:992:22;;-1:-1:-1;2386:2:22;2378:11;;2408:6;1428:992;-1:-1:-1;;;1428:992:22:o;2425:556::-;2647:2;2632:18;;2672:20;;2701:31;2672:20;2701:31;:::i;:::-;2751:42;2831:2;2824:5;2820:14;2809:9;2802:33;2915:6;2877:36;2907:4;2899:6;2895:17;2877:36;:::i;:::-;2873:49;2866:4;2855:9;2851:20;2844:79;2971:2;2963:6;2959:15;2954:2;2943:9;2939:18;2932:43;;;2425:556;;;;;:::o;2986:1184::-;3290:4;3338:3;3327:9;3323:19;3361:42;3442:2;3434:6;3430:15;3419:9;3412:34;3465:2;3486:6;3540:2;3532:6;3528:15;3523:2;3512:9;3508:18;3501:43;3563:2;3601:3;3596:2;3585:9;3581:18;3574:31;3625:6;3655;3647;3640:22;3693:3;3682:9;3678:19;3671:26;;3720:6;3706:20;;3744:1;3754:338;3768:6;3765:1;3762:13;3754:338;;;3843:6;3830:20;3863:31;3888:5;3863:31;:::i;:::-;3919:14;;3907:27;;4008:2;3972:34;3990:15;;;3972:34;:::i;:::-;3968:43;3954:12;;;3947:65;4067:15;;;;4032:12;;;;3790:1;3783:9;3754:338;;;3758:3;4109;4101:11;;;;;;4160:2;4152:6;4148:15;4143:2;4132:9;4128:18;4121:43;;;2986:1184;;;;;;;;:::o
Swarm Source
none://none
Loading...
Loading
Loading...
Loading

Multichain Portfolio | 34 Chains
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.