RToken Ethereum Contracts

QuantstampFiles named in the report

Quantstamp reviewed Reserve (RToken Ethereum Contracts) on 31 Oct 2019: 9 findings, 0 critical; 5 marked fixed, 4 open.

No open critical findings
Open the reportOpen Reserve’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
Medium001
Low403
HighInteger Overflow / UnderflowFixed

Integer overflow/underflow occur when an integer hits its bit-size limit. Every integer has a set range; when that range is passed, the value loops back around. A clock is a good analogy: at 11:59, the minute hand goes to 0, not 60, because 59 is the largest possible minute. The following lines of code are potentially affected by integer overflow / underflow: * `L540: savingAssetOrignalAmount += sOriginalCreated;` * `L617: totalProportions += uint256(proportions[i]);` * `L621: (uint256(proportions[i]) * uint256(PROPORTION_BASE)) /` * `L667: if (rGross > (account.lDebt + account.rInterest)) {` * `L668: return rGross - account.lDebt - account.rInterest;` * `L705: (rAmount * hat.proportions[i]) / PROPORTION_BASE;` * `L717: (sInternalAmount * hat.proportions[i]) / PROPORTION_BASE;` * `L801: (rAmount * hat.proportions[i]) / PROPORTION_BASE;` * `L814: (sInternalAmount * hat.proportions[i]) / PROPORTION_BASE;`

MediumPossible Transfer to 0x0 / Contract AddressFixed

It is rarely desirable for tokens to be sent to the `0x0` address (intentional token burning is a notable exception) nor to the contract itself. However, these mistakes are often made due to human errors. Hence, it's often a good idea to prevent these mistakes from happening within the smart contract itself. Neither `createHat` nor `createHatInternal` checks if one of the `recipients` addresses are equal to `0x0`. This allows a user to set one of the recipients to `0x0` by mistake, which would effectively lead to transferring tokens to `0x0` when `distributeLoans` is called.

LowPossible Confusion between `savingAssetConversionRate` and `10**18`Fixed

On several lines of code (`L342`, `L386`, `L770`), the constant `10**18` is used for certain computations. For example: ``` 340: totalSavingsAmount += savingAssetOrignalAmount 341: .mul(ias.exchangeRateStored()) 342: .div(10**18); ``` Similar computations are being done on other lines of code using `savingAssetConversionRate`instead of the constant `10**18`. For example: ``` 368: stats.totalSavings = statsStored.totalInternalSavings 369: .mul(ias.exchangeRateStored()) 370: .div(savingAssetConversionRate); ``` Since the initial value used to initialize `savingAssetConversionRate` is `10**18`, it is unclear whether the constant `10**18` is being misused or not. A similar finding was observed for the same constant `10**18`and the call to `ias.exchangeRateStored()` (see `L770` versus `L750`).

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. The following unchecked return values were identified: * `RToken.changeAllocationStrategy(IAllocationStrategy)` ignores return value by external calls `token.transferFrom(msg.sender,address(this),totalSupply)` * `RToken.changeAllocationStrategy(IAllocationStrategy)` ignores return value by external calls `token.approve(address(ias),totalSupply)` * `RToken.mintInternal(uint256)` ignores return value by external calls `token.transferFrom(msg.sender,address(this),mintAmount)` * `RToken.mintInternal(uint256)` ignores return value by external calls `token.approve(address(ias),mintAmount)` * `RToken.redeemInternal(address,uint256)` ignores return value by external calls `token.transfer(redeemTo,redeemAmount)` * `RToken.estimateAndRecollectLoans(address,uint256)` ignores return value by external calls `ias.accrueInterest()` * `RToken.sameHatTransfer(address,address,uint256)` ignores return value by external calls `ias.accrueInterest()` * `RToken.payInterestInternal(address)` ignores return value by external calls `ias.accrueInterest()`

LowUse of Experimental Features in ProductionFixed

Some smart contracts rely on the experimental feature `ABIEncoderV2`, whose use is discouraged in production. Some bugs associated with it have already been reported (see [https://blog.ethereum.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/ and https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs/](https://blog.ethereum.org/2019/03/26/solidity-optimizer-and-abiencoderv2-bug/ and https://blog.ethereum.org/2019/06/25/solidity-storage-array-bugs/)), but have been fixed on release `0.5.10` onwards.

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 (17)

  • contracts/LibraryLock.sol
  • contracts/test/RinkebyDaiFaucet.sol
  • contracts/Ownable.sol
  • contracts/test/TestBundle.sol
  • contracts/CompoundAllocationStrategy.sol
  • contracts/test/StorageLayout.sol
  • contracts/IRTokenAdmin.sol
  • contracts/test/ComptrollerMock.sol
  • contracts/Proxiable.sol
  • contracts/RTokenStorage.sol
  • contracts/RTokenStructs.sol
  • contracts/Proxy.sol
  • contracts/ReentrancyGuard.sol
  • contracts/RToken.sol
  • contracts/IAllocationStrategy.sol
  • contracts/test/InterestRateModelMock.sol
  • contracts/IRToken.sol

Part of Reserve’s security record

Reserve
Audits4 audits by 4 firmsLast audit Mar 2026, by Oak Security.
Critical findingsNo open critical findingsAcross 4 reports.
Open Reserve’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