{
  "language": "Solidity",
  "sources": {
    "contracts/CCFF00Plants.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nimport {ERC721} from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\nimport {ERC2981} from \"@openzeppelin/contracts/token/common/ERC2981.sol\";\nimport {ReentrancyGuard} from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {Base64} from \"@openzeppelin/contracts/utils/Base64.sol\";\nimport {PlantTypes,IPlantRenderer} from \"./PlantTypes.sol\";\n\n/// @notice Fixed-allocation plants, gas-only actions and fixed 2.5% sale royalties.\n/// Ownership is creator attribution only. No upgrade, arbitrary mint, burn,\n/// fertility reset, royalty setter or renderer setter exists.\ncontract CCFF00Plants is ERC721, ERC2981, ReentrancyGuard, Ownable2Step {\n    uint96 public constant ROYALTY_BPS=250;\n    uint256 public immutable GENESIS_SUPPLY;\n    uint256 public immutable MAX_SUPPLY;\n    uint256 public constant MATURITY=90 days;\n    uint256 public constant PRUNE_INTERVAL=30 days;\n    IPlantRenderer public immutable renderer;\n    bytes32 public immutable allocationCommitment;\n    address[] public genesisRecipients;\n    uint16 public genesisMinted;\n    uint16 public offspringMinted;\n    mapping(uint256=>PlantTypes.Plant) private plants;\n    mapping(uint256=>uint64) public revision;\n    mapping(uint64=>bool) public usedGenome;\n    struct Offer { uint16 a; uint16 b; address ownerA; address ownerB; address recipient; uint64 revisionA; uint64 revisionB; uint64 deadline; uint64 genome; }\n    mapping(uint256=>Offer) public offers;\n    event MetadataUpdate(uint256 _tokenId);\n    event BatchMetadataUpdate(uint256 _fromTokenId,uint256 _toTokenId);\n    event PairProposed(uint256 indexed a,uint256 indexed b,address indexed recipient,uint64 deadline,uint64 genome);\n    event PairCancelled(uint256 indexed a);\n    event Pollinated(uint256 indexed a,uint256 indexed b,uint256 indexed child,address recipient,uint64 genome);\n    event Pruned(uint256 indexed tokenId,uint8 branch,uint64 timestamp);\n    error InvalidPair(); error NotOwner(); error Immature(); error AlreadyPollinated(); error StaleOffer(); error BadRecipient(); error BadGenesis(); error BadPrune(); error PreviewChanged();\n\n    constructor(address renderer_,address[] memory recipients,bytes32 snapshotCommitment,address royaltyRecipient)\n        ERC721(\"CCFF00 PLANTS\",\"PLANTS\") Ownable(royaltyRecipient) {\n        require(renderer_.code.length>0 && snapshotCommitment!=bytes32(0),\"CONFIG\");\n        _setDefaultRoyalty(royaltyRecipient,ROYALTY_BPS);\n        require(recipients.length>=2 && recipients.length<=128 && IPlantRenderer(renderer_).assetCount()==recipients.length,\"COUNT\");\n        GENESIS_SUPPLY=recipients.length;MAX_SUPPLY=2*recipients.length-1;\n        renderer=IPlantRenderer(renderer_); allocationCommitment=keccak256(abi.encode(recipients,snapshotCommitment));\n        for(uint256 i;i<recipients.length;++i){if(recipients[i]==address(0))revert BadRecipient();genesisRecipients.push(recipients[i]);usedGenome[_genesisGenome(i)]=true;}\n    }\n    function _genesisGenome(uint256 i) internal pure returns(uint64){ return uint64(i | (i<<8) | (i<<16)); }\n    function totalSupply() public view returns(uint256){return uint256(genesisMinted)+offspringMinted;}\n    function plant(uint256 id) external view returns(PlantTypes.Plant memory){_requireOwned(id);return plants[id];}\n    function isEligible(uint256 id) external view returns(bool){_requireOwned(id);return !plants[id].pollinated && block.timestamp>=uint256(plants[id].born)+MATURITY;}\n    function supportsInterface(bytes4 id) public view override(ERC721,ERC2981) returns(bool){return id==0x49064906||id==0x7f5828d0||super.supportsInterface(id);}\n    /// @notice Immutable, self-contained collection metadata for marketplaces.\n    function contractURI() external pure returns(string memory){\n        string memory icon=Base64.encode(bytes('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 160 160\" shape-rendering=\"crispEdges\"><rect width=\"160\" height=\"160\" fill=\"#080b08\"/><path d=\"M78 120h4V70h-4zM78 90H58V70h-4v24h24zM82 80h20V54h-4v22H82z\" fill=\"#678900\"/><path d=\"M74 48h12v12H74zM50 60h12v12H50zM94 44h12v12H94zM78 124h4v4h-4z\" fill=\"#ccff00\"/></svg>'));\n        bytes memory json=bytes(string.concat('{\"name\":\"CCFF00 PLANTS\",\"description\":\"128 Genesis pixel plants for qualifying CCFF00 holders. Full growth in 90 days, calendar seasons, annual bloom and growth rings. Any two mature unpollinated plants can create one offspring; each plant pairs once. Maximum lifetime supply: 255. Breeding and pruning cost gas only.\",\"image\":\"data:image/svg+xml;base64,',icon,'\"}'));\n        return string.concat('data:application/json;base64,',Base64.encode(json));\n    }\n    function tokenURI(uint256 id) public view override returns(string memory){_requireOwned(id);return renderer.tokenURI(id,plants[id],block.timestamp);}\n    function previewArt(uint64 genome,uint256 ageDays,uint256 atTime) external view returns(string memory){\n        require(ageDays<=36500 && atTime>=ageDays*1 days,\"PREVIEW\");\n        PlantTypes.Plant memory p; p.genome=genome;p.born=uint64(atTime-ageDays*1 days);\n        return renderer.svg(p,atTime);\n    }\n    /// @notice Anyone can pay for delivery, but only to the immutable recipient.\n    /// Already-issued IDs are skipped. A rejecting receiver rolls back this batch;\n    /// deliver other IDs separately and let the recipient redirect their own ID.\n    function airdrop(uint16[] calldata ids) external nonReentrant {\n        require(ids.length>0 && ids.length<=16,\"BATCH\");\n        for(uint256 i;i<ids.length;++i){uint256 id=ids[i];if(id==0||id>GENESIS_SUPPLY)revert BadGenesis();if(_ownerOf(id)==address(0))_genesis(id,genesisRecipients[id-1]);}\n    }\n    function claimGenesis(uint16 id,address recipient) external nonReentrant {\n        if(id==0||id>GENESIS_SUPPLY||_ownerOf(id)!=address(0))revert BadGenesis();\n        if(msg.sender!=genesisRecipients[id-1])revert NotOwner();if(recipient==address(0))revert BadRecipient();_genesis(id,recipient);\n    }\n    function _genesis(uint256 id,address recipient) private {\n        PlantTypes.Plant memory p;p.genome=_genesisGenome(id-1);p.born=uint64(block.timestamp);plants[id]=p;++genesisMinted;_safeMint(recipient,id);\n    }\n    function _eligible(uint256 a,uint256 b) private view {\n        if(a==b)revert InvalidPair();_requireOwned(a);_requireOwned(b);\n        if(plants[a].pollinated||plants[b].pollinated)revert AlreadyPollinated();\n        if(block.timestamp<uint256(plants[a].born)+MATURITY||block.timestamp<uint256(plants[b].born)+MATURITY)revert Immature();\n    }\n    /// @notice Predictable inherited genome. No caller salt, timestamp or tx-order entropy.\n    /// At most 255 genomes can be occupied; 256 mutation variants guarantee a free\n    /// encoded genome. This does not by itself prove perceptual artwork uniqueness.\n    function previewPair(uint256 a,uint256 b) public view returns(uint64 genome) {\n        if(a==b)revert InvalidPair();_requireOwned(a);_requireOwned(b);if(a>b)(a,b)=(b,a);\n        uint64 ga=plants[a].genome;uint64 gb=plants[b].genome;\n        uint256 h=uint256(keccak256(abi.encode(\"CCFF00_PLANTS_GENETICS_V1\",a,b,ga,gb)));\n        uint8 bodyA=uint8(ga>>(h&1==0?0:8));uint8 bodyB=uint8(gb>>(h&2==0?0:8));uint8 root=uint8((h&4==0?ga:gb)>>16);\n        uint64 base=uint64(bodyA)|(uint64(bodyB)<<8)|(uint64(root)<<16)|(uint64(1+(h>>8)%3)<<24);\n        for(uint256 i;i<256;++i){genome=base|(uint64(uint8((h>>16)+i))<<32);if(!usedGenome[genome])return genome;}\n        revert InvalidPair();\n    }\n    function pair(uint16 a,uint16 b,address recipient,uint64 expectedGenome) external nonReentrant returns(uint256){\n        _eligible(a,b);if(ownerOf(a)!=msg.sender||ownerOf(b)!=msg.sender)revert NotOwner();return _pair(a,b,recipient,expectedGenome);\n    }\n    function proposePair(uint16 a,uint16 b,address recipient,uint64 deadline,uint64 expectedGenome) external {\n        _eligible(a,b);if(ownerOf(a)!=msg.sender)revert NotOwner();if(recipient==address(0))revert BadRecipient();\n        require(deadline>block.timestamp && deadline<=block.timestamp+30 days,\"EXPIRY\");\n        if(previewPair(a,b)!=expectedGenome)revert PreviewChanged();\n        ++revision[a];offers[a]=Offer(a,b,msg.sender,ownerOf(b),recipient,revision[a],revision[b],deadline,expectedGenome);\n        emit PairProposed(a,b,recipient,deadline,expectedGenome);\n    }\n    function cancelPair(uint256 a) external {if(ownerOf(a)!=msg.sender)revert NotOwner();++revision[a];delete offers[a];emit PairCancelled(a);}\n    function acceptPair(uint256 a) external nonReentrant returns(uint256){\n        Offer memory o=offers[a];if(o.ownerA==address(0)||block.timestamp>o.deadline)revert StaleOffer();\n        if(msg.sender!=o.ownerB)revert NotOwner();\n        if(ownerOf(o.a)!=o.ownerA||ownerOf(o.b)!=o.ownerB||revision[o.a]!=o.revisionA||revision[o.b]!=o.revisionB)revert StaleOffer();\n        _eligible(o.a,o.b);delete offers[a];return _pair(o.a,o.b,o.recipient,o.genome);\n    }\n    function _pair(uint16 a,uint16 b,address recipient,uint64 expected) private returns(uint256 id){\n        if(recipient==address(0))revert BadRecipient();if(previewPair(a,b)!=expected)revert PreviewChanged();\n        require(offspringMinted<GENESIS_SUPPLY-1,\"SUPPLY\");plants[a].pollinated=true;plants[b].pollinated=true;++revision[a];++revision[b];\n        usedGenome[expected]=true;id=GENESIS_SUPPLY+1+offspringMinted;++offspringMinted;\n        PlantTypes.Plant memory p;p.genome=expected;p.born=uint64(block.timestamp);p.parentA=a<b?a:b;p.parentB=a<b?b:a;\n        p.generation=1+(plants[a].generation>plants[b].generation?plants[a].generation:plants[b].generation);plants[id]=p;\n        _safeMint(recipient,id);emit MetadataUpdate(a);emit MetadataUpdate(b);emit Pollinated(a,b,id,recipient,expected);\n    }\n    /// @notice Trim one of four bounded foliage sectors. Protected structure,\n    /// roots and central trunk are never removed. The renderer regrows it in 30 days.\n    function prune(uint256 id,uint8 branch) external {\n        if(ownerOf(id)!=msg.sender)revert NotOwner();PlantTypes.Plant storage p=plants[id];\n        if(block.timestamp<uint256(p.born)+MATURITY)revert Immature();\n        if(branch>3 || (p.prunedAt!=0 && block.timestamp<uint256(p.prunedAt)+PRUNE_INTERVAL))revert BadPrune();\n        if((renderer.prunableBranches(p.genome)&(uint8(1)<<branch))==0)revert BadPrune();\n        p.prunedAt=uint64(block.timestamp);p.pruneBranch=branch;emit Pruned(id,branch,p.prunedAt);emit MetadataUpdate(id);\n    }\n    /// @notice Optional cache refresh signal; read-time growth needs no caller.\n    function refresh(uint256 id) external {_requireOwned(id);emit MetadataUpdate(id);}\n    function _update(address to,uint256 id,address auth) internal override returns(address from){from=super._update(to,id,auth);++revision[id];delete offers[id];}\n}\n"
    },
    "contracts/PixelBank.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.26;\r\nimport {LibZip} from \"solady/src/utils/LibZip.sol\";\r\n\r\n/// @notice Lossless column-transposed FastLZ storage for the same pixel records.\r\n/// Compressed payloads are immutable, prepared and validated before deployment.\r\ncontract PixelData {\r\n    constructor(bytes memory payload) {\r\n        require(payload.length > 0 && payload.length <= 24000, \"DATA_SIZE\");\r\n        bytes memory runtime = bytes.concat(hex\"00\", payload);\r\n        assembly (\"memory-safe\") { return(add(runtime, 32), mload(runtime)) }\r\n    }\r\n}\r\n\r\n\r\ncontract PixelBank {\r\n    struct Entry {address pointer;uint24 offset;uint16 length;}\r\n    Entry[] private entries;\r\n    uint8 public immutable count;\r\n    bytes32 public immutable artworkCommitment;\r\n    constructor(Entry[] memory data,bytes32 commitment){\r\n        require(data.length==128 && commitment!=bytes32(0),\"CONFIG\");\r\n        count=128;artworkCommitment=commitment;\r\n        for(uint256 i;i<data.length;i++){Entry memory e=data[i];require(e.offset>=1&&e.length>0&&uint256(e.offset)+e.length<=e.pointer.code.length,\"ENTRY\");entries.push(e);}\r\n    }\r\n    function entry(uint8 id) external view returns(Entry memory){require(id<count,\"ID\");return entries[id];}\r\n    function readColumns(uint8 id) public view returns(bytes memory columns){\r\n        require(id<count,\"ID\");Entry memory e=entries[id];bytes memory packed=new bytes(e.length);address target=e.pointer;uint256 offset=e.offset;uint256 length=e.length;\r\n        assembly (\"memory-safe\") {extcodecopy(target,add(packed,32),offset,length)}\r\n        columns=LibZip.flzDecompress(packed);\r\n        length=columns.length;require(length>0&&length<=24000&&length%6==0,\"DECODE\");\r\n    }\r\n    function read(uint8 id) external view returns(bytes memory data){\r\n        bytes memory columns=readColumns(id);data=new bytes(columns.length);uint256 pixels=columns.length/6;\r\n        assembly (\"memory-safe\") {\r\n            let source:=add(columns,32) let dest:=add(data,32)\r\n            for {let i:=0} lt(i,pixels) {i:=add(i,1)} {\r\n                let input:=add(source,i) let output:=add(dest,mul(i,6))\r\n                mstore8(output,byte(0,mload(input)))\r\n                mstore8(add(output,1),byte(0,mload(add(input,pixels))))\r\n                mstore8(add(output,2),byte(0,mload(add(input,mul(pixels,2)))))\r\n                mstore8(add(output,3),byte(0,mload(add(input,mul(pixels,3)))))\r\n                mstore8(add(output,4),byte(0,mload(add(input,mul(pixels,4)))))\r\n                mstore8(add(output,5),byte(0,mload(add(input,mul(pixels,5)))))\r\n            }\r\n        }\r\n    }\r\n}\r\n"
    },
    "contracts/PlantCalendar.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nlibrary PlantCalendar {\n    // Gregorian civil date algorithm, with bounded constant work.\n    function date(uint256 timestamp) internal pure returns (uint256 year, uint256 month, uint256 day) {\n        uint256 z=timestamp/1 days + 719468;\n        uint256 era=z/146097; uint256 doe=z-era*146097;\n        uint256 yoe=(doe-doe/1460+doe/36524-doe/146096)/365;\n        year=yoe+era*400; uint256 doy=doe-(365*yoe+yoe/4-yoe/100);\n        uint256 mp=(5*doy+2)/153; day=doy-(153*mp+2)/5+1;\n        month=mp<10?mp+3:mp-9; if(month<=2) ++year;\n    }\n    // Common-year seasonal day, Feb 29 shares Feb 28; UTC, Northern Hemisphere.\n    function dayOfYear(uint256 timestamp) internal pure returns (uint256 n) {\n        (,uint256 month,uint256 day)=date(timestamp);\n        uint16[12] memory starts=[uint16(0),31,59,90,120,151,181,212,243,273,304,334];\n        if(month==2 && day==29) day=28;\n        n=starts[month-1]+day-1;\n    }\n    function yearsOld(uint256 born,uint256 now_) internal pure returns(uint256 age) {\n        if(now_<=born)return 0;\n        (uint256 by,uint256 bm,uint256 bd)=date(born); (uint256 y,uint256 m,uint256 d)=date(now_);\n        if(bm==2 && bd==29)bd=28;\n        age=y-by; if(m<bm || (m==bm && d<bd))--age;\n    }\n    function season(uint256 d) internal pure returns(uint256) { return d<59||d>=334?3:d<151?0:d<243?1:2; }\n    function lush(uint256 day) internal pure returns(uint256) {\n        uint16[8] memory ds=[uint16(0),59,105,151,242,287,334,365];\n        uint16[8] memory ls=[uint16(35),35,500,1000,1000,450,35,35];\n        for(uint256 i=1;i<8;++i)if(day<=ds[i]){\n            uint256 u=(day-ds[i-1])*1000/(ds[i]-ds[i-1]); uint256 smooth=u*u*(3000-2*u)/1000000;\n            return ls[i]>=ls[i-1]?ls[i-1]+(ls[i]-ls[i-1])*smooth/1000:ls[i-1]-(ls[i-1]-ls[i])*smooth/1000;\n        }\n        return 35;\n    }\n}\n"
    },
    "contracts/PlantRenderer.sol": {
      "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.26;\r\nimport {Base64} from \"@openzeppelin/contracts/utils/Base64.sol\";\r\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\r\nimport {PixelBank} from \"./PixelBank.sol\";\r\nimport {PlantTypes,IPlantRenderer} from \"./PlantTypes.sol\";\r\nimport {PlantCalendar} from \"./PlantCalendar.sol\";\r\n\r\n/// @notice Exact packed Genesis geometry; bounded compositional hybrid renderer.\r\ncontract PlantRenderer is IPlantRenderer {\r\n    using Strings for uint256;\r\n    PixelBank public immutable bank;\r\n    uint8 public immutable assetCount;\r\n    struct Buffer {bytes data;uint256 used;}\r\n    struct View {uint256 age;uint256 day;uint256 lush;uint256 season;uint256 regrowth;uint256 rings;uint8 cut;bool bloom;}\r\n    constructor(address bank_){require(bank_.code.length>0,\"BANK\");bank=PixelBank(bank_);assetCount=PixelBank(bank_).count();}\r\n    function _view(PlantTypes.Plant memory p,uint256 at) private pure returns(View memory v){\r\n        v.age=at>p.born?(at-p.born)/1 days:0;if(v.age>90)v.age=90;\r\n        v.day=PlantCalendar.dayOfYear(at);v.lush=PlantCalendar.lush(v.day);v.season=PlantCalendar.season(v.day);\r\n        v.regrowth=p.prunedAt==0||at>=uint256(p.prunedAt)+30 days?1000:at<=p.prunedAt?0:(at-p.prunedAt)*1000/30 days;\r\n        v.cut=p.pruneBranch;v.rings=PlantCalendar.yearsOld(p.born,at);\r\n        v.bloom=v.age==90 && (v.day+365-uint256(keccak256(abi.encode(p.genome)))%365)%365<14;\r\n    }\r\n    function calendar(uint256 t) external pure returns(uint256 year,uint256 month,uint256 day,uint256 seasonalDay){(year,month,day)=PlantCalendar.date(t);seasonalDay=PlantCalendar.dayOfYear(t);}\r\n    function phenotype(PlantTypes.Plant calldata p,uint256 at) external pure returns(uint256 age,uint256 season,bool blooming,uint256 rings,uint256 regrowth){View memory v=_view(p,at);return(v.age,v.season,v.bloom,v.rings,v.regrowth);}\r\n    function _pixel(Buffer memory b,uint256 x,uint256 y) private pure {\r\n        if(x<3||x>156||y<4||y>174)return;\r\n        // All color buffers share one raster. Paths paint dark to light, so the\r\n        // highest color at an overlapping coordinate is the visible result.\r\n        uint256 index=y*160+x;uint8 color=uint8(b.used);\r\n        if(uint8(b.data[index])<color)b.data[index]=bytes1(color);\r\n    }\r\n    function _paths(Buffer memory b) private pure returns(bytes[4] memory data){\r\n        bytes memory raster=b.data;\r\n        uint256[4] memory counts;uint256[4] memory cursors;\r\n        // Two bounded scans for all colors, allocating only horizontal runs.\r\n        assembly (\"memory-safe\") {\r\n            function decimal(out,n) -> end {\r\n                if gt(n,99) {mstore8(out,add(48,div(n,100))) out:=add(out,1)}\r\n                if gt(n,9) {mstore8(out,add(48,mod(div(n,10),10))) out:=add(out,1)}\r\n                mstore8(out,add(48,mod(n,10))) end:=add(out,1)\r\n            }\r\n            let start:=add(raster,32)\r\n            for {let y:=4} lt(y,175) {y:=add(y,1)} {\r\n                let row:=add(start,mul(y,160))\r\n                let prev:=0\r\n                for {let x:=3} lt(x,157) {x:=add(x,1)} {\r\n                    let c:=byte(0,mload(add(row,x)))\r\n                    if and(iszero(iszero(c)),iszero(eq(c,prev))) {let slot:=add(counts,mul(sub(c,1),32)) mstore(slot,add(mload(slot),1))}\r\n                    prev:=c\r\n                }\r\n            }\r\n            for {let i:=0} lt(i,4) {i:=add(i,1)} {\r\n                let out:=mload(0x40) let slot:=mul(i,32)\r\n                mstore(add(data,slot),out) mstore(add(cursors,slot),add(out,32))\r\n                mstore(0x40,and(add(add(out,32),add(mul(mload(add(counts,slot)),23),31)),not(31)))\r\n            }\r\n            for {let y:=4} lt(y,175) {y:=add(y,1)} {\r\n                let row:=add(start,mul(y,160))\r\n                for {let x:=3} lt(x,157) {} {\r\n                    let c:=byte(0,mload(add(row,x)))\r\n                    switch c\r\n                    case 0 {x:=add(x,1)}\r\n                    default {\r\n                        let first:=x\r\n                        for {} and(lt(x,157),eq(byte(0,mload(add(row,x))),c)) {x:=add(x,1)} {}\r\n                        let width:=sub(x,first) let slot:=add(cursors,mul(sub(c,1),32)) let out:=mload(slot)\r\n                        mstore8(out,77) out:=decimal(add(out,1),first)\r\n                        mstore8(out,32) out:=decimal(add(out,1),y)\r\n                        mstore8(out,104) out:=decimal(add(out,1),width)\r\n                        mstore8(out,118) mstore8(add(out,1),49) mstore8(add(out,2),104) mstore8(add(out,3),45)\r\n                        out:=decimal(add(out,4),width)\r\n                        mstore8(out,122) mstore(slot,add(out,1))\r\n                    }\r\n                }\r\n            }\r\n            for {let i:=0} lt(i,4) {i:=add(i,1)} {let slot:=mul(i,32) let out:=mload(add(data,slot)) mstore(out,sub(mload(add(cursors,slot)),add(out,32)))}\r\n        }\r\n    }\r\n    function _visible(bytes memory data,uint256 i,View memory v,uint256 x,uint256 y,uint256 renderAge) private pure returns(bool,uint256){ unchecked { \r\n        uint256 n=data.length/6;\r\n        if(uint8(data[i+n*2])>renderAge)return(false,0);\r\n        uint256 meta=uint8(data[i+n*3]);uint256 kind=meta>>2;uint256 color=meta&3;\r\n        uint256 rank=(uint256(uint8(data[i+n*4]))<<8)|uint8(data[i+n*5]);\r\n        if(kind>0){uint256 amount=v.lush;\r\n            // rank <= lush^1.6, compared using bounded integer powers.\r\n            if(kind==2 && rank**5*1000000000>amount**8)return(false,0);\r\n            if(kind==3){uint256 delta=v.day>280?v.day-280:280-v.day;uint256 autumn=delta>=62?0:1000-delta*1000/62;if(autumn>amount)amount=autumn;amount=120+880*amount/1000;}\r\n            if(rank>amount)return(false,0);\r\n            uint256 branch=(x<80?0:1)+(y<76?0:2);\r\n            if(v.regrowth<1000 && branch==v.cut && y<128 && (x<75||x>85) && rank>=v.regrowth)return(false,0);\r\n        }\r\n        if(data[i+n*2]!=0){if(v.lush<170 && color>0)--color;if(kind>0 && v.season==2 && color>0)--color;}\r\n        return(true,color);\r\n     } }\r\n    function _layer(Buffer[4] memory buffers,bytes memory data,View memory v,uint256 mode,int256 ax,int256 ay,uint256 sx,uint256 sy) private pure { unchecked { \r\n        uint256 n=data.length/6;\r\n        uint256 renderAge=v.age;\r\n        if(mode==2){if(renderAge<=12)return;renderAge=(renderAge-12)*90/78;}\r\n        for(uint256 i;i<n;++i){uint256 ox=uint8(data[i]);uint256 oy=uint8(data[i+n*1]);if(mode==1&&oy<128)continue;if(mode==2&&oy>=128)continue;\r\n            int256 xx=ax+(int256(ox)-80)*int256(sx)/100;int256 yy=ay+(int256(oy)-128)*int256(sy)/100;\r\n            if(xx<4||xx>155||yy<5||yy>173)continue;uint256 x=uint256(xx);uint256 y=uint256(yy);\r\n            (bool visible,uint256 color)=_visible(data,i,v,x,y,renderAge);if(!visible)continue;_pixel(buffers[color],x,y);\r\n            if(v.bloom && (uint8(data[i+n*3])>>2)>0 && (ox*31+oy*17)%113==0){_pixel(buffers[3],x+1,y);_pixel(buffers[3],x,y+1);}\r\n        }\r\n     } }\r\n    function _line(Buffer memory b,int256 ax,int256 ay,int256 bx,int256 by) private pure {\r\n        int256 dx=bx-ax;int256 dy=by-ay;uint256 n=uint256(dx<0?-dx:dx);uint256 ny=uint256(dy<0?-dy:dy);if(ny>n)n=ny;if(n==0)n=1;\r\n        for(uint256 i;i<=n;++i)_pixel(b,uint256(ax+dx*int256(i)/int256(n)),uint256(ay+dy*int256(i)/int256(n)));\r\n    }\r\n    function _mask(bytes memory data,int256 ax,int256 ay,uint256 sx,uint256 sy) private pure returns(uint8 mask){ unchecked { \r\n        uint256 n=data.length/6;\r\n        for(uint256 i;i<n;++i){if(uint8(data[i+n*3])>>2==0||uint8(data[i+n*1])>=128)continue;\r\n            int256 x=ax+(int256(uint256(uint8(data[i])))-80)*int256(sx)/100;\r\n            int256 y=ay+(int256(uint256(uint8(data[i+n*1])))-128)*int256(sy)/100;\r\n            if(x<4||x>155||y<5||y>=128||(x>=75&&x<=85))continue;\r\n            uint8 branch=(x<80?0:1)+(y<76?0:2);mask|=uint8(1)<<branch;\r\n        }\r\n     } }\r\n    function prunableBranches(uint64 genome) external view returns(uint8){\r\n        uint8 a=uint8(genome);uint8 b=uint8(genome>>8);uint256 mode=(genome>>24)&255;uint256 mutation=uint8(genome>>32);\r\n        bytes memory da=bank.readColumns(a);if(mode==0)return _mask(da,80,128,100,100);bytes memory db=bank.readColumns(b);\r\n        int256 bend=int256(mutation%16)-8;uint256 height=55+mutation/16;\r\n        if(mode==1)return _mask(da,52+bend,113,50,65)|_mask(db,105+bend,108,52,height);\r\n        if(mode==2)return _mask(da,80+bend,117,70,height)|_mask(db,116,106,36,46);\r\n        require(mode==3,\"GENOME\");return _mask(da,45,122,35,49)|_mask(db,80+bend,112,45,height)|_mask(da,115,122,35,44);\r\n    }\r\n    function svg(PlantTypes.Plant calldata p,uint256 at) public view returns(string memory){\r\n        uint8 a=uint8(p.genome);uint8 b=uint8(p.genome>>8);uint8 root=uint8(p.genome>>16);uint256 mode=(p.genome>>24)&255;uint256 mutation=uint8(p.genome>>32);\r\n        require(a<assetCount&&b<assetCount&&root<assetCount&&mode<=3,\"GENOME\");View memory v=_view(p,at);\r\n        if(v.age==0)return '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 160 180\" shape-rendering=\"crispEdges\"><rect width=\"160\" height=\"180\" fill=\"#080b08\"/><path fill=\"#ccff00\" d=\"M80 128h1v1h-1z\"/></svg>';\r\n        bytes memory da=bank.readColumns(a);bytes memory db=mode==0?bytes(\"\"):b==a?da:bank.readColumns(b);bytes memory dr=mode==0?bytes(\"\"):root==a?da:root==b?db:bank.readColumns(root);\r\n        Buffer[4] memory paths;\r\n        bytes memory raster=new bytes(160*180);\r\n        for(uint256 i;i<4;++i){paths[i].data=raster;paths[i].used=i+1;}\r\n        if(mode==0)_layer(paths,da,v,0,80,128,100,100);\r\n        else{\r\n            _layer(paths,dr,v,1,80,128,100,100);\r\n            int256 bend=int256(mutation%16)-8;uint256 height=55+mutation/16;\r\n            // Three bounded inherited crown arrangements; no recursive ancestry rendering.\r\n            if(mode==1){if(v.age>=12){_line(paths[2],80,128,52+bend,113);_line(paths[2],80,128,105+bend,108);}_layer(paths,da,v,2,52+bend,113,50,65);_layer(paths,db,v,2,105+bend,108,52,height);}\r\n            else if(mode==2){if(v.age>=12){_line(paths[2],80,128,80+bend,117);_line(paths[2],80,116,116,106);}_layer(paths,da,v,2,80+bend,117,70,height);_layer(paths,db,v,2,116,106,36,46);}\r\n            else{if(v.age>=12){_line(paths[2],80,128,45,122);_line(paths[2],80,128,80+bend,112);_line(paths[2],80,128,115,122);}_layer(paths,da,v,2,45,122,35,49);_layer(paths,db,v,2,80+bend,112,45,height);_layer(paths,da,v,2,115,122,35,44);}\r\n        }\r\n        bytes[4] memory encoded=_paths(paths[0]);\r\n        bytes memory rings;\r\n        uint256 count=v.rings>8?8:v.rings;\r\n        for(uint256 i;i<count;++i){uint256 size=4+i*3;rings=bytes.concat(rings,bytes(string.concat('<rect x=\"',(80-size/2).toString(),'\" y=\"',(148-size/2).toString(),'\" width=\"',size.toString(),'\" height=\"',size.toString(),'\" fill=\"none\" stroke=\"#354900\" stroke-width=\"1\"/>')));}\r\n        return string(bytes.concat('<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 160 180\" shape-rendering=\"crispEdges\"><rect width=\"160\" height=\"180\" fill=\"#080b08\"/>',rings,'<path fill=\"#354900\" d=\"',encoded[0],'\"/><path fill=\"#678900\" d=\"',encoded[1],'\"/><path fill=\"#9bc500\" d=\"',encoded[2],'\"/><path fill=\"#ccff00\" d=\"',encoded[3],'\"/></svg>'));\r\n    }\r\n    function tokenURI(uint256 id,PlantTypes.Plant calldata p,uint256 at) external view returns(string memory){\r\n        View memory v=_view(p,at);string[4] memory seasons=[\"Spring\",\"Summer\",\"Autumn\",\"Winter\"];\r\n        string memory attributes=string.concat('[{\"trait_type\":\"Generation\",\"value\":',uint256(p.generation).toString(),'},',\r\n            '{\"trait_type\":\"Pollination\",\"value\":\"',p.pollinated?'Pollinated':'Unpollinated','\"},',\r\n            '{\"trait_type\":\"Growth days\",\"value\":',v.age.toString(),'},',\r\n            '{\"trait_type\":\"Season\",\"value\":\"',seasons[v.season],'\"},',\r\n            '{\"trait_type\":\"Annual bloom\",\"value\":\"',v.bloom?'Blooming':'Dormant','\"},',\r\n            '{\"trait_type\":\"Growth rings\",\"value\":',v.rings.toString(),'},',\r\n            '{\"trait_type\":\"Pruning\",\"value\":\"',v.regrowth<1000?'Regrowing':'Full','\"},',\r\n            '{\"trait_type\":\"Parent A\",\"value\":',uint256(p.parentA).toString(),'},',\r\n            '{\"trait_type\":\"Parent B\",\"value\":',uint256(p.parentB).toString(),'}]');\r\n        bytes memory json=bytes(string.concat('{\"name\":\"CCFF00 PLANTS #',id.toString(),'\",\"description\":\"An onchain pixel plant. Full growth in 90 days. Each plant may pair once in its lifetime.\",\"image\":\"data:image/svg+xml;base64,',Base64.encode(bytes(svg(p,at))),'\",\"attributes\":',attributes,'}'));\r\n        return string.concat('data:application/json;base64,',Base64.encode(json));\r\n    }\r\n}\r\n"
    },
    "contracts/PlantTypes.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nlibrary PlantTypes {\n    struct Plant {\n        uint64 genome;\n        uint64 born;\n        uint64 prunedAt;\n        uint16 parentA;\n        uint16 parentB;\n        uint16 generation;\n        uint8 pruneBranch;\n        bool pollinated;\n    }\n}\ninterface IPlantRenderer {\n    function assetCount() external view returns(uint8);\n    function prunableBranches(uint64 genome) external view returns(uint8);\n    function tokenURI(uint256 id, PlantTypes.Plant calldata p, uint256 timestamp) external view returns (string memory);\n    function svg(PlantTypes.Plant calldata p, uint256 timestamp) external view returns (string memory);\n}\n"
    },
    "contracts/TestReceivers.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\ninterface IGame {function pair(uint16,uint16,address,uint64) external returns(uint256);function claimGenesis(uint16,address) external;}\n/// @dev Test fixture only: never part of the release deployment.\ncontract RejectReceiver is IERC721Receiver {\n    function onERC721Received(address,address,uint256,bytes calldata) external pure returns(bytes4){revert(\"REJECT\");}\n}\ncontract ReenterReceiver is IERC721Receiver {\n    address public target;uint16 public a;uint16 public b;uint64 public genome;bool public blocked;\n    function arm(address t,uint16 x,uint16 y,uint64 g) external {target=t;a=x;b=y;genome=g;}\n    function onERC721Received(address,address,uint256,bytes calldata) external returns(bytes4){\n        (bool ok,)=target.call(abi.encodeWithSelector(IGame.pair.selector,a,b,address(this),genome));blocked=!ok;return IERC721Receiver.onERC721Received.selector;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/ERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"./IERC721.sol\";\nimport {IERC721Receiver} from \"./IERC721Receiver.sol\";\nimport {IERC721Metadata} from \"./extensions/IERC721Metadata.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {Strings} from \"../../utils/Strings.sol\";\nimport {IERC165, ERC165} from \"../../utils/introspection/ERC165.sol\";\nimport {IERC721Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    mapping(uint256 tokenId => address) private _owners;\n\n    mapping(address owner => uint256) private _balances;\n\n    mapping(uint256 tokenId => address) private _tokenApprovals;\n\n    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC721-balanceOf}.\n     */\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        if (owner == address(0)) {\n            revert ERC721InvalidOwner(address(0));\n        }\n        return _balances[owner];\n    }\n\n    /**\n     * @dev See {IERC721-ownerOf}.\n     */\n    function ownerOf(uint256 tokenId) public view virtual returns (address) {\n        return _requireOwned(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721Metadata-name}.\n     */\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-symbol}.\n     */\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev See {IERC721Metadata-tokenURI}.\n     */\n    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n        _requireOwned(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /**\n     * @dev See {IERC721-approve}.\n     */\n    function approve(address to, uint256 tokenId) public virtual {\n        _approve(to, tokenId, _msgSender());\n    }\n\n    /**\n     * @dev See {IERC721-getApproved}.\n     */\n    function getApproved(uint256 tokenId) public view virtual returns (address) {\n        _requireOwned(tokenId);\n\n        return _getApproved(tokenId);\n    }\n\n    /**\n     * @dev See {IERC721-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC721-isApprovedForAll}.\n     */\n    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /**\n     * @dev See {IERC721-transferFrom}.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) public virtual {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n        address previousOwner = _update(to, tokenId, _msgSender());\n        if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) public {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev See {IERC721-safeTransferFrom}.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n        transferFrom(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     *\n     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n     * core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n     */\n    function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n     * particular (ignoring whether it is owned by `owner`).\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n        return\n            spender != address(0) &&\n            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n     * Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets\n     * the `spender` for the specific `tokenId`.\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n        if (!_isAuthorized(owner, spender, tokenId)) {\n            if (owner == address(0)) {\n                revert ERC721NonexistentToken(tokenId);\n            } else {\n                revert ERC721InsufficientApproval(spender, tokenId);\n            }\n        }\n    }\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n     *\n     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n     * remain consistent with one another.\n     */\n    function _increaseBalance(address account, uint128 value) internal virtual {\n        unchecked {\n            _balances[account] += value;\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n     */\n    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n        address from = _ownerOf(tokenId);\n\n        // Perform (optional) operator check\n        if (auth != address(0)) {\n            _checkAuthorized(from, auth, tokenId);\n        }\n\n        // Execute the update\n        if (from != address(0)) {\n            // Clear approval. No need to re-authorize or emit the Approval event\n            _approve(address(0), tokenId, address(0), false);\n\n            unchecked {\n                _balances[from] -= 1;\n            }\n        }\n\n        if (to != address(0)) {\n            unchecked {\n                _balances[to] += 1;\n            }\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        return from;\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner != address(0)) {\n            revert ERC721InvalidSender(address(0));\n        }\n    }\n\n    /**\n     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        _checkOnERC721Received(address(0), to, tokenId, data);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal {\n        address previousOwner = _update(address(0), tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        } else if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n     * are aware of the ERC721 standard to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is like {safeTransferFrom} in the sense that it invokes\n     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `tokenId` token must exist and be owned by `from`.\n     * - `to` cannot be the zero address.\n     * - `from` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId) internal {\n        _safeTransfer(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        _checkOnERC721Received(from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is\n     * either the owner of the token, or approved to operate on all tokens held by this owner.\n     *\n     * Emits an {Approval} event.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address to, uint256 tokenId, address auth) internal {\n        _approve(to, tokenId, auth, true);\n    }\n\n    /**\n     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not\n     * emitted in the context of transfers.\n     */\n    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {\n        // Avoid reading the owner unless necessary\n        if (emitEvent || auth != address(0)) {\n            address owner = _requireOwned(tokenId);\n\n            // We do not use _isAuthorized because single-token approvals should not be able to call approve\n            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {\n                revert ERC721InvalidApprover(auth);\n            }\n\n            if (emitEvent) {\n                emit Approval(owner, to, tokenId);\n            }\n        }\n\n        _tokenApprovals[tokenId] = to;\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Requirements:\n     * - operator can't be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        if (operator == address(0)) {\n            revert ERC721InvalidOperator(operator);\n        }\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).\n     * Returns the owner.\n     *\n     * Overrides to ownership logic should be done to {_ownerOf}.\n     */\n    function _requireOwned(uint256 tokenId) internal view returns (address) {\n        address owner = _ownerOf(tokenId);\n        if (owner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n        return owner;\n    }\n\n    /**\n     * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the\n     * recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.\n     *\n     * @param from address representing the previous owner of the given token ID\n     * @param to target address that will receive the tokens\n     * @param tokenId uint256 ID of the token to be transferred\n     * @param data bytes optional data to send along with the call\n     */\n    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory data) private {\n        if (to.code.length > 0) {\n            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) {\n                    revert ERC721InvalidReceiver(to);\n                }\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    revert ERC721InvalidReceiver(to);\n                } else {\n                    /// @solidity memory-safe-assembly\n                    assembly {\n                        revert(add(32, reason), mload(reason))\n                    }\n                }\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/common/ERC2981.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/common/ERC2981.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC2981} from \"../../interfaces/IERC2981.sol\";\nimport {IERC165, ERC165} from \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.\n *\n * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for\n * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.\n *\n * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the\n * fee is specified in basis points by default.\n *\n * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See\n * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to\n * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.\n */\nabstract contract ERC2981 is IERC2981, ERC165 {\n    struct RoyaltyInfo {\n        address receiver;\n        uint96 royaltyFraction;\n    }\n\n    RoyaltyInfo private _defaultRoyaltyInfo;\n    mapping(uint256 tokenId => RoyaltyInfo) private _tokenRoyaltyInfo;\n\n    /**\n     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The default royalty receiver is invalid.\n     */\n    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);\n\n    /**\n     * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).\n     */\n    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);\n\n    /**\n     * @dev The royalty receiver for `tokenId` is invalid.\n     */\n    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {\n        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @inheritdoc IERC2981\n     */\n    function royaltyInfo(uint256 tokenId, uint256 salePrice) public view virtual returns (address, uint256) {\n        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[tokenId];\n\n        if (royalty.receiver == address(0)) {\n            royalty = _defaultRoyaltyInfo;\n        }\n\n        uint256 royaltyAmount = (salePrice * royalty.royaltyFraction) / _feeDenominator();\n\n        return (royalty.receiver, royaltyAmount);\n    }\n\n    /**\n     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a\n     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an\n     * override.\n     */\n    function _feeDenominator() internal pure virtual returns (uint96) {\n        return 10000;\n    }\n\n    /**\n     * @dev Sets the royalty information that all ids in this contract will default to.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));\n        }\n\n        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Removes default royalty information.\n     */\n    function _deleteDefaultRoyalty() internal virtual {\n        delete _defaultRoyaltyInfo;\n    }\n\n    /**\n     * @dev Sets the royalty information for a specific token id, overriding the global default.\n     *\n     * Requirements:\n     *\n     * - `receiver` cannot be the zero address.\n     * - `feeNumerator` cannot be greater than the fee denominator.\n     */\n    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {\n        uint256 denominator = _feeDenominator();\n        if (feeNumerator > denominator) {\n            // Royalty fee will exceed the sale price\n            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);\n        }\n        if (receiver == address(0)) {\n            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));\n        }\n\n        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);\n    }\n\n    /**\n     * @dev Resets royalty information for the token id back to the global default.\n     */\n    function _resetTokenRoyalty(uint256 tokenId) internal virtual {\n        delete _tokenRoyaltyInfo[tokenId];\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable2Step.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.20;\n\nimport {Ownable} from \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is specified at deployment time in the constructor for `Ownable`. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        if (pendingOwner() != sender) {\n            revert OwnableUnauthorizedAccount(sender);\n        }\n        _transferOwnership(sender);\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Base64.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.2) (utils/Base64.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n */\nlibrary Base64 {\n    /**\n     * @dev Base64 Encoding/Decoding Table\n     */\n    string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\n     */\n    function encode(bytes memory data) internal pure returns (string memory) {\n        /**\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n         */\n        if (data.length == 0) return \"\";\n\n        // Loads the table into memory\n        string memory table = _TABLE;\n\n        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter\n        // and split into 4 numbers of 6 bits.\n        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up\n        // - `data.length + 2`  -> Round up\n        // - `/ 3`              -> Number of 3-bytes chunks\n        // - `4 *`              -> 4 characters for each chunk\n        string memory result = new string(4 * ((data.length + 2) / 3));\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Prepare the lookup table (skip the first \"length\" byte)\n            let tablePtr := add(table, 1)\n\n            // Prepare result pointer, jump over length\n            let resultPtr := add(result, 0x20)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n\n            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and\n            // set it to zero to make sure no dirty bytes are read in that section.\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n\n            // Run over the input, 3 bytes at a time\n            for {\n\n            } lt(dataPtr, endPtr) {\n\n            } {\n                // Advance 3 bytes\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n\n                // To write each character, shift the 3 byte (24 bits) chunk\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.\n                // Use this as an index into the lookup table, mload an entire word\n                // so the desired character is in the least significant byte, and\n                // mstore8 this least significant byte into the result and continue.\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n            }\n\n            // Reset the value that was cached\n            mstore(afterPtr, afterCache)\n\n            // When data `bytes` is not exactly 3 bytes long\n            // it is padded with `=` characters at the end\n            switch mod(mload(data), 3)\n            case 1 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n                mstore8(sub(resultPtr, 2), 0x3d)\n            }\n            case 2 {\n                mstore8(sub(resultPtr, 1), 0x3d)\n            }\n        }\n\n        return result;\n    }\n}\n"
    },
    "solady/src/utils/LibZip.sol": {
      "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Library for compressing and decompressing bytes.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol)\n/// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor)\n/// @author FastLZ by ariya (https://github.com/ariya/FastLZ)\n///\n/// @dev Note:\n/// The accompanying solady.js library includes implementations of\n/// FastLZ and calldata operations for convenience.\nlibrary LibZip {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     FAST LZ OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // LZ77 implementation based on FastLZ.\n    // Equivalent to level 1 compression and decompression at the following commit:\n    // https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42\n    // Decompression is backwards compatible.\n\n    /// @dev Returns the compressed `data`.\n    function flzCompress(bytes memory data) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            function ms8(d_, v_) -> _d {\n                mstore8(d_, v_)\n                _d := add(d_, 1)\n            }\n            function u24(p_) -> _u {\n                _u := mload(p_)\n                _u := or(shl(16, byte(2, _u)), or(shl(8, byte(1, _u)), byte(0, _u)))\n            }\n            function cmp(p_, q_, e_) -> _l {\n                for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } {\n                    e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_)\n                }\n            }\n            function literals(runs_, src_, dest_) -> _o {\n                for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } {\n                    mstore(ms8(_o, 31), mload(src_))\n                    _o := add(_o, 0x21)\n                    src_ := add(src_, 0x20)\n                }\n                if iszero(runs_) { leave }\n                mstore(ms8(_o, sub(runs_, 1)), mload(src_))\n                _o := add(1, add(_o, runs_))\n            }\n            function mt(l_, d_, o_) -> _o {\n                for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } {\n                    o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_))\n                }\n                if iszero(lt(l_, 7)) {\n                    _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_))\n                    leave\n                }\n                _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_))\n            }\n            function setHash(i_, v_) {\n                let p_ := add(mload(0x40), shl(2, i_))\n                mstore(p_, xor(mload(p_), shl(224, xor(shr(224, mload(p_)), v_))))\n            }\n            function getHash(i_) -> _h {\n                _h := shr(224, mload(add(mload(0x40), shl(2, i_))))\n            }\n            function hash(v_) -> _r {\n                _r := and(shr(19, mul(2654435769, v_)), 0x1fff)\n            }\n            function setNextHash(ip_, ipStart_) -> _ip {\n                setHash(hash(u24(ip_)), sub(ip_, ipStart_))\n                _ip := add(ip_, 1)\n            }\n            result := mload(0x40)\n            calldatacopy(result, calldatasize(), 0x8000) // Zeroize the hashmap.\n            let op := add(result, 0x8000)\n            let a := add(data, 0x20)\n            let ipStart := a\n            let ipLimit := sub(add(ipStart, mload(data)), 13)\n            for { let ip := add(2, a) } lt(ip, ipLimit) {} {\n                let r := 0\n                let d := 0\n                for {} 1 {} {\n                    let s := u24(ip)\n                    let h := hash(s)\n                    r := add(ipStart, getHash(h))\n                    setHash(h, sub(ip, ipStart))\n                    d := sub(ip, r)\n                    if iszero(lt(ip, ipLimit)) { break }\n                    ip := add(ip, 1)\n                    if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } }\n                }\n                if iszero(lt(ip, ipLimit)) { break }\n                ip := sub(ip, 1)\n                if gt(ip, a) { op := literals(sub(ip, a), a, op) }\n                let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9))\n                op := mt(l, d, op)\n                ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart)\n                a := ip\n            }\n            // Copy the result to compact the memory, overwriting the hashmap.\n            let end := sub(literals(sub(add(ipStart, mload(data)), a), a, op), 0x7fe0)\n            let o := add(result, 0x20)\n            mstore(result, sub(end, o)) // Store the length.\n            for {} iszero(gt(o, end)) { o := add(o, 0x20) } { mstore(o, mload(add(o, 0x7fe0))) }\n            mstore(end, 0) // Zeroize the slot after the string.\n            mstore(0x40, add(end, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Returns the decompressed `data`.\n    function flzDecompress(bytes memory data) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := mload(0x40)\n            let op := add(result, 0x20)\n            let end := add(add(data, 0x20), mload(data))\n            for { data := add(data, 0x20) } lt(data, end) {} {\n                let w := mload(data)\n                let c := byte(0, w)\n                let t := shr(5, c)\n                if iszero(t) {\n                    mstore(op, mload(add(data, 1)))\n                    data := add(data, add(2, c))\n                    op := add(op, add(1, c))\n                    continue\n                }\n                for {\n                    let g := eq(t, 7)\n                    let l := add(2, xor(t, mul(g, xor(t, add(7, byte(1, w)))))) // M\n                    let s := add(add(shl(8, and(0x1f, c)), byte(add(1, g), w)), 1) // R\n                    let r := sub(op, s)\n                    let f := xor(s, mul(gt(s, 0x20), xor(s, 0x20)))\n                    let j := 0\n                } 1 {} {\n                    mstore(add(op, j), mload(add(r, j)))\n                    j := add(j, f)\n                    if lt(j, l) { continue }\n                    data := add(data, add(2, g))\n                    op := add(op, l)\n                    break\n                }\n            }\n            mstore(result, sub(op, add(result, 0x20))) // Store the length.\n            mstore(op, 0) // Zeroize the slot after the string.\n            mstore(0x40, add(op, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                    CALLDATA OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // Calldata compression and decompression using selective run length encoding:\n    // - Sequences of 0x00 (up to 128 consecutive).\n    // - Sequences of 0xff (up to 32 consecutive).\n    //\n    // A run length encoded block consists of two bytes:\n    // (0) 0x00\n    // (1) A control byte with the following bit layout:\n    //     - [7]     `0: 0x00, 1: 0xff`.\n    //     - [0..6]  `runLength - 1`.\n    //\n    // The first 4 bytes are bitwise negated so that the compressed calldata\n    // can be dispatched into the `fallback` and `receive` functions.\n\n    /// @dev Returns the compressed `data`.\n    function cdCompress(bytes memory data) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            function countLeadingZeroBytes(x_) -> _r {\n                _r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x_))\n                _r := or(_r, shl(6, lt(0xffffffffffffffff, shr(_r, x_))))\n                _r := or(_r, shl(5, lt(0xffffffff, shr(_r, x_))))\n                _r := or(_r, shl(4, lt(0xffff, shr(_r, x_))))\n                _r := xor(31, or(shr(3, _r), lt(0xff, shr(_r, x_))))\n            }\n            function min(x_, y_) -> _z {\n                _z := xor(x_, mul(xor(x_, y_), lt(y_, x_)))\n            }\n            result := mload(0x40)\n            let end := add(data, mload(data))\n            let m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f\n            let o := add(result, 0x20)\n            for { let i := data } iszero(eq(i, end)) {} {\n                i := add(i, 1)\n                let c := byte(31, mload(i))\n                if iszero(c) {\n                    for {} 1 {} {\n                        let x := mload(add(i, 0x20))\n                        if iszero(x) {\n                            let r := min(sub(end, i), 0x20)\n                            r := min(sub(0x7f, c), r)\n                            i := add(i, r)\n                            c := add(c, r)\n                            if iszero(gt(r, 0x1f)) { break }\n                            continue\n                        }\n                        let r := countLeadingZeroBytes(x)\n                        r := min(sub(end, i), r)\n                        i := add(i, r)\n                        c := add(c, r)\n                        break\n                    }\n                    mstore(o, shl(240, c))\n                    o := add(o, 2)\n                    continue\n                }\n                if eq(c, 0xff) {\n                    let r := 0x20\n                    let x := not(mload(add(i, r)))\n                    if x { r := countLeadingZeroBytes(x) }\n                    r := min(min(sub(end, i), r), 0x1f)\n                    i := add(i, r)\n                    mstore(o, shl(240, or(r, 0x80)))\n                    o := add(o, 2)\n                    continue\n                }\n                mstore8(o, c)\n                o := add(o, 1)\n                c := mload(add(i, 0x20))\n                mstore(o, c)\n                // `.each(b => b == 0x00 || b == 0xff ? 0x80 : 0x00)`.\n                c := not(or(and(or(add(and(c, m), m), c), or(add(and(not(c), m), m), not(c))), m))\n                let r := shl(7, lt(0x8421084210842108cc6318c6db6d54be, c)) // Save bytecode.\n                r := or(shl(6, lt(0xffffffffffffffff, shr(r, c))), r)\n                // forgefmt: disable-next-item\n                r := add(iszero(c), shr(3, xor(byte(and(0x1f, shr(byte(24,\n                    mul(0x02040810204081, shr(r, c))), 0x8421084210842108cc6318c6db6d54be)),\n                    0xc0c8c8d0c8e8d0d8c8e8e0e8d0d8e0f0c8d0e8d0e0e0d8f0d0d0e0d8f8f8f8f8), r)))\n                r := min(sub(end, i), r)\n                o := add(o, r)\n                i := add(i, r)\n            }\n            // Bitwise negate the first 4 bytes.\n            mstore(add(result, 4), not(mload(add(result, 4))))\n            mstore(result, sub(o, add(result, 0x20))) // Store the length.\n            mstore(o, 0) // Zeroize the slot after the string.\n            mstore(0x40, add(o, 0x20)) // Allocate the memory.\n        }\n    }\n\n    /// @dev Returns the decompressed `data`.\n    function cdDecompress(bytes memory data) internal pure returns (bytes memory result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mload(data) {\n                result := mload(0x40)\n                let s := add(data, 4)\n                let v := mload(s)\n                let end := add(add(0x20, data), mload(data))\n                let m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f\n                let o := add(result, 0x20)\n                mstore(s, not(v)) // Bitwise negate the first 4 bytes.\n                for { let i := add(0x20, data) } 1 {} {\n                    let c := mload(i)\n                    if iszero(byte(0, c)) {\n                        c := add(1, byte(1, c))\n                        if iszero(gt(c, 0x80)) {\n                            i := add(i, 2)\n                            calldatacopy(o, calldatasize(), c) // Fill with 0x00.\n                            o := add(o, c)\n                            if iszero(lt(i, end)) { break }\n                            continue\n                        }\n                        i := add(i, 2)\n                        mstore(o, not(0)) // Fill with 0xff.\n                        o := add(o, sub(c, 0x80))\n                        if iszero(lt(i, end)) { break }\n                        continue\n                    }\n                    mstore(o, c)\n                    c := not(or(or(add(and(c, m), m), c), m)) // `.each(b => b == 0x00 ? 0x80 : 0x00)`.\n                    let r := shl(7, lt(0x8421084210842108cc6318c6db6d54be, c)) // Save bytecode.\n                    r := or(shl(6, lt(0xffffffffffffffff, shr(r, c))), r)\n                    // forgefmt: disable-next-item\n                    c := add(iszero(c), shr(3, xor(byte(and(0x1f, shr(byte(24,\n                        mul(0x02040810204081, shr(r, c))), 0x8421084210842108cc6318c6db6d54be)),\n                        0xc0c8c8d0c8e8d0d8c8e8e0e8d0d8e0f0c8d0e8d0e0e0d8f0d0d0e0d8f8f8f8f8), r)))\n                    o := add(o, c)\n                    i := add(i, c)\n                    if lt(i, end) { continue }\n                    if gt(i, end) { o := sub(o, sub(i, end)) }\n                    break\n                }\n                mstore(s, v) // Restore the first 4 bytes.\n                mstore(result, sub(o, add(result, 0x20))) // Store the length.\n                mstore(o, 0) // Zeroize the slot after the string.\n                mstore(0x40, add(o, 0x20)) // Allocate the memory.\n            }\n        }\n    }\n\n    /// @dev To be called in the `fallback` function.\n    /// ```\n    ///     fallback() external payable { LibZip.cdFallback(); }\n    ///     receive() external payable {} // Silence compiler warning to add a `receive` function.\n    /// ```\n    /// For efficiency, this function will directly return the results, terminating the context.\n    /// If called internally, it must be called at the end of the function.\n    function cdFallback() internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(calldatasize()) { return(calldatasize(), calldatasize()) }\n            let o := 0\n            let f := not(3) // For negating the first 4 bytes.\n            for { let i := 0 } lt(i, calldatasize()) {} {\n                let c := byte(0, xor(add(i, f), calldataload(i)))\n                i := add(i, 1)\n                if iszero(c) {\n                    let d := byte(0, xor(add(i, f), calldataload(i)))\n                    i := add(i, 1)\n                    // Fill with either 0xff or 0x00.\n                    mstore(o, not(0))\n                    if iszero(gt(d, 0x7f)) { calldatacopy(o, calldatasize(), add(d, 1)) }\n                    o := add(o, add(and(d, 0x7f), 1))\n                    continue\n                }\n                mstore8(o, c)\n                o := add(o, 1)\n            }\n            let success := delegatecall(gas(), address(), 0x00, o, codesize(), 0x00)\n            returndatacopy(0x00, 0x00, returndatasize())\n            if iszero(success) { revert(0x00, returndatasize()) }\n            return(0x00, returndatasize())\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n     * reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@openzeppelin/contracts/interfaces/draft-IERC6093.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard ERC20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"
    },
    "@openzeppelin/contracts/interfaces/IERC2981.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2981.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n */\ninterface IERC2981 is IERC165 {\n    /**\n     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n     */\n    function royaltyInfo(\n        uint256 tokenId,\n        uint256 salePrice\n    ) external view returns (address receiver, uint256 royaltyAmount);\n}\n"
    },
    "@openzeppelin/contracts/utils/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    /**\n     * @dev Muldiv operation overflow.\n     */\n    error MathOverflowedMulDiv();\n\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            return a / b;\n        }\n\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0 = x * y; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            if (denominator <= prod1) {\n                revert MathOverflowedMulDiv();\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/math/SignedMath.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "viaIR": true,
    "evmVersion": "paris",
    "metadata": {
      "bytecodeHash": "none"
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode.object",
          "evm.deployedBytecode.object",
          "evm.deployedBytecode.immutableReferences",
          "storageLayout"
        ]
      }
    }
  }
}