ETH Price: $2,191.92 (-9.58%)

Transaction Decoder

Block:
12362434 at May-03-2021 04:57:22 PM +UTC
Transaction Fee:
0.018083754 ETH $39.64
Gas Used:
165,906 Gas / 109 Gwei

Emitted Events:

Account State Difference:

  Address   Before After State Difference Code
(zhizhu.top)
1,994.235018210245762486 Eth1,994.253101964245762486 Eth0.018083754
0x7Bd29408...3bB716Bc7
0x9Df2d651...C7906333D
3.980407636637445862 Eth
Nonce: 1
1.46348129004485327 Eth
Nonce: 2
2.516926346592592592
0xC352B534...53488e56a
(Autoglyphs: Deployer)
476.04568140875929857 Eth478.544524001351891162 Eth2.498842592592592592

Execution Trace

ETH 2.499384093915343915 Meebits.CALL( )
  • ETH 0.000541501322751323 0x9df2d651c837c7c5fac430fcf69b811c7906333d.CALL( )
  • ETH 2.498842592592592592 Autoglyphs: Deployer.CALL( )
    pragma solidity 0.7.6;
    
    /**
     *  __  __           _     _ _
     * |  \/  |         | |   (_) |
     * | \  / | ___  ___| |__  _| |_ ___
     * | |\/| |/ _ \/ _ \ '_ \| | __/ __|
     * | |  | |  __/  __/ |_) | | |_\__ \
     * |_|  |_|\___|\___|_.__/|_|\__|___/
     *
     * An NFT project from Larva Labs.
     *
     */
    interface IERC165 {
        function supportsInterface(bytes4 interfaceId) external view returns (bool);
    }
    
    interface IERC721 is IERC165 {
        event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
        event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
        event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
        function balanceOf(address owner) external view returns (uint256 balance);
        function ownerOf(uint256 tokenId) external view returns (address owner);
        function safeTransferFrom(address from, address to, uint256 tokenId) external;
        function transferFrom(address from, address to, uint256 tokenId) external;
        function approve(address to, uint256 tokenId) external;
        function getApproved(uint256 tokenId) external view returns (address operator);
        function setApprovalForAll(address operator, bool _approved) external;
        function isApprovedForAll(address owner, address operator) external view returns (bool);
        function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
    }
    
    /**
     * Minimal interface to Cryptopunks for verifying ownership during Community Grant.
     */
    interface Cryptopunks {
        function punkIndexToAddress(uint index) external view returns(address);
    }
    
    interface ERC721TokenReceiver
    {
        function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns(bytes4);
    }
    
    library SafeMath {
    
        /**
        * @dev Multiplies two numbers, throws on overflow.
        */
        function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
            if (a == 0) {
                return 0;
            }
            c = a * b;
            require(c / a == b);
            return c;
        }
    
        /**
        * @dev Integer division of two numbers, truncating the quotient.
        */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            // assert(b > 0); // Solidity automatically throws when dividing by 0
            // uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
            return a / b;
        }
    
        /**
        * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
        */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            require(b <= a);
            return a - b;
        }
    
        /**
        * @dev Adds two numbers, throws on overflow.
        */
        function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
            c = a + b;
            require(c >= a);
            return c;
        }
    }
    
    contract Meebits is IERC721 {
    
        using SafeMath for uint256;
    
        /**
         * Event emitted when minting a new NFT. "createdVia" is the index of the Cryptopunk/Autoglyph that was used to mint, or 0 if not applicable.
         */
        event Mint(uint indexed index, address indexed minter, uint createdVia);
    
        /**
         * Event emitted when a trade is executed.
         */
        event Trade(bytes32 indexed hash, address indexed maker, address taker, uint makerWei, uint[] makerIds, uint takerWei, uint[] takerIds);
    
        /**
         * Event emitted when ETH is deposited into the contract.
         */
        event Deposit(address indexed account, uint amount);
    
        /**
         * Event emitted when ETH is withdrawn from the contract.
         */
        event Withdraw(address indexed account, uint amount);
    
        /**
         * Event emitted when a trade offer is cancelled.
         */
        event OfferCancelled(bytes32 hash);
    
        /**
         * Event emitted when the public sale begins.
         */
        event SaleBegins();
    
        /**
         * Event emitted when the community grant period ends.
         */
        event CommunityGrantEnds();
    
        bytes4 internal constant MAGIC_ON_ERC721_RECEIVED = 0x150b7a02;
    
        // IPFS Hash to the NFT content
        string public contentHash = "QmfXYgfX1qNfzQ6NRyFnupniZusasFPMeiWn5aaDnx7YXo";
    
        uint public constant TOKEN_LIMIT = 20000;
        uint public constant SALE_LIMIT = 9000;
    
        mapping(bytes4 => bool) internal supportedInterfaces;
    
        mapping (uint256 => address) internal idToOwner;
    
        mapping (uint256 => uint256) public creatorNftMints;
    
        mapping (uint256 => address) internal idToApproval;
    
        mapping (address => mapping (address => bool)) internal ownerToOperators;
    
        mapping(address => uint256[]) internal ownerToIds;
    
        mapping(uint256 => uint256) internal idToOwnerIndex;
    
        string internal nftName = "Meebits";
        string internal nftSymbol = unicode"⚇";
    
        uint internal numTokens = 0;
        uint internal numSales = 0;
    
        // Cryptopunks contract
        address internal punks;
    
        // Autoglyphs contract
        address internal glyphs;
    
        address payable internal deployer;
        address payable internal beneficiary;
        bool public communityGrant = true;
        bool public publicSale = false;
        uint private price;
        uint public saleStartTime;
        uint public saleDuration;
    
        //// Random index assignment
        uint internal nonce = 0;
        uint[TOKEN_LIMIT] internal indices;
    
        //// Market
        bool public marketPaused;
        bool public contractSealed;
        mapping (address => uint256) public ethBalance;
        mapping (bytes32 => bool) public cancelledOffers;
    
        modifier onlyDeployer() {
            require(msg.sender == deployer, "Only deployer.");
            _;
        }
    
        bool private reentrancyLock = false;
    
        /* Prevent a contract function from being reentrant-called. */
        modifier reentrancyGuard {
            if (reentrancyLock) {
                revert();
            }
            reentrancyLock = true;
            _;
            reentrancyLock = false;
        }
    
        modifier canOperate(uint256 _tokenId) {
            address tokenOwner = idToOwner[_tokenId];
            require(tokenOwner == msg.sender || ownerToOperators[tokenOwner][msg.sender], "Cannot operate.");
            _;
        }
    
        modifier canTransfer(uint256 _tokenId) {
            address tokenOwner = idToOwner[_tokenId];
            require(
                tokenOwner == msg.sender
                || idToApproval[_tokenId] == msg.sender
                || ownerToOperators[tokenOwner][msg.sender], "Cannot transfer."
            );
            _;
        }
    
        modifier validNFToken(uint256 _tokenId) {
            require(idToOwner[_tokenId] != address(0), "Invalid token.");
            _;
        }
    
        constructor(address _punks, address _glyphs, address payable _beneficiary) {
            supportedInterfaces[0x01ffc9a7] = true; // ERC165
            supportedInterfaces[0x80ac58cd] = true; // ERC721
            supportedInterfaces[0x780e9d63] = true; // ERC721 Enumerable
            supportedInterfaces[0x5b5e139f] = true; // ERC721 Metadata
            deployer = msg.sender;
            punks = _punks;
            glyphs = _glyphs;
            beneficiary = _beneficiary;
        }
    
        function startSale(uint _price, uint _saleDuration) external onlyDeployer {
            require(!publicSale);
            price = _price;
            saleDuration = _saleDuration;
            saleStartTime = block.timestamp;
            publicSale = true;
            emit SaleBegins();
        }
    
        function endCommunityGrant() external onlyDeployer {
            require(communityGrant);
            communityGrant = false;
            emit CommunityGrantEnds();
        }
    
        function pauseMarket(bool _paused) external onlyDeployer {
            require(!contractSealed, "Contract sealed.");
            marketPaused = _paused;
        }
    
        function sealContract() external onlyDeployer {
            contractSealed = true;
        }
    
        //////////////////////////
        //// ERC 721 and 165  ////
        //////////////////////////
    
        function isContract(address _addr) internal view returns (bool addressCheck) {
            uint256 size;
            assembly { size := extcodesize(_addr) } // solhint-disable-line
            addressCheck = size > 0;
        }
    
        function supportsInterface(bytes4 _interfaceID) external view override returns (bool) {
            return supportedInterfaces[_interfaceID];
        }
    
        function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata _data) external override {
            _safeTransferFrom(_from, _to, _tokenId, _data);
        }
    
        function safeTransferFrom(address _from, address _to, uint256 _tokenId) external override {
            _safeTransferFrom(_from, _to, _tokenId, "");
        }
    
        function transferFrom(address _from, address _to, uint256 _tokenId) external override canTransfer(_tokenId) validNFToken(_tokenId) {
            address tokenOwner = idToOwner[_tokenId];
            require(tokenOwner == _from, "Wrong from address.");
            require(_to != address(0), "Cannot send to 0x0.");
            _transfer(_to, _tokenId);
        }
    
        function approve(address _approved, uint256 _tokenId) external override canOperate(_tokenId) validNFToken(_tokenId) {
            address tokenOwner = idToOwner[_tokenId];
            require(_approved != tokenOwner);
            idToApproval[_tokenId] = _approved;
            emit Approval(tokenOwner, _approved, _tokenId);
        }
    
        function setApprovalForAll(address _operator, bool _approved) external override {
            ownerToOperators[msg.sender][_operator] = _approved;
            emit ApprovalForAll(msg.sender, _operator, _approved);
        }
    
        function balanceOf(address _owner) external view override returns (uint256) {
            require(_owner != address(0));
            return _getOwnerNFTCount(_owner);
        }
    
        function ownerOf(uint256 _tokenId) external view override returns (address _owner) {
            require(idToOwner[_tokenId] != address(0));
            _owner = idToOwner[_tokenId];
        }
    
        function getApproved(uint256 _tokenId) external view override validNFToken(_tokenId) returns (address) {
            return idToApproval[_tokenId];
        }
    
        function isApprovedForAll(address _owner, address _operator) external override view returns (bool) {
            return ownerToOperators[_owner][_operator];
        }
    
        function _transfer(address _to, uint256 _tokenId) internal {
            address from = idToOwner[_tokenId];
            _clearApproval(_tokenId);
    
            _removeNFToken(from, _tokenId);
            _addNFToken(_to, _tokenId);
    
            emit Transfer(from, _to, _tokenId);
        }
    
        function randomIndex() internal returns (uint) {
            uint totalSize = TOKEN_LIMIT - numTokens;
            uint index = uint(keccak256(abi.encodePacked(nonce, msg.sender, block.difficulty, block.timestamp))) % totalSize;
            uint value = 0;
            if (indices[index] != 0) {
                value = indices[index];
            } else {
                value = index;
            }
    
            // Move last value to selected position
            if (indices[totalSize - 1] == 0) {
                // Array position not initialized, so use position
                indices[index] = totalSize - 1;
            } else {
                // Array position holds a value so use that
                indices[index] = indices[totalSize - 1];
            }
            nonce++;
            // Don't allow a zero index, start counting at 1
            return value.add(1);
        }
    
        // Calculate the mint price
        function getPrice() public view returns (uint) {
            require(publicSale, "Sale not started.");
            uint elapsed = block.timestamp.sub(saleStartTime);
            if (elapsed >= saleDuration) {
                return 0;
            } else {
                return saleDuration.sub(elapsed).mul(price).div(saleDuration);
            }
        }
    
        // The deployer can mint in bulk without paying
        function devMint(uint quantity, address recipient) external onlyDeployer {
            for (uint i = 0; i < quantity; i++) {
                _mint(recipient, 0);
            }
        }
    
        function mintsRemaining() external view returns (uint) {
            return SALE_LIMIT.sub(numSales);
        }
    
        /**
         * Community grant minting.
         */
        function mintWithPunkOrGlyph(uint _createVia) external reentrancyGuard returns (uint) {
            require(communityGrant);
            require(!marketPaused);
            require(_createVia > 0 && _createVia <= 10512, "Invalid punk/glyph index.");
            require(creatorNftMints[_createVia] == 0, "Already minted with this punk/glyph");
            if (_createVia > 10000) {
                // It's a glyph
                // Compute the glyph ID
                uint glyphId = _createVia.sub(10000);
                // Make sure the sender owns the glyph
                require(IERC721(glyphs).ownerOf(glyphId) == msg.sender, "Not the owner of this glyph.");
            } else {
                // It's a punk
                // Compute the punk ID
                uint punkId = _createVia.sub(1);
                // Make sure the sender owns the punk
                require(Cryptopunks(punks).punkIndexToAddress(punkId) == msg.sender, "Not the owner of this punk.");
            }
            creatorNftMints[_createVia]++;
            return _mint(msg.sender, _createVia);
        }
    
        /**
         * Public sale minting.
         */
        function mint() external payable reentrancyGuard returns (uint) {
            require(publicSale, "Sale not started.");
            require(!marketPaused);
            require(numSales < SALE_LIMIT, "Sale limit reached.");
            uint salePrice = getPrice();
            require(msg.value >= salePrice, "Insufficient funds to purchase.");
            if (msg.value > salePrice) {
                msg.sender.transfer(msg.value.sub(salePrice));
            }
            beneficiary.transfer(salePrice);
            numSales++;
            return _mint(msg.sender, 0);
        }
    
        function _mint(address _to, uint createdVia) internal returns (uint) {
            require(_to != address(0), "Cannot mint to 0x0.");
            require(numTokens < TOKEN_LIMIT, "Token limit reached.");
            uint id = randomIndex();
    
            numTokens = numTokens + 1;
            _addNFToken(_to, id);
    
            emit Mint(id, _to, createdVia);
            emit Transfer(address(0), _to, id);
            return id;
        }
    
        function _addNFToken(address _to, uint256 _tokenId) internal {
            require(idToOwner[_tokenId] == address(0), "Cannot add, already owned.");
            idToOwner[_tokenId] = _to;
    
            ownerToIds[_to].push(_tokenId);
            idToOwnerIndex[_tokenId] = ownerToIds[_to].length.sub(1);
        }
    
        function _removeNFToken(address _from, uint256 _tokenId) internal {
            require(idToOwner[_tokenId] == _from, "Incorrect owner.");
            delete idToOwner[_tokenId];
    
            uint256 tokenToRemoveIndex = idToOwnerIndex[_tokenId];
            uint256 lastTokenIndex = ownerToIds[_from].length.sub(1);
    
            if (lastTokenIndex != tokenToRemoveIndex) {
                uint256 lastToken = ownerToIds[_from][lastTokenIndex];
                ownerToIds[_from][tokenToRemoveIndex] = lastToken;
                idToOwnerIndex[lastToken] = tokenToRemoveIndex;
            }
    
            ownerToIds[_from].pop();
        }
    
        function _getOwnerNFTCount(address _owner) internal view returns (uint256) {
            return ownerToIds[_owner].length;
        }
    
        function _safeTransferFrom(address _from,  address _to,  uint256 _tokenId,  bytes memory _data) private canTransfer(_tokenId) validNFToken(_tokenId) {
            address tokenOwner = idToOwner[_tokenId];
            require(tokenOwner == _from, "Incorrect owner.");
            require(_to != address(0));
    
            _transfer(_to, _tokenId);
    
            if (isContract(_to)) {
                bytes4 retval = ERC721TokenReceiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data);
                require(retval == MAGIC_ON_ERC721_RECEIVED);
            }
        }
    
        function _clearApproval(uint256 _tokenId) private {
            if (idToApproval[_tokenId] != address(0)) {
                delete idToApproval[_tokenId];
            }
        }
    
        //// Enumerable
    
        function totalSupply() public view returns (uint256) {
            return numTokens;
        }
    
        function tokenByIndex(uint256 index) public pure returns (uint256) {
            require(index >= 0 && index < TOKEN_LIMIT);
            return index + 1;
        }
    
        function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256) {
            require(_index < ownerToIds[_owner].length);
            return ownerToIds[_owner][_index];
        }
    
        //// Metadata
    
        /**
          * @dev Converts a `uint256` to its ASCII `string` representation.
          */
        function toString(uint256 value) internal pure returns (string memory) {
            if (value == 0) {
                return "0";
            }
            uint256 temp = value;
            uint256 digits;
            while (temp != 0) {
                digits++;
                temp /= 10;
            }
            bytes memory buffer = new bytes(digits);
            uint256 index = digits - 1;
            temp = value;
            while (temp != 0) {
                buffer[index--] = bytes1(uint8(48 + temp % 10));
                temp /= 10;
            }
            return string(buffer);
        }
    
        /**
          * @dev Returns a descriptive name for a collection of NFTokens.
          * @return _name Representing name.
          */
        function name() external view returns (string memory _name) {
            _name = nftName;
        }
    
        /**
         * @dev Returns an abbreviated name for NFTokens.
         * @return _symbol Representing symbol.
         */
        function symbol() external view returns (string memory _symbol) {
            _symbol = nftSymbol;
        }
    
        /**
         * @dev A distinct URI (RFC 3986) for a given NFT.
         * @param _tokenId Id for which we want uri.
         * @return _tokenId URI of _tokenId.
         */
        function tokenURI(uint256 _tokenId) external view validNFToken(_tokenId) returns (string memory) {
            return string(abi.encodePacked("https://meebits.larvalabs.com/meebit/", toString(_tokenId)));
        }
    
        //// MARKET
    
        struct Offer {
            address maker;
            address taker;
            uint256 makerWei;
            uint256[] makerIds;
            uint256 takerWei;
            uint256[] takerIds;
            uint256 expiry;
            uint256 salt;
        }
    
        function hashOffer(Offer memory offer) private pure returns (bytes32){
            return keccak256(abi.encode(
                        offer.maker,
                        offer.taker,
                        offer.makerWei,
                        keccak256(abi.encodePacked(offer.makerIds)),
                        offer.takerWei,
                        keccak256(abi.encodePacked(offer.takerIds)),
                        offer.expiry,
                        offer.salt
                    ));
        }
    
        function hashToSign(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt) public pure returns (bytes32) {
            Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
            return hashOffer(offer);
        }
    
        function hashToVerify(Offer memory offer) private pure returns (bytes32) {
            return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hashOffer(offer)));
        }
    
        function verify(address signer, bytes32 hash, bytes memory signature) internal pure returns (bool) {
            require(signer != address(0));
            require(signature.length == 65);
    
            bytes32 r;
            bytes32 s;
            uint8 v;
    
            assembly {
                r := mload(add(signature, 32))
                s := mload(add(signature, 64))
                v := byte(0, mload(add(signature, 96)))
            }
    
            if (v < 27) {
                v += 27;
            }
    
            require(v == 27 || v == 28);
    
            return signer == ecrecover(hash, v, r, s);
        }
    
        function tradeValid(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt, bytes memory signature) view public returns (bool) {
            Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
            // Check for cancellation
            bytes32 hash = hashOffer(offer);
            require(cancelledOffers[hash] == false, "Trade offer was cancelled.");
            // Verify signature
            bytes32 verifyHash = hashToVerify(offer);
            require(verify(offer.maker, verifyHash, signature), "Signature not valid.");
            // Check for expiry
            require(block.timestamp < offer.expiry, "Trade offer expired.");
            // Only one side should ever have to pay, not both
            require(makerWei == 0 || takerWei == 0, "Only one side of trade must pay.");
            // At least one side should offer tokens
            require(makerIds.length > 0 || takerIds.length > 0, "One side must offer tokens.");
            // Make sure the maker has funded the trade
            require(ethBalance[offer.maker] >= offer.makerWei, "Maker does not have sufficient balance.");
            // Ensure the maker owns the maker tokens
            for (uint i = 0; i < offer.makerIds.length; i++) {
                require(idToOwner[offer.makerIds[i]] == offer.maker, "At least one maker token doesn't belong to maker.");
            }
            // If the taker can be anybody, then there can be no taker tokens
            if (offer.taker == address(0)) {
                // If taker not specified, then can't specify IDs
                require(offer.takerIds.length == 0, "If trade is offered to anybody, cannot specify tokens from taker.");
            } else {
                // Ensure the taker owns the taker tokens
                for (uint i = 0; i < offer.takerIds.length; i++) {
                    require(idToOwner[offer.takerIds[i]] == offer.taker, "At least one taker token doesn't belong to taker.");
                }
            }
            return true;
        }
    
        function cancelOffer(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt) external {
            require(maker == msg.sender, "Only the maker can cancel this offer.");
            Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
            bytes32 hash = hashOffer(offer);
            cancelledOffers[hash] = true;
            emit OfferCancelled(hash);
        }
    
        function acceptTrade(address maker, address taker, uint256 makerWei, uint256[] memory makerIds, uint256 takerWei, uint256[] memory takerIds, uint256 expiry, uint256 salt, bytes memory signature) external payable reentrancyGuard {
            require(!marketPaused, "Market is paused.");
            require(msg.sender != maker, "Can't accept ones own trade.");
            Offer memory offer = Offer(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt);
            if (msg.value > 0) {
                ethBalance[msg.sender] = ethBalance[msg.sender].add(msg.value);
                emit Deposit(msg.sender, msg.value);
            }
            require(offer.taker == address(0) || offer.taker == msg.sender, "Not the recipient of this offer.");
            require(tradeValid(maker, taker, makerWei, makerIds, takerWei, takerIds, expiry, salt, signature), "Trade not valid.");
            require(ethBalance[msg.sender] >= offer.takerWei, "Insufficient funds to execute trade.");
            // Transfer ETH
            ethBalance[offer.maker] = ethBalance[offer.maker].sub(offer.makerWei);
            ethBalance[msg.sender] = ethBalance[msg.sender].add(offer.makerWei);
            ethBalance[msg.sender] = ethBalance[msg.sender].sub(offer.takerWei);
            ethBalance[offer.maker] = ethBalance[offer.maker].add(offer.takerWei);
            // Transfer maker ids to taker (msg.sender)
            for (uint i = 0; i < makerIds.length; i++) {
                _transfer(msg.sender, makerIds[i]);
            }
            // Transfer taker ids to maker
            for (uint i = 0; i < takerIds.length; i++) {
                _transfer(maker, takerIds[i]);
            }
            // Prevent a replay attack on this offer
            bytes32 hash = hashOffer(offer);
            cancelledOffers[hash] = true;
            emit Trade(hash, offer.maker, msg.sender, offer.makerWei, offer.makerIds, offer.takerWei, offer.takerIds);
        }
    
        function withdraw(uint amount) external reentrancyGuard {
            require(amount <= ethBalance[msg.sender]);
            ethBalance[msg.sender] = ethBalance[msg.sender].sub(amount);
            (bool success, ) = msg.sender.call{value:amount}("");
            require(success);
            emit Withdraw(msg.sender, amount);
        }
    
        function deposit() external payable {
            ethBalance[msg.sender] = ethBalance[msg.sender].add(msg.value);
            emit Deposit(msg.sender, msg.value);
        }
    
    }