在 Solidity 中返回任意长度的结构数组

Returning arbitraty length array of structs in Solidity

在合同中,我试图实现某种结构的递归性。

我有一个对应于 Ticket 类型结构的钱包地址映射。

struct Ticket {
        uint256 ticketId;
        string firstname;
        string lastname;
    }
mapping (address => Ticket) tickets;

我对这个解决方案的问题是我不知道如何return 每张具有相同地址的票。

function setTicket(address _address, string memory _firstname, string memory _lastname) public returns(uint256){
        
        uint256 ticketNewId = uint256(keccak256(abi.encodePacked(block.timestamp, block.difficulty)));
        Ticket storage ticket = tickets[_address];
        ticket.firstname = _firstname;
        ticket.lastname = _lastname;
        ticket.ticketId = ticketNewId;
        ticketaccts.push(_address);
        return ticketNewId;
    }
    
    function getTickets() view public returns(address[] memory){
        return ticketaccts;
    }
    
    function getTicket(address _address) view public returns (Ticket memory){
        return (tickets[_address]);
    }

这里是 getTicket() return 给定 _address 的最后一张票。 但我想要的是 return 所有具有相同 _address 的票 我该怎么做?

有一个老式的解决方案可以提供读取调用

  • 一张送多少票getTicketCount(address)

  • 第n张票getTicket(address, n)

最终我选择的解决方案如下:

function getTicketByAddress(address _address) public view returns (Ticket[] memory){ 
        Ticket[] memory ticketByAddress = new Ticket[](tickets[_address].length);

        uint numberOfTicket = 0;

        for(uint i = 0; i < tickets[_address].length;  i++) {
            ticketByAddress[numberOfTicket] = tickets[_address][i];
            numberOfTicket++;
        }

        return ticketByAddress; //don't work well in remix!
    }

退款功能的用法示例:

function makeRefund(uint256 _ticketId ) public returns(Ticket memory) {
        Ticket[] memory ticketByAddress = new Ticket[](tickets[msg.sender].length);
        Ticket memory refundTicket;

        uint numberOfTicket = 0;

        for(uint i = 0; i < tickets[msg.sender].length;  i++) {
            ticketByAddress[numberOfTicket] = tickets[msg.sender][i];
            numberOfTicket++;
        }
        ticketByAddress[_ticketId].refunded = true;
        refundTicket = ticketByAddress[_ticketId];
        
        if(refundTicket.categorie == 1){
            uint256 time = (dateEvent - refundTicket.date)/86400;
            require(time >= 1, "It is too late for a refund!");
            msg.sender.transfer(ticketPrice);
            
            maxTickets++;
            totalTicket++;
        }

        return refundTicket;
    }