As of 23 Oct 2026, PerlinX has 2 audit reports by 1 security firm on Trustblock; the latest is by Quantstamp, dated 19 Aug 2020. Those reports list no open critical findings.
Record last updated . It holds audits and findings, contracts and incidents up to Oct 2026. Trustblock does not review code.
Newest first
| Audit | Security firm | Date | Scope | Critical findings | Report |
|---|---|---|---|---|---|
| PerlinXerc20emission | Security firm: Quantstamp | Date: | Scope: Files named in the report | No open critical findings | Open · certificate.quantstamp.com |
| PerlinXRewards.sol | Security firm: Quantstamp | Date: | Scope: Files named in the report | No open critical findings | Open · certificate.quantstamp.com |
Statuses are the security firm’s own, from each report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 2 |
| Medium | 0 | 1 | 0 |
| Low | 0 | 11 | 8 |
The contract has multiple admins. However, one admin can change the contract parameters without the consent of others. In this case, it is preferred to introduce a minimum quorum between admins instead of having a single admin doing a change. ** 2020-08-07 update ** The Perlin team stated that they have added `treasury` address for fund-sensitive actions.
Open the reportThere is no check on the input value given to `changeEraDuration`, which allows setting the era duration to zero. ** 2020-08-18 update **: Perlin team states that the design permits 0x0 as a valid input parameter.
Open the reportThe `changeIncentiveAddress` function does not check if `newIncentiveAddress` is different from `0x0`. ** 2020-08-18 update **: Perlin team states that the design permits 0x0 as a valid input parameter.
Open the reportAs it presently is constructed, the contract is vulnerable to the [allowance double-spend exploit](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/b4f87bb8fc25fb07f73099701e39e167a3d36465/contracts/token/ERC20/ERC20.sol#L71-L78), as with other ERC20 tokens. An example of an exploit goes as follows: 1. Alice allows Bob to transfer `N` amount of Alice's tokens (`N>0`) by calling the `approve()` method on `Token` smart contract (passing Bob's address and `N` as method arguments) 2. After some time, Alice decides to change from `N` to `M` (`M>0`) the number of Alice's tokens Bob is allowed to transfer, so she calls the `approve()` method again, this time passing Bob's address and `M` as method arguments 3. Bob notices Alice's second transaction before it was mined and quickly sends another transaction that calls the `transferFrom()` method to transfer `N` Alice's tokens somewhere 4. If Bob's transaction will be executed before Alice's transaction, then Bob will successfully transfer `N` Alice's tokens and will gain an ability to transfer another `M` tokens 5. Before Alice notices any irregularities, Bob calls `transferFrom()` method again, this time to transfer `M` Alice's tokens. The exploit (as described above) is mitigated through use of functions that increase/decrease the allowance relative to its current value, such as `increaseAllowance` and `decreaseAllowance`. Pending community agreement on an ERC standard that would protect against this exploit, we recommend that developers of applications dependent on `approve()` / `transferFrom()` should keep in mind that they have to set allowance to 0 first and verify if it was used before setting the new value. Teams who decide to wait for such a standard should make these recommendations to app developers who work with their token contract.
Open the reportThe `SafeMath` library is cloned in the file. A subset of the ERC20 has been cloned, with some modifications. The clone-and-own approach involves copying and adjusting open source code at one's own discretion. From the development perspective, it is initially beneficial as it reduces the amount of effort. However, from the security perspective, it involves some risks as the code may not follow the best practices, may contain a security vulnerability, or may include intentionally or unintentionally modified upstream libraries.
Open the reportThe constructor does not check if `_perlin1` is different from `0x0`, nor if it refers to a contract. If the given address is `0x0` or refers to an externally owned account (EOA), the `Perlin2 ` contract will not work as expected. ** 2020-08-19 update **: Perlin team states that it is for testing only and will be removed before the deployment of the contract.
Open the reportSmart 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. Specifically, `Perlinx2` gives the `DAO` address a privileged role, as only the `DAO` address can call functions marked as `onlyDAO ` (e.g., `changeEmissionCurve`, `changeEraDuration `, etc). ** 2020-08-18 update **: Perlin team has added related explanation to the README file.
Open the reportThe clone-and-own approach involves copying and adjusting open source code at one's own discretion. From the development perspective, it is initially beneficial as it reduces the amount of effort. However, from the security perspective, it involves some risks as the code may not follow the best practices, may contain a security vulnerability, or may include intentionally or unintentionally modified upstream libraries. Rather than the clone-and-own approach, a good industry practice is to use the Truffle framework for managing library dependencies. This eliminates the clone-and-own risks yet allows for following best practices, such as, using libraries. ** 2020-08-25 update **: The Perlin team considers that this is at low risk and all the problems related to it are reversible.
Open the reportCurrently, `listSynth` does not check if the input triple `<pool, synth, emp>` is valid; hence, it is possible to invoke `listSynth` with a pool address that has no relation to the given `synth` address, which in turn, has no relation to the given `emp` address. A similar issue occurs for `listPool`. ** 2020-08-05 update ** The Perlin team stated that: “A balance of flexibility required, since these are just lookups and future AMMs might be used where it is unknown how to verify. It is not critical if they are listed wrong. The WEB-UI will show errors and alert admin if they incorrectly added. It is then possible to overwrite by just listing again”.
Open the reportFunctions taking an input address (`constructor`, `listSynth`, `listPool`, `addAdmin`, etc) do not check if the given input is different from `0x0`, or if in the case of an expected contract address, that the input is indeed a contract. Passing in an incorrect input address may cause temporary downtime and/or unexpected behavior. ** 2020-08-25 update **: The Perlin team considers that this is at low risk and all the problems related to it are reversible.
Open the reportOn `L188`, `total` could be zero; if so, the transaction will revert and taking the snapshot will fail for all pools.
Open the reportThe function `claim` does not zero out a member’s rewards for an era. The specification stated that this should happen, and while it decreases the rewards, there is nothing that decreases the rewards mapping to a specific member. Specifically, the `mapMemberEraPool_Claim` is not zeroed out. ** 2020-08-05 update ** The Perlin team stated that: “Multiple reward assets can be claimed, eg PERL, or BAL, or in future UNI (Uniswap token). These assets are likely to be airdropped to the rewards contract and need to be claimed. Thus, must not zero out claims, since these claims need to be re-used. Instead, a new mapping mapMemberEraAsset_hasClaimed[msg.sender][era][rewardAsset] = true; Tracks whether a member has claimed for a particular reward asset or not”.
Open the reportThe reports name a repository or files. Open a report to see its scope.
Is this your project? Show this record on your own website. The label states what the record holds, links to this page and updates by itself. It is free and needs no sign-in.
Automatic: the three strongest facts of this project’s own record (its last audit and two more), highlighted. They update with the record. Picking a fact turns Automatic off.
<head><script src="https://widget.trustblock.run/project-widget.min.js" defer></script></head><body><divdata-tb-project-widgetdata-tb-project-slug="perlin"></div></body>
Paste the code where the label should appear. It uses no API credit and updates by itself.
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