In December 2024, Serai requested Trail of Bits audit our Ethereum contracts. This included our Schnorr signature contract, to verify signatures from the Serai validators, our router contract, to handle coins in to and out from Serai, and associated Rust libraries for interacting with these contracts. Also included was our logic for interpreting ERC20s transfers to Serai, without first requiring an approval transaction.
Our router is the most critical part of our Ethereum integration. Comparable to a bridge contract, it handles messages to and from the Serai network. In an age where cross-chain bridges are frequently insecure, and frequently compromised for billions of USD across the industry, our router contract represented a prime target. Accordingly, we wanted to work to ensure its correctness and accuracy.
Trail of Bits found no high, medium, nor low severity issues with the included scope, an increadible feat. Our quality of documentation was praised, and we were found to follow best practices. We had two informational findings, both remediated with Trail of Bits reviewing our fixes, and three comments; two were responded to and one was dismissed as intentional behavior.
The first informational finding was how alloy, a prominent Rust library for interacting with Ethereum, potentially panicked when decoding invalid calldata without checking it. While Serai never decoded arbitrary calldata without checking it, the latest release of alloy was expected to remove the ability to check calldata upon decoding. Accordingly, the concern was Serai would upgrade the version of alloy used, removing the checks performed upon the calldata, and become vulnerable to these panics. We have performed the upgrade to alloy's 1.0 release and validated the new version does not have the same panics, addressing the finding.
The second finding was how we didn't allow the identity point, or point at infinity, as a public key yet only via an indirect check. We intentionally banned points whose x-coordinates are zero, as they would have undefined behavior within our smart contract, yet the identity point is special in that it doesn't have a well-defined x-coordinate, and accordingly itself would exhibit undefined behavior. Conventionally, the x-coordinate of the identity point is considered zero however, and the Rust library we use for the secp256k1 elliptic curve did represent the identity point with zero for its x-coordinate. This meant we did ban the identity point, yet only due to this common convention, and not due to an explicit intent. While the identity point should never be observed in practice, as randomly selecting it as a public key has the same odds as selecting Satoshi's public key, we always want to ensure properly defined rules and flow throughout the entire codebase. We have since added an explicit check the public key is not the identity point.
One comment was on how our documentation in one location was out of date, which has been updated. One comment was on how when we sign messages for the Ethereum contract, we sign the blockchain's ID (ensuring a message for Ethereum is not also used with an another Ethereum-esque blockchain), yet we didn't sign the contract's address (ensuring a message for a router on Ethereum isn't used with another router on Ethereum). As we only expect to deploy a single router on any network, this wasn't an issue, but we agree it's better practice and have updated accordingly. Finally, it was noted how our contracts are built with a Solidity compiler whose version is explicitly compared to the expected value, instead of parsed with greater logic. As we only want our contracts built with a single version of the Solidity compiler, ensuring they're reproducible and verifiable, this was accepted as intended behavior.
Secure, properly functioning code is our utmost priority. We thank Trail of Bits for their thorough assessment and professional evaluation of our contracts. The findings and recommendations from this audit help inform our ongoing security efforts. For their full audit, please see their publication, which we've additionally uploaded to the Serai repository. We look forward to continuing publication of audits we have performed, and to the initial release of our codebase.