The team of Augur contracted byterocket to conduct a smart contract audit of the turbo module, an implementation of Augur that uses on-chain data sources for near-immediate market and resolution data.
The turbo module contains:
The team of byterocket reviewed and audited the above smart contracts in the course of this audit. We started on the 4th of May and finished on the 23rd of May.
The audit included the following services:
byterocket gained access to the code via their public GitHub repository. We started the audit on the dev branch’s state on May 3rd, 2021 (commit hash d90917167839c60fd08887c47471a68f386cf418). Throughout our audit, changes have been made to the code, which we incorporated up until the latest state of the branch on May 19th, 2021 (commit hash 982e468e8c5c3a17e6959e9de8d6c06569fa60c5). Any subsequent changes have not been verified by us.
We conducted a manual multi-pass code review of the smart contracts mentioned in section (1). Three different auditors went through the smart contract independently and compared their results in multiple concluding discussions.
These contracts are written according to the latest standards used within the Ethereum community and the Solidity community’s best practices. The naming of variables is very logical and understandable, which results in the contract being easy to understand. The code is very well documented and up to the latest standards. A very helpful document has been provided to us, describing the architectural principles and goals of the smart contracts and the implemented protocol. As per our analysis, the code conforms with the architectural document.
Some of our earlier findings have already been fixed throughout the changes that happened in the repository between May 3rd and May 23rd 2021, which have subsequently been disregarded.
On the code level, we found no bugs or flaws, only a potential false positive. Besides that, we have noted some minor other findings. A further check with multiple automated reviewing tools (MythX, Slither, Manticore, and different fuzzing tools) did not find any additional bugs besides some common false positives.
A common false positive that came up multiple times throughout the automated checks that we did was the exit() function in the FeePot contract, stating that redeemInternal() function call does facilitate a transfer before the corresponding state changes and the token burn takes place. We do not think that a reentrancy attack is possible here and were not able to facilitate one throughout our various tests, which also took place on our custom testnet. We are fairly confident that this is a false positive finding and we won’t flag it as a vulnerability because of that.
We still advise the developers to have an additional look at this code segment and maybe consider a slight rewrite that would reorder the execution here.
The code segment from line 196 to 198 should only execute if _fees is greater than 0 in order to save gas and not unnecessarily emit an event. However, this poses absolutely no threats to the overall security, hence we are only noting it.
The code segment from line 205 to 207 should only execute if _fees is greater than 0 in order to save gas and not unnecessarily emit an event. However, this poses absolutely no threats to the overall security, hence we are only noting it.
Part of our audits are also analyses of the protocol and its logic. A team of three auditors went through the implementation and documentation of the implemented protocol.
We were not able to find any weaknesses or underlying problems of a game theoretic nature in the protocol and it’s logic. We were also not able to think of any loopholes that were not covered by the Augur developers.
In our discussion we were not able to find any weaknesses within the implementation of the protocol. None of our function calls (even when we did randomized fuzzing tests) were able to produce any unforeseen outcomes and skew the results in any way. The overall process flow was valid at all times.
Thus, We were not able to discover any problems in the protocol implemented in the smart contract.
As per our testing strategy, we deploy audited smart contracts (if requested by the client) onto a testnet to verify the implementation’s functionality. We usually deploy simple smart contracts to a local Ganache instance, which is sufficient for most cases. In this case. we wanted to ensure no Ganache-related coverups of the contracts’ misbehavior. We created two testnets: a geth-based one and a parity/openethereum-based one. All of our tests have been executed on both testnets without any difference in the results. We were able to use the contracts as intended and could not maliciously game the protocol in practice.
We used fuzzing tools that generate random and semi-random inputs and interact with the contracts, trying to produce any unforeseen states within the contracts, especially the treasury contract. Throughout our tests, we were not able to create or observe any issues or problems. The contract behaved as expected and reverted correctly, given wrong inputs. No unforeseen states occurred during our fuzz-tests.
The potential false positive reentrancy attack mentioned in (2.1) could also not be executed by us after several tests to do so. Even after manually modifying the block times and execution order, an exploit was not possible. This led us to the conclusion that this is most likely a false positive.
When looking at how the contracts behave in practice, we also take a look at the provided unit tests. The overall quality of the repository and its structure is very high, which does also include well-written unit tests with good coverage.
All of the current best-practice checks have been implemented. While there is certainly room for further improvement, we deem that the provided tests sufficiently test all of the contracts functionalities.
In our tests none of the provided unit tests failed. All in all, we are very satisfied with the provided unit tests, their quality and the overall test coverage. We were not able to find any issues with the provided tests.
During our code review (which was done manually and automated), we found no bugs or flaws. Our automated systems and review tools came up with one false positive particularly often, which is mentioned in section (2.1). We manually verified this finding multiple times and subsequently deemed it a false positive, not being able to exploit the contracts through this code segment.
The protocol review and analysis did neither uncover any game-theoretical nature problems nor any other functions prone to abuse.
During our multiple deployments to various local testnets, we haven’t been able to find any additional problems or unforeseen issues. The provided unit tests worked flawlessly and we were also not able to find any issues here.
In general, we are delighted with the overall quality of the code, its tests and documentation.
We store our public audit reports on IPFS; a peer-to-peer network called the "Inter Planetary File System". This allows us to store our reports in a distributed network instead of just a single server, so even if our website is down, every report is still available.
The IPFS Hash, a unique identifier of the report, is signed on-chain by both the client and us to prove that both sides have approved this audit report. This signing mechanism allows users to verify that neither side has faked or tampered with the audit.