Solidstamp Community Audit

This audit was performed on commit 4f06cca8fcf4c29bb3afd01d02ee240218fc4a19 by Matthew Di Ferrante.

The audit was performed as part of ZK Labs' community audit initiative for non-ICO projects.

The code is fairly simple, leveraging open zeppelin to maximize code reuse. There are not many functions and the amount of tracked state is minimal, keeping code complexity low.

Adequate tests are included which cover all functionality and code paths.

Flow Graph

Contract Intent

The SolidStamp contracts allow smart contract auditors to submit their outcomes for an audit on-chain to the SolidStamp registry. Then, users can look up a smart contract address (or code hash) and see how many audits it has received (if any), how often and how recently.

It also allows users to "request" an audit for an on-chain address, and fund a bounty in ETH for said audit, to incentivize audits for a contract. The requester specifies an address that it requests an audit from, such that only that address (or auditor) can fulfill it.

See https://www.solidstamp.com/ for more information about the project.

Contract Breakdown

The codebase consists of three main contracts, detailed below.

SolidStampRegister.sol

This contract maintains the "storage" for the SolidStamp contract, such that the functionality of SolidStamp can be upgraded without wiping out the audit history. It's a simple contract and inherits only from Zeppelin's Ownable.

constructor

The constructor allows populating an initial list of audits/outcomes, to carry over results from previous versions of the contract.

getAuditOutcome

This function returns an audit outcome for an (auditor, code hash) pair.

registerAuditOutcome

This function registers an audit outcome for an (auditor, code hash) pair. It can only be called by the SolidStamp contract.

changeSolidStampContract

This function allows the contract owner to change the address of the SolidStamp contract, in case it has been upgraded.

SolidStamp.sol

The SolidStamp contract is what users and auditors will directly interact with when requesting or committing audit results. It's also a fairly simply contract, and inherits from Zeppelin's Ownable, Pausable, and from a custom Upgradeable contract. The contract has "commission" functionality which allows the contract owner to take commission on audits requested via the smart contract, represented as a percentage of the total compensation, up to MAX_COMMISSION.

The contract has three main functions that users interact with, detailed below.

requestAudit

This function is called by users who want a certain auditor to audit a contract. The user chooses an auditor, code hash, and an audit duration / request expiration time. While calling this function, the user sends ETH as part of the contract call, which will go to the payout if the auditor takes on the job. An audit cannot be requested twice by the same user for a single (auditor, codehash) pair if the contract has already been audited.

A user can "extend" the expiry date of an audit, or add to the reward, by just calling this function repeatedly.

This function is only callable when the SolidStamp contract is not in the Paused state.

withdrawRequest

This function allows a user to cancel their audit request and withdraw the ETH they contributed to the payout. The user can only cancel their request if the "expiry" time for the request has lapsed.

auditContract

This function allows an auditor to submit their audit conclusion and retrieve the payout, minus the commission. The commission is stored in the contract to be withdrawn by the contract owner.

Upgradeable.sol

This is a simple contract, inheriting from Zeppelin's Pausable and Ownable, with a single function setNewAddress and single state variable newContractAddress, which holds the address of the "new contract" if the current contract has been phased out in favour of an upgrade.

Issues

Contract creator can change commission between a request and a payout

Ideally, commission would be set at the time of request, and unchangeable from that point on for that specific contribution, vs being applied on auditContract. For complexity's sake, it might be best to just fix the commission to a constant, unchangeable amount at deployment time.

Contract owner can change result of past audits

The contract owner can upgrade set the SolidStamp contract address in the registry to any arbitrary code (or even a normal account), which then can call into the registry and alter past entries. This should be prevented, and ideally audit commitments should check and store a signature from the auditor's address in the registry such that committments can't be spoofed by bad code.