Airswap

QuantstampFiles named in the report

Quantstamp reviewed AirSwap on 20 Jan 2020: 9 findings, 0 critical; 7 marked fixed, 1 acknowledged, 1 open.

No open critical findings
Open the reportOpen AirSwap’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings9

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High001
Medium002
Low114
HighFunds may be locked if `setRuleAndIntent` is called multiple timesFixed

The function `Delegate.setRuleAndIntent` sets the stake of the delegate owner in the `Indexer` contract by transferring staking tokens from the user to the indexer, through the `Delegate` contract. However, if the function is called a second time, the underlying `Indexer.setIntent` will only transfer a partial amount of the total transferred tokens (i.e., the delta of the previously set intent value versus the currently set intent value). Since the behavior of the `Delegate` and the `Indexer` differ in this regard, tokens can become stuck in the Delegate. This is elaborated upon in issue [274](https://github.com/airswap/airswap-protocols/issues/274).

MediumCentralization of PowerFixed

Smart contracts will often have `owner` variables to designate the person with special privileges to make modifications to the smart contract. However, this centralization of power needs to be made clear to the users, especially depending on the level of privilege the contract allows to the owner. In particular, the owner may `selfdestruct` the contract locking funds forever. Since the `killContract()` function does not send any of the transferred tokens out of the contract, all tokens will remain permanently locked in the contract if not previously removed by users. The platform can censor transaction via `unsetIntentForUser()`: whenever an intent is set, the owner can just unset it. It is also not easy to see if it is the owners who did this, as the event emitted is the same. The owner may also permanently pause the contract locking funds.

MediumInteger arithmetic may cause incorrect pricing logicFixed

On L233 and L290, we have the following two conditions that relate sender and signer order amounts: * L233 (Equation "A"): `order.sender.param == order.signer.param.mul(10 ** rule.priceExp).div(rule.priceCoef)` * L290 (Equation "B"): `signerParam = senderParam.mul(rule.priceCoef).div(10 ** rule.priceExp);` Due to integer arithmetic truncation issues, these two equations may not relate as expected. Consider the case where: * rule.priceExp = 2 * rule.priceCoef = 3 For Equation B, when senderParam = 90, we obtain `signerParam = 90 * 3 // 100 = 2` due to integer truncation. However, when plugging back into Equation A, we obtain `2 * 100 // 3 = 66` (which doesn't equal the expected value of 90`. This means that if the signerParam is calculated by the logic in Equation B, it would not pass the requirement of Equation A.

Low`isValid()` does not check that the `validator` contract is correctFixed

While the `Swap` contract ensures that an `Order` is correctly formatted and properly signed in the `isValid()` function, it does not check that the intended `Swap` contract, as denoted by the `Order.signature.validator` field, corresponds to the correct `Swap` contract. If a sender/signer participates with multiple swap contracts, replay attacks may be possible by re-submitting the order.

Low`transferFrom()` success should not be checked by querying token balancesFixed

On L349: `require(initialBalance.sub(param) == INRERC20(token).balanceOf(from), "TRANSFER_FAILED");` is a dangerous equality. Although this will hold for most ERC20 tokens, the specification does not guarantee that the external ERC20 contract will adhere to this condition. For example, the token could mint or burn tokens upon a `transfer()` for various reasons.

LowReturn values of ERC20 function calls are not checkedFixed

On L346 of `Swap.sol`, `ERC20.transferFrom()` is expected to return a boolean value indicating success. Although the `INRERC20` is used here, the underlying contract is most likely an `ERC20` token, and therefore its return value should be checked for success.

LowUnchecked Return ValueFixed

Most functions will return a `true` or `false` value upon success. Some functions, like `send()`, are more crucial to check than others. It's important to ensure that every necessary function is checked. On L151 of `Wrapper`, the external `call.value()` is not checked for success, which may cause ether transfers to the user to fail. A similar issue exists for the `transfer()` on L127 of `Wrapper`, and L340 of `Swap`.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (39)

  • source/tokens/contracts/FungibleToken.sol
  • source/swap/contracts/Migrations.sol
  • source/tokens/contracts/IERC721Receiver.sol
  • source/delegate-factory/contracts/interfaces/IDelegateFactory.sol
  • source/types/contracts/Imports.sol
  • source/wrapper/contracts/Wrapper.sol
  • source/indexer/contracts/interfaces/ILocatorWhitelist.sol
  • source/tokens/contracts/AdaptedERC721.sol
  • source/delegate-factory/contracts/Imports.sol
  • source/indexer/contracts/Migrations.sol
  • source/tokens/contracts/WETH9.sol
  • source/delegate/contracts/interfaces/IDelegate.sol
  • source/swap/contracts/Swap.sol
  • source/tokens/contracts/OMGToken.sol
  • source/delegate/contracts/Migrations.sol
  • source/tokens/contracts/interfaces/INRERC20.sol
  • source/wrapper/contracts/HelperMock.sol
  • source/swap/contracts/interfaces/ISwap.sol
  • source/tokens/contracts/Migrations.sol
  • source/delegate-factory/contracts/Migrations.sol
  • source/tokens/contracts/NonFungibleToken.sol
  • source/wrapper/contracts/Migrations.sol
  • source/indexer/contracts/Indexer.sol
  • source/swap/contracts/Imports.sol
  • source/tokens/contracts/OrderTest721.sol
  • source/types/contracts/Migrations.sol
  • source/types/contracts/Types.sol
  • source/indexer/contracts/Imports.sol
  • source/wrapper/contracts/Imports.sol
  • source/index/contracts/Migrations.sol
  • source/index/contracts/Imports.sol
  • source/tokens/contracts/interfaces/IWETH.sol
  • source/types/test/MockTypes.sol
  • source/delegate-factory/contracts/DelegateFactory.sol
  • source/index/contracts/Index.sol
  • source/tokens/contracts/KittyCore.sol
  • source/delegate/contracts/Delegate.sol
  • source/delegate/contracts/Imports.sol
  • source/indexer/contracts/interfaces/IIndexer.sol

Part of AirSwap’s security record

AirSwap
Audits7 audits by 2 firmsLast audit Apr 2024, by PeckShield.
Critical findingsNo open critical findingsAcross 7 reports.
Open AirSwap’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us