Security

Locking Aavegotchi state before trading

Without some kind of locking mechanism it is possible to put up an Aavegotchi for sale and for the owner to remove or alter the state of the Aavegotchi right when/after it is sold but before the transfer occurs. This is a front-running attack.

The following function locks certain assets and the state of an Aavegotchi for a number of seconds specified by _lockDuration

function lockAavegotchi(uint256 _tokenId, uint256 _lockDuration) external 
  onlyUnlocked(_tokenId) 
{
  require(
    s.aavegotchis[_tokenId].status == LibAppStorage.STATUS_AAVEGOTCHI, 
    "AavegotchiFacet: Must be claimed"
  );
  require(
    msg.sender == s.aavegotchis[_tokenId].owner, 
    "AavegotchiFacet: Only owner can lock aavegotchi"
  );
  s.aavegotchis[_tokenId].unlockTime = block.timestamp + _lockDuration;
  emit LockAavegotchi(_tokenId, _lockDuration);
 }

The onlyUnlocked modifier is on functions that should only be called when an aavegotchi is unlocked. It causes functions to revert if an aavegotchi is locked.

modifier onlyUnlocked(uint256 _tokenId) {
  require(
    s.aavegotchis[_tokenId].unlockTime < block.timestamp, 
    "Only callable on unlocked Aavegotchis"
  );
  _;
}

The general rule is that state changes caused by external function calls that can be bad for an aavegotchi can only succeed when the aavegotchi is unlocked.

Here are functions that can only be called when an Aavegotchi is unlocked:

  • setAavegotchiName

  • spendSkillPoints

  • lockAavegotchi

  • decreaseStake

  • decreaseAndDestroy

  • transferFromParent ERC998 function that transfers items out of aavegotchi.

  • transferAsChild ERC998 function that transfers items out of aavegotchi to other aavegotchi or NFT.

  • useConsumable

Note that the equipWearables function does not have to be unlocked to use. The reason is because equipWearables does not remove items from the inventory of an Aavegotchi.

Last updated