Skip to content

Listing all kitties owned by a user is O(n^2) #4

@Arachnid

Description

@Arachnid

Description

tokensOfOwnerByIndex linearly scans all kitties looking for the nth one owned by the specified account. Since each call iterates over all the previous results, if there are n kitties, m of them owned by the specified address, this will take O(m * n) time.

Although this function notes that it's not intended to be called onchain, even offchain the execution time of listing kitties will soon become impractical.

Scenario

  1. Create lots of kitties.
  2. Attempt to enumerate all kitties owned by someone with lots of kitties.

Impact

It may become effectively impossible to list someone's kitties - particularly newer ones.

Reproduction

See Scenario.

Fix

Maintain an array of kitties-by-owner. This array can be efficiently updated by moving the last element into deleted indexes, since it's not necessary for the array to be kept in order. EG:

mapping(address=>uint[]) kittiesByOwner;

function deleteKitty(address owner, uint idx) {
  var kittyList = kittiesByOwner[owner];
  require(idx < kittyList.length);
  if(idx < kittyList.length - 1) {
    kittyList[idx] = kittyList[kittyList.length - 1];
  }
  kittyList.length -= 1;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions