pragma solidity ^0.8.7;

//                                                #K#EL# .                                          
//                                              j,#.#W#E#### #                                        
//                                            #W#t###W######## fD                                     
//                                          .################K###                                     
//                                         ###################t####                                   
//                                       :#########################                                   
//                                      #############################,                                
//                                     #G#############################                                
//                                     ####G###############Df#######D                                 
//                                    ############################E##L                                
//                                    ################Wf  G####,###,                                  
//                                   i###K###.####E        ##:## L##                                  
//                                    ##########,           ## #G: W                                  
//                                    j#########            .:    #                                   
//                                     #########                                                      
//                                     L########;                  #                                  
//                                      ########,                  W                                  
//                                      ########                                                      
//                                      ########                    f                                 
//                                       ######K       Kj        W. #                                 
//                                       ######      ##,  #    .#,  #E                                
//                                        #####     E  G###W;#K##   #DD                               
//                                        ##### ;LW#t   E#L#    #G  #;                                
//                                        K#  #         ## #  t i.  #f                                
//                                        #                #   #    ##                                
//                                       Wt if      K     t #  #    #                                 
//                                       Ki   #      #   K: f##L:##G#                                 
//                                        #           :j:  tKjt.    #                                 
//                                        W#tjG           #######  .W                                 
//                                          W#           ####Gi### WE                                 
//                                            #         ## #    D# #                                  
//                                            Dt        ##:f    :#D#                                  
//                                             #       .###  ##  ###                                  
//                                              #:     f##D E###L##                                   
//                                               ,     D###E#######                                   
//                                               E   #tD###########                                   
//                                               #   i############,                                   
//                                              ##     L##########                                    
//                                            f####D     L#######                                     
//                                       :E###########Wf   ;###:                                      
//                                   L##########################                                      
//                                i################# ###########D                                     
//                              i###E ###############W#############                                   
//                             #################################Gt###                                 
//                            ########################################W                               
//                           W########################################W;.                             
//                          K####################LW######################                             
//                          ##############################################                            
//                         ###############################################                            
//                        .###K ###########################################t.                         
//                        ##############L####################j########jttttttttD#                     
//                        ###################################,########ttttttttttt                     
//                       ############################################ttttttttttE                      
//                       ############################################ttttttttttE                      
//                      t###########################################ttttttttttG                       
//                      ##########################:#################ttttttttttW                       
//                      #####:#################### ################ttttttttttD                        
//                      ##########################################Gfttttttttt#                        
//                     j################j#####################j    tjttttttLKj                        
//                     ##################E##################W       WtttED                            
//                     #####################################     tK  #tK                              
//                      ############ ######################:      ## :tW.E#j                          
//                     #############t#####################E         WEt#      G                       
//                     #############D###########, #######E     E#;   f:       .                       
//                     #############E###################;        :#K #  tWj   W                       
//                     #############E#################:        f   #,#L        i                      
//                     ####G########f#################          ,t ##;  ,K##i :                       
//                     #####W#######;################W           E####i      ,E                       
//                     ############# ################K         #######     L###                       
//                     ############# ######i :#######W        #################.                      
//                     ############# ##:  ,W##########   .:  W#################K                      
//                     ############   D############### #########################                      
//                     #########;:##############################################                      
//                     K#######K################################################                      
//                     i################# ##################;#####;.######## ###                      
//                      ####################################:###############.###                      
//                      ####################################################:###                      
//                      W#####################; ############################G###                      
//                      .###i,##############::#################################K                      
//                       #################:i###################################;                      
//                       E##############.G############t########################                       
//                        ############ W############# ########################i                       
//                        ;#########,############################## ##########                        
//                         #################K#################################                        
//                          K############### ################################      


contract CryptoUncle12 is Ownable, ERC721, NonblockingReceiver {


    address public _owner;
    string private baseURI;
    uint256 nextTokenId = 0;
    uint256 MAX_MINT_ETHEREUM = 5000;
    uint256 PRICE = 0.002 ether;

    uint gasForDestinationLzReceive = 350000;

    constructor(string memory baseURI_, address _layerZeroEndpoint) ERC721("CryptoUncle12 NFT", "CryptoUncle12") {
        _owner = msg.sender;
        endpoint = ILayerZeroEndpoint(_layerZeroEndpoint);
        baseURI = baseURI_;
    }

    // mint function
    function mint(uint8 numTokens) external payable {
        require((PRICE * numTokens) <= msg.value, "Not enough amount sent.");
        require(nextTokenId + numTokens <= MAX_MINT_ETHEREUM, "CryptoUncle12: Mint exceeds supply");
        for (uint256 i = 0; i < numTokens; i++) {
            _safeMint(msg.sender, ++nextTokenId);
        }
    }

    // This function transfers the nft from your address on the
    // source chain to the same address on the destination chain
    function traverseChains(uint16 _chainId, uint tokenId) public payable {
        require(msg.sender == ownerOf(tokenId), "You must own the token to traverse");
        require(trustedRemoteLookup[_chainId].length > 0, "This chain is currently unavailable for travel");

        // burn NFT, eliminating it from circulation on src chain
        _burn(tokenId);

        // abi.encode() the payload with the values to send
        bytes memory payload = abi.encode(msg.sender, tokenId);

        // encode adapterParams to specify more gas for the destination
        uint16 version = 1;
        bytes memory adapterParams = abi.encodePacked(version, gasForDestinationLzReceive);

        // get the fees we need to pay to LayerZero + Relayer to cover message delivery
        // you will be refunded for extra gas paid
        (uint messageFee, ) = endpoint.estimateFees(_chainId, address(this), payload, false, adapterParams);

        require(msg.value >= messageFee, "CryptoUncle12: msg.value not enough to cover messageFee. Send gas for message fees");

        endpoint.send{value: msg.value}(
            _chainId,                           // destination chainId
            trustedRemoteLookup[_chainId],      // destination address of nft contract
            payload,                            // abi.encoded()'ed bytes
            payable(msg.sender),                // refund address
            address(0x0),                       // 'zroPaymentAddress' unused for this
            adapterParams                       // txParameters
        );
    }

    function setBaseURI(string memory URI) external onlyOwner {
        baseURI = URI;
    }

    function donate() external payable {
        // thank you
    }

    // This allows the devs to receive kind donations
    function withdraw(uint amt) external onlyOwner {
        (bool sent, ) = payable(_owner).call{value: amt}("");
        require(sent, "CryptoUncle12: Failed to withdraw Ether");
    }

    // just in case this fixed variable limits us from future integrations
    function setGasForDestinationLzReceive(uint newVal) external onlyOwner {
        gasForDestinationLzReceive = newVal;
    }

    // ------------------
    // Internal Functions
    // ------------------
 
    function _LzReceive(uint16 _srcChainId, bytes memory _srcAddress, uint64 _nonce, bytes memory _payload) override internal {
        // decode
        (address toAddr, uint tokenId) = abi.decode(_payload, (address, uint));
        require(_srcChainId!=0,"_srcChainId");
        require(_srcAddress.length!=0,"_srcAddress");
        require(_nonce!=0,"_nonce");

        // mint the tokens back into existence on destination chain
        _safeMint(toAddr, tokenId);
    }

    function _baseURI() override internal view returns (string memory) {
        return baseURI;
    }

}
[{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"},{"internalType":"address","name":"_layerZeroEndpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"indexed":false,"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"_nonce","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"MessageFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"failedMessages","outputs":[{"internalType":"uint256","name":"payloadLength","type":"uint256"},{"internalType":"bytes32","name":"payloadHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"lzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"numTokens","type":"uint8"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"onLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_srcChainId","type":"uint16"},{"internalType":"bytes","name":"_srcAddress","type":"bytes"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"bytes","name":"_payload","type":"bytes"}],"name":"retryMessage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"URI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newVal","type":"uint256"}],"name":"setGasForDestinationLzReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"bytes","name":"_trustedRemote","type":"bytes"}],"name":"setTrustedRemote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"traverseChains","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"trustedRemoteLookup","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]