creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/AuthorizedTransferSecurityRegistryCreator.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.24;\n\nimport {\n    ImmutableCreate2FactoryInterface\n} from \"seaport-types/src/interfaces/ImmutableCreate2FactoryInterface.sol\";\n\nimport {\n    IAuthorizedTransferSecurityRegistry\n} from \"./interfaces/IAuthorizedTransferSecurityRegistry.sol\";\n\n/// @title AuthorizedTransferSecurityRegistryCreator\n/// @dev Deploys and configures AuthorizedTransferSecurityRegistry contracts.\ncontract AuthorizedTransferSecurityRegistryCreator {\n    ImmutableCreate2FactoryInterface private constant factory = (\n        ImmutableCreate2FactoryInterface(\n            0x0000000000FFe8B47B3e2130213B802212439497\n        )\n    );\n\n    error UNAUTHORIZED();\n\n    function _canDeploy() internal view returns (bool) {\n        return \n            tx.origin == address(0x939C8d89EBC11fA45e576215E2353673AD0bA18A) ||\n            tx.origin == address(0xe80a65eB7a3018DedA407e621Ef5fb5B416678CA) ||\n            tx.origin == address(0x86D26897267711ea4b173C8C124a0A73612001da) ||\n            tx.origin == address(0xbF81D02F3Ee59E79af3D9337a186F65c9faE39F3);\n    }\n\n    function deployAndConfigure(\n        address initialOwner,\n        bytes32 salt,\n        bytes memory initializationCode,\n        address[] memory authorizers,\n        address[] memory operators\n    ) external returns (address registry) {\n        if (!_canDeploy()) {\n            revert UNAUTHORIZED();\n        }\n\n        IAuthorizedTransferSecurityRegistry registryContract = (\n            IAuthorizedTransferSecurityRegistry(\n                factory.safeCreate2(salt, initializationCode)\n            )\n        );\n\n        // Note: in provided init code, this contract must be supplied\n        // as the default owner so that it can perform configuration and\n        // reassign ownership of the default list to the supplied owner.\n        if (authorizers.length > 0) {\n            registryContract.addAuthorizers(0, authorizers);\n        }\n        if (operators.length > 0) {\n            registryContract.addOperators(0, operators);\n        }\n        registryContract.reassignOwnershipOfList(0, initialOwner);\n\n        return address(registryContract);\n    }\n}"
      },
      "lib/seaport-types/src/interfaces/ImmutableCreate2FactoryInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\n/**\n * @title ImmutableCreate2FactoryInterface\n * @author 0age\n * @notice This contract provides a safeCreate2 function that takes a salt value\n *         and a block of initialization code as arguments and passes them into\n *         inline assembly. The contract prevents redeploys by maintaining a\n *         mapping of all contracts that have already been deployed, and\n *         prevents frontrunning or other collisions by requiring that the first\n *         20 bytes of the salt are equal to the address of the caller (this can\n *         be bypassed by setting the first 20 bytes to the null address). There\n *         is also a view function that computes the address of the contract\n *         that will be created when submitting a given salt or nonce along with\n *         a given block of initialization code.\n */\ninterface ImmutableCreate2FactoryInterface {\n    /**\n     * @dev Create a contract using CREATE2 by submitting a given salt or nonce\n     *      along with the initialization code for the contract. Note that the\n     *      first 20 bytes of the salt must match those of the calling address,\n     *      which prevents contract creation events from being submitted by\n     *      unintended parties.\n     *\n     * @param salt               The nonce that will be passed into the CREATE2\n     *                           call.\n     * @param initializationCode The initialization code that will be passed\n     *                           into the CREATE2 call.\n     *\n     * @return deploymentAddress Address of the contract that will be created.\n     */\n    function safeCreate2(\n        bytes32 salt,\n        bytes calldata initializationCode\n    ) external payable returns (address deploymentAddress);\n\n    /**\n     * @dev Compute the address of the contract that will be created when\n     *      submitting a given salt or nonce to the contract along with the\n     *      contract's initialization code. The CREATE2 address is computed in\n     *      accordance with EIP-1014, and adheres to the formula therein of\n     *      `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]`\n     *      when performing the computation. The computed address is then\n     *      checked for any existing contract code - if so, the null address\n     *      will be returned instead.\n     *\n     * @param salt     The nonce passed into the CREATE2 address calculation.\n     * @param initCode The contract initialization code to be used that will be\n     *                 passed into the CREATE2 address calculation.\n     *\n     * @return deploymentAddress Address of the contract that will be created,\n     *                           or the null address if a contract already\n     *                           exists at that address.\n     */\n    function findCreate2Address(\n        bytes32 salt,\n        bytes calldata initCode\n    ) external view returns (address deploymentAddress);\n\n    /**\n     * @dev Compute the address of the contract that will be created when\n     *      submitting a given salt or nonce to the contract along with the\n     *      keccak256 hash of the contract's initialization code. The CREATE2\n     *      address is computed in accordance with EIP-1014, and adheres to the\n     *      `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]`\n     *      formula when performing the computation. The computed address is\n     *      then checked for any existing contract code - if so, the null\n     *      address will be returned instead.\n     *\n     * @param salt         The nonce passed into the CREATE2 address\n     *                     calculation.\n     * @param initCodeHash The keccak256 hash of the initialization code that\n     *                     will be passed into the CREATE2 address calculation.\n     *\n     * @return deploymentAddress Address of the contract that will be created,\n     *                           or the null address if a contract already\n     *                           exists at that address.\n     */\n    function findCreate2AddressViaHash(\n        bytes32 salt,\n        bytes32 initCodeHash\n    ) external view returns (address deploymentAddress);\n\n    /**\n     * @dev Determine if a contract has already been deployed by the factory to\n     *      a given address.\n     *\n     * @param deploymentAddress The contract address to check.\n     *\n     * @return True if the contract has been deployed, false otherwise.\n     */\n    function hasBeenDeployed(\n        address deploymentAddress\n    ) external view returns (bool);\n}\n"
      },
      "src/interfaces/IAuthorizedTransferSecurityRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nenum ListTypes {\n    AuthorizerList,\n    OperatorList\n}\n\n/// @title IAuthorizedTransferSecurityRegistry\n/// @dev Interface for the Authorized Transfer Security Registry, a simplified version of the Transfer\n///      Security Registry that only supports authorizers and whitelisted operators, and assumes a\n///      security level of OperatorWhitelistEnableOTC + authorizers for all collections that use it.\n///      Note that a number of view functions on collections that add this validator will not work.\ninterface IAuthorizedTransferSecurityRegistry {\n    event CreatedList(uint256 indexed id, string name);\n    event AppliedListToCollection(address indexed collection, uint120 indexed id);\n    event ReassignedListOwnership(uint256 indexed id, address indexed newOwner);\n    event AddedAccountToList(ListTypes indexed kind, uint256 indexed id, address indexed account);\n    event RemovedAccountFromList(ListTypes indexed kind, uint256 indexed id, address indexed account);\n\n    error AuthorizedTransferSecurityRegistry__ListDoesNotExist();\n    error AuthorizedTransferSecurityRegistry__CallerDoesNotOwnList();\n    error AuthorizedTransferSecurityRegistry__ArrayLengthCannotBeZero();\n    error AuthorizedTransferSecurityRegistry__CallerMustHaveElevatedPermissionsForSpecifiedNFT();\n    error AuthorizedTransferSecurityRegistry__ListOwnershipCannotBeTransferredToZeroAddress();\n    error AuthorizedTransferSecurityRegistry__ZeroAddressNotAllowed();\n    error AuthorizedTransferSecurityRegistry__UnauthorizedTransfer();\n    error AuthorizedTransferSecurityRegistry__CallerIsNotValidAuthorizer();\n\n    /// Manage lists of authorizers & operators that can be applied to collections\n    function createList(string calldata name) external returns (uint120);\n    function createListCopy(string calldata name, uint120 sourceListId) external returns (uint120);\n    function reassignOwnershipOfList(uint120 id, address newOwner) external;\n    function renounceOwnershipOfList(uint120 id) external;\n    function applyListToCollection(address collection, uint120 id) external;\n    function listOwners(uint120 id) external view returns (address);\n\n    /// Manage and query for authorizers on lists\n    function addAuthorizers(uint120 id, address[] calldata accounts) external;\n    function removeAuthorizers(uint120 id, address[] calldata accounts) external;\n    function getAuthorizers(uint120 id) external view returns (address[] memory);\n    function isAuthorizer(uint120 id, address account) external view returns (bool);\n    function getAuthorizersByCollection(address collection) external view returns (address[] memory);\n    function isAuthorizerByCollection(address collection, address account) external view returns (bool);\n\n    /// Manage and query for operators on lists\n    function addOperators(uint120 id, address[] calldata accounts) external;\n    function removeOperators(uint120 id, address[] calldata accounts) external;\n    function getOperators(uint120 id) external view returns (address[] memory);\n    function isOperator(uint120 id, address account) external view returns (bool);\n    function getOperatorsByCollection(address collection) external view returns (address[] memory);\n    function isOperatorByCollection(address collection, address account) external view returns (bool);\n\n    /// Ensure that a specific operator has been authorized to transfer tokens\n    function validateTransfer(address caller, address from, address to) external view;\n\n    /// Ensure that a transfer has been authorized for a specific tokenId\n    function validateTransfer(address caller, address from, address to, uint256 tokenId) external view;\n\n    /// Ensure that a transfer has been authorized for a specific amount of a specific tokenId, and\n    /// reduce the transferable amount remaining\n    function validateTransfer(address caller, address from, address to, uint256 tokenId, uint256 amount) external;\n\n    /// Legacy alias for validateTransfer (address caller, address from, address to)\n    function applyCollectionTransferPolicy(address caller, address from, address to) external view;\n\n    /// Temporarily assign a specific allowed operator for a given collection\n    function beforeAuthorizedTransfer(address operator, address token) external;\n\n    /// Clear assignment of a specific allowed operator for a given collection\n    function afterAuthorizedTransfer(address token) external;\n\n    /// Temporarily allow a specific tokenId from a given collection to be transferred\n    function beforeAuthorizedTransfer(address token, uint256 tokenId) external;\n\n    /// Clear assignment of an specific tokenId's transfer allowance\n    function afterAuthorizedTransfer(address token, uint256 tokenId) external;\n\n    /// Temporarily allow a specific amount of a specific tokenId from a given collection to be transferred\n    function beforeAuthorizedTransferWithAmount(address token, uint256 tokenId, uint256 amount) external;\n\n    /// Clear assignment of a tokenId's transfer allowance for a specific amount\n    function afterAuthorizedTransferWithAmount(address token, uint256 tokenId) external;\n}"
      }
    },
    "settings": {
      "remappings": [
        "seaport-core/=lib/seaport-core/",
        "seaport-types/=lib/seaport-types/",
        "seaport-sol/=lib/seaport-sol/src/",
        "seaport-deploy/=lib/seaport-deploy/src/",
        "solady/=lib/solady/",
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "@limitbreak/creator-token-standards/=lib/creator-token-standards/src/",
        "@rari-capital/solmate/=lib/seaport-sol/lib/seaport/lib/solmate/",
        "ERC721A/=lib/creator-token-standards/lib/ERC721A/contracts/",
        "creator-token-standards/=lib/creator-token-standards/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/seaport-sol/lib/seaport/lib/openzeppelin-contracts/lib/erc4626-tests/",
        "erc721a/=lib/creator-token-standards/lib/ERC721A/",
        "forge-std/=lib/forge-std/src/",
        "murky/=lib/creator-token-standards/lib/murky/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "seaport/=lib/seaport-sol/lib/seaport/contracts/",
        "solarray/=lib/seaport-sol/lib/solarray/src/",
        "solmate/=lib/seaport-sol/lib/seaport/lib/solmate/src/",
        "tstorish/=lib/tstorish/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 9999999
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "cancun",
      "viaIR": false,
      "libraries": {}
    }
  }}