¿Por qué cryptokitties usa almacenamiento en lugar de memoria?

Hay muchas explicaciones sobre el almacenamiento y la memoria, como esta pregunta o esta pregunta . Pero me pregunto por qué cryptokitties, por ejemplo, usa almacenamiento en lugar de memoria en muchas funciones. En este caso auctionno se modifica. ¿No sería más barato usar memoria aquí?

function _bid(uint256 _tokenId, uint256 _bidAmount) internal returns (uint256) {

    Auction storage auction = _getAuctionByTokenId(_tokenId);
    require(_isOnAuction(auction));

    uint256 price = _currentPrice(auction);
    require(_bidAmount >= price);

    address seller = auction.seller;
    _removeAuction(_tokenId);

    // Transfer proceeds to seller (if there are any!)
    if (price > 0) {
       ...
        uint256 auctioneerCut = _computeCut(price);
        uint256 sellerProceeds = price - auctioneerCut;
        // Ether transfer
        seller.transfer(sellerProceeds);
    }

    emit AuctionSuccessful(_tokenId, price, msg.sender);
    return price;
}

Respuestas (2)

Porque no está creando un nuevo objeto sino que es un puntero de almacenamiento. _getAuctionByTokenIdlo más probable es que lea algo en el almacenamiento del contrato.

Supongamos este ejemplo

contract MyContract {
    struct myStruct {
        address id;
    }
    mapping(address => myStruct) myMapping;

    function doSomeStuff(address _tokenId) public view returns(address) {    
        myStruct storage myObj = myMapping[_tokenId];

        return myObj.id;
    }   
}

myObjno es un objeto nuevo sino un puntero a una ubicación de almacenamiento ya almacenada dentro de mi contrato. Si elimino la storagepalabra clave, obtendría la siguiente advertencia:

Advertencia: la variable se declara como un puntero de almacenamiento. Utilice una palabra clave de "almacenamiento" explícita para silenciar esta advertencia.

Es más barato de usar storage, porque solo crea un puntero. Si tuviera que usar memory, la función esencialmente tendría que crear una copia de Auction, que luego se descartaría al final de la función.

Lo hicieron porque no hay manipulación de auction, si quisieran modificarlo de alguna manera, pero no cambiaron el valor almacenado, entonces sería mejor usar memory.

Acabo de leer este artículo en Medium que describe claramente la diferencia entre los dos.