1 Summary
ConsenSys Diligence conducted a security audit on the PegaSys Permissioning smart contracts. These contracts are used to provide on-chain permission rules for a Pantheon node.
2 Audit Scope
This audit covered the following files:
File Name | SHA-1 Hash |
---|---|
AccountIngress.sol | 57207a6878535bc2f3d40216d96f07eef9bbdfd9 |
AccountRulesList.sol | 73ffd92be5b6c3b1e18d1b860344dac578c9aa31 |
Admin.sol | e13931323093f1555f4dfcc74fad6a2c457c1082 |
AdminProxy.sol | eecd073b4e05a4445fb00888074b48c443c5bbf4 |
Ingress.sol | b0fcff06fa7d55136cfe483331280e4e9bb9def4 |
NodeIngress.sol | 3f46f78e4c1b9a546287135a13ffa303f62a826b |
NodeRulesList.sol | fa9382c4cf3f4d800aa3d0e89bb9a712d5aa5f0c |
AccountRules.sol | c730212300e070ed22b1490f6e67347d1f36c051 |
AccountRulesProxy.sol | 1024d00149ee0258f5ee4c0671a09ada723c3645 |
AdminList.sol | 0304e06bfc4c87abc4d2f4c0361633590c5ef830 |
NodeRules.sol | 8f0dc9efd5bc09a8c6346495e23a398c907baf21 |
NodeRulesProxy.sol | 01967d8481a3f1497ecdfcfcd5e7dd2ea9f9c17e |
The audit team evaluated that the system is secure, resilient, and working according to its specifications. The audit activities can be grouped into the following three broad categories:
- Security: Identifying security related issues within the contract.
- Architecture: Evaluating the system architecture through the lens of established smart contract best practices.
- Code quality: A full review of the contract source code. The primary areas of focus include:
- Correctness
- Readability
- Scalability
- Code complexity
- Quality of test coverage
3 System Overview
Pantheon, an enterprise Ethereum client, can be used to create permissioned networks. Such a network has rules dictating what nodes are allowed to connect and what transactions are allowed to be submitted. The Permissioning smart contracts are an on-chain mechanism for managing these rules and synchronizing them among clients.
3.1 Detailed Design
Two contracts are included as part of the network’s genesis block:
AccountIngress
is used to check whether incoming transactions should be allowed. It callstransactionAllowed
on theAccountRules
contract.NodeIngress
is used to check whether incoming node connections should be allowed. It callsconnectionAllowed
on theNodeRules
contract.
These contracts are a layer of indirection that can be used for upgradeability. Rather than directly implement permissioning rules, they delegate to other contracts which can be swapped at runtime by administrators.
The following contracts provide the actual rules implementations:
AccountRules
keeps a whitelist of accounts that are allowed to make transactions.NodeRules
keeps a whitelist of nodes that are allowed to connect to the network.
Finally, the Admin
contract is used to keep a whitelist of administrator accounts. These accounts are allowed to add or remove things from the whitelists. They can also swap out the rules contracts altogether.
4 Key Observations/Recommendations
- Overall the system is low in complexity but general enough to allow more sophisticated contracts in the future.
- There is a lot of code duplication, especially between
AccountRulesList
andNodeRulesList
. Some of it could perhaps be factored out into a common base contract. - All administrators have equal rights in the system. This means that any administrator can remove all the other administrators or change any of the contracts. This limits the contracts’ usefulness to situations where all administrators trust each other.
5 Style Recommendations
We recommend implementing the following changes to improve the maintainability and readability of the code.
5.1 Use 0
to represent a bytes32
zero value
In contracts/Ingress.sol
, comparisons can be done with 0
rather than 0x0000000000000000000000000000000000000000000000000000000000000000
.
5.2 Use the external
visibility rather than public
when possible
If a function does not need to be called by the contract itself, it can be labelled external. This clarifies the intention, and may allow the compiler to improve gas efficiency.
The following functions can be labelled external
:
AccountRules.getContractVersion()
AccountRules.isReadOnly()
AccountRules.enterReadOnly()
AccountRules.exitReadOnly()
AccountRules.transactionAllowed(address,address,uint256,uint256,uint256,bytes)
AccountRulesProxy.transactionAllowed(address,address,uint256,uint256,uint256,bytes)
AccountRules.addAccount(address)
AccountRules.removeAccount(address)
AccountRules.getSize()
AccountRules.getByIndex(uint256)
AccountRules.getAccounts()
AccountRules.addAccounts(address[])
Ingress.setContractAddress(bytes32,address)
Ingress.removeContract(bytes32)
Ingress.getAllContractKeys()
NodeRules.getContractVersion()
NodeRules.isReadOnly()
NodeRules.enterReadOnly()
NodeRules.exitReadOnly()
NodeRulesProxy.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16)
NodeRules.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16)
NodeRules.addEnode(bytes32,bytes32,bytes16,uint16)
NodeRules.removeEnode(bytes32,bytes32,bytes16,uint16)
NodeRules.getSize()
NodeRules.getByIndex(uint256)
Admin.addAdmin(address)
Admin.removeAdmin(address)
Admin.getAdmins()
Admin.addAdmins(address[])
NodeIngress.getContractVersion()
NodeIngress.emitRulesChangeEvent(bool)
NodeIngress.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16)
AccountIngress.getContractVersion()
AccountIngress.emitRulesChangeEvent(bool)
AccountIngress.transactionAllowed(address,address,uint256,uint256,uint256,bytes)
5.3 Declare variables as constant
where possible
If a variable is not meant to change, it should be labelled as constant
. This will save on gas costs, and increase safety.
The following storage variables can be made constant
:
Ingress.ADMIN_CONTRACT
Ingress.RULES_CONTRACT
NodeIngress.version
NodeRules.version
5.4 Declare important literals as constants
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
appears in two places in the code, and 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
appears once.
These literal values should be declared as constant
s and given a name that describes their semantics.
5.5 Return explicitly
Solidity allows functions to end without a return
statement, as happens in NodeRules.getByIndex()
and AccountRules.getByIndex()
if the specified index does not exist.
Functions are easier to use, analyze, and maintain when return statements are explicit in all code branches (or where all returns use a named return variable).
5.6 Give contracts more descriptive and consistent names
More descriptive contract naming would aid maintainability.
- The contracts that have names ending with
Proxy
areInterface
s and not proxies. AccountRulesList
could be namedAccountList
.Admin
’s similarities toNodeRules
andAccountRules
may be more obvious if either all or none of these contract names used theRules
suffix.- The purpose of
Exposed
contracts may be more immediately understood if the prefix was changed toTest
and/or if they were moved into a folder containing only test contracts.
5.7 Give event parameters more descriptive names
The meaning of the adminAdded
parameter in the AdminAdded
event is not obvious. The log might be better named AdminAddRequested
, and/or the parameter might be better named successful
.
The same feedback applies to the first parameters in the following events:
AdminRemoved
NodeAdded
NodeRemoved
AccountAdded
AccountRemoved
6 Security Specification
This section describes, from a security perspective, the expected behavior of the system under audit. It is not a substitute for documentation. The purpose of this section is to identify specific security properties that were validated by the audit team.
6.1 Actors
The relevant actors are as follows:
- Nodes – Only authorized nodes may connect to the network. Once connected, though, a node’s operator can replace the Pantheon software with software of their choosing, which enables them to bypass any on-chain connection restrictions.
- Administrators – These are on-chain accounts that have the ability to change the rules contracts and to grant and revoke administrative priveleges to others.
- Authorized accounts – These accounts have been permitted, based on the on-chain permissioning system, to send transactions.
- Other accounts – Other accounts should be unable to send transactions.
6.2 Trust Model
In any smart contract system, it’s important to identify what trust is expected/required between various actors. For this audit, we established the following trust model:
- Everyone must trust the administrators fully. They each have the ability to single-handedly take over the permissioning system, so all participants in the network, including the administrators themselves, must fully trust all the administrators.
- Node operators are free to make their nodes do whatever they want. The rest of the network should not have to trust that a given node is acting properly. The network should be robust to a malicious or buggy node.
6.3 Important Security Properties
The following is a non-exhaustive list of security properties that were verified in this audit:
- It’s possible for each node to validate all incoming blocks and reject those that violate permissioning rules. This means there’s no need to trust the other nodes in the network.
- Non-administrators cannot change the rules contracts or change any of the rules themselves.
7 Issues
Each issue has an assigned severity:
- Minor issues are subjective in nature. They are typically suggestions around best practices or readability. Code maintainers should use their own judgment as to whether to address such issues.
- Medium issues are objective in nature but are not security vulnerabilities. These should be addressed unless there is a clear reason not to.
- Major issues are security vulnerabilities that may not be directly exploitable or may require certain conditions in order to be exploited. All major issues should be addressed.
- Critical issues are directly exploitable security vulnerabilities that need to be fixed.
7.1 readOnlyMode
is ineffective and may result in a false sense of security Medium ✓ Addressed
Resolution
ed2d4a2
by adding comments to clarify that readOnlyMode
is meant simply to prevent accidental changes during upgrades.
Description
AccountRules
and NodeRules
can both enter and exit a mode of operation called readOnlyMode
.
The only effect of readOnlyMode
is to prevent admins (who are the only users able to change rules) from changing rules.
Those same admins can disable readOnlyMode
, so this mode will not prevent a determined actor from doing something they want to do.
Recommendation
Either readOnlyMode
should be removed to prevent it from providing a false sense of security, or the authorization required to toggle readOnlyMode
should be separated from the authorization required to change rules.
7.2 Ingress.setContractAddress()
can cause duplicate entries in contractKeys
Medium ✓ Fixed
Resolution
faff726
.
Description
setContractAddress()
checks ContractDetails
existence by inspecting contractAddress
. A contractAddress
of 0
means that the contract does not already exist, and its name must be added to contractKeys
:
code/contracts/Ingress.sol:L39-L62
function setContractAddress(bytes32 name, address addr) public returns (bool) {
require(name > 0x0000000000000000000000000000000000000000000000000000000000000000, "Contract name must not be empty.");
require(isAuthorized(msg.sender), "Not authorized to update contract registry.");
ContractDetails memory info = registry[name];
// create info if it doesn't exist in the registry
if (info.contractAddress == address(0)) {
info = ContractDetails({
owner: msg.sender,
contractAddress: addr
});
// Update registry indexing
contractKeys.push(name);
} else {
info.contractAddress = addr;
}
// update record in the registry
registry[name] = info;
emit RegistryUpdated(addr,name);
return true;
}
If, however, a contract is actually added with the address 0
, which is currently allowed in the code, then the contract does already exists, and adding the name to contractKeys
again will result in a duplicate.
Mitigation
An admin can call removeContract
repeatedly with the same name to remove multiple duplicate entries.
Recommendation
Either disallow a contract address of 0
or check for existence via the owner
field instead (which can never be 0
).
7.3 Use specific contract types instead of address
where possible Minor ✓ Fixed
Resolution
Description
For clarity and to get more out of the Solidity type checker, it’s generally preferred to use a specific contract type for variables rather than the generic address
.
Examples
AccountRules.ingressContractAddress
could instead be AccountRules.ingressContract
and use the type IngressContract
:
code/contracts/AccountRules.sol:L16
address private ingressContractAddress;
code/contracts/AccountRules.sol:L24
AccountIngress ingressContract = AccountIngress(ingressContractAddress);
code/contracts/AccountRules.sol:L32
constructor (address ingressAddress) public {
This same pattern is found in NodeRules
:
code/contracts/NodeRules.sol:L32
address private nodeIngressContractAddress;
Recommendation
Where possible, use a specific contract type rather than address
.
7.4 Ingress
should use a set Minor ✓ Fixed
Resolution
Description
The AdminList
, AccountRulesList
, and NodeRulesList
contracts have been recently rewritten to use a set. Ingress
has the semantics of a set but has not been written the same way.
This leads to some inefficiencies. In particular, Ingress.removeContract
is an O(n) operation:
code/contracts/Ingress.sol:L68-L74
for (uint i = 0; i < contractKeys.length; i++) {
// Delete the key from the array + mapping if it is present
if (contractKeys[i] == name) {
delete registry[contractKeys[i]];
contractKeys[i] = contractKeys[contractKeys.length - 1];
delete contractKeys[contractKeys.length - 1];
contractKeys.length--;
Recommendation
Use the same set implementation for Ingress
: an array of ContractDetails
and a mapping of names to indexes in that array.
7.5 Use a specific Solidity compiler version Minor ✓ Fixed
Resolution
acf5a22
by pinning to Solidity 0.5.9 everywhere except the Ingress
contract. Because the Ingress
contract is hardcoded into the genesis block, it can’t be easily changed. Non-critical issues like this one won’t be addressed in that contract.
Description
A number of files use a “floating” pragma as follows:
pragma solidity >=0.4.22 <0.6.0;
It’s better to use a specific Solidity compiler version (preferably a current version). This removes any confusion about which compiler was used when the contract is deployed, and it makes sure the code is never subjected to older compiler bugs.
It’s still a good idea to upgrade the compiler version in the future as compiler bugs are fixed, but this way you must explicitly choose the new compiler version in your code when you do so.
Recommendation
Based on the Truffle configuration, the code is currently compiled with Solidity 0.5.9. Consider changing the existing pragma
s to the following:
pragma solidity 0.5.9;
7.6 ContractDetails.owner
is never read Minor ✓ Fixed
Resolution
d3f505e
.
Description
The ContractDetails
struct used by Ingress
contracts has an owner
field that is written to, but it is never read.
code/contracts/Ingress.sol:L14-L19
struct ContractDetails {
address owner;
address contractAddress;
}
mapping(bytes32 => ContractDetails) registry;
Recommendation
If owner
is not (yet) needed, the ContractDetails
struct should be removed altogether and the type of Ingress.registry
should change to mapping(bytes32 => address)
8 Tool-Based Analysis
Several tools were used to perform automated analysis of the reviewed contracts. These issues were reviewed by the audit team, and relevant issues are listed in the Issue Details section.
8.1 MythX
MythX is a security analysis API for Ethereum smart contracts. It performs multiple types of analysis, including fuzzing and symbolic execution, to detect many common vulnerability types. The tool was used for automated vulnerability discovery for all audited contracts and libraries. More details on MythX can be found at mythx.io.
Below is the raw output of the MythX vulnerability scan:
Summary
40 problems (0 errors, 40 warnings)
Warnings
SWC | count | visual |
---|---|---|
SWC-108 | 5 | XXXXX |
SWC-131 | 27 | XXXXXXXXXXXXXXXXXXXX |
SWC-110 | 3 | XXX |
SWC-128 | 3 | XXX |
SWC-123 | 2 | XX |
Details
AccountRules.sol - 7 problems (0 errors, 7 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
12:9 | The state variable visibility is not set. It is best practice to set the visibility of state variables explicitly. The default visibility for "readOnlyMode" is internal. Other possible visibility values are public and private. | SWC-108 |
Warning |
14:9 | The state variable visibility is not set. It is best practice to set the visibility of state variables explicitly. The default visibility for "version" is internal. Other possible visibility values are public and private. | SWC-108 |
Warning |
61:8 | Unused local variable "" The local variable "" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
62:8 | Unused local variable "" The local variable "" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
63:8 | Unused local variable "" The local variable "" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
64:8 | Unused local variable "" The local variable "" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
65:8 | Unused local variable "" The local variable "" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
AccountRulesList.sol - 2 problems (0 errors, 2 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
15:4 | A reachable exception has been detected. It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit assert() should only be used to check invariants. Use require() for regular input checking. |
SWC-110 |
Warning |
36:8 | Potential denial-of-service if block gas limit is reached. A storage modification is executed in a loop. Be aware that the transaction may fail to execute if the loop is unbounded and the necessary gas exceeds the block gas limit. | SWC-128 |
AccountRulesProxy.sol - 12 problems (0 errors, 12 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
5:8 | Unused local variable "sender" The local variable "sender" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
5:8 | Unused local variable "sender" The local variable "sender" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
6:8 | Unused local variable "target" The local variable "target" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
6:8 | Unused local variable "target" The local variable "target" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
7:8 | Unused local variable "value" The local variable "value" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
7:8 | Unused local variable "value" The local variable "value" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
8:8 | Unused local variable "gasPrice" The local variable "gasPrice" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
8:8 | Unused local variable "gasPrice" The local variable "gasPrice" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
9:8 | Unused local variable "gasLimit" The local variable "gasLimit" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
9:8 | Unused local variable "gasLimit" The local variable "gasLimit" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
10:8 | Unused local variable "payload" The local variable "payload" is created within the contract "AccountRules" but does not seem to be used anywhere. | SWC-131 |
Warning |
10:8 | Unused local variable "payload" The local variable "payload" is created within the contract "AccountRulesProxy" but does not seem to be used anywhere. | SWC-131 |
AdminList.sol - 3 problems (0 errors, 3 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
17:4 | A reachable exception has been detected. It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit assert() should only be used to check invariants. Use require() for regular input checking. |
SWC-110 |
Warning |
38:8 | Potential denial-of-service if block gas limit is reached. A storage modification is executed in a loop. Be aware that the transaction may fail to execute if the loop is unbounded and the necessary gas exceeds the block gas limit. | SWC-128 |
Warning |
42:23 | Potential denial-of-service if block gas limit is reached. A storage modification is executed in a loop. Be aware that the transaction may fail to execute if the loop is unbounded and the necessary gas exceeds the block gas limit. | SWC-128 |
AdminProxy.sol - 3 problems (0 errors, 3 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
4:10 | precondition violation A precondition was violated. Make sure valid inputs are provided to both callees (e.g, via passed arguments) and callers (e.g., via return values). | SWC-123 |
Warning |
4:26 | Unused local variable "source" The local variable "source" is created within the contract "Admin" but does not seem to be used anywhere. | SWC-131 |
Warning |
4:26 | Unused local variable "source" The local variable "source" is created within the contract "AdminProxy" but does not seem to be used anywhere. | SWC-131 |
Ingress.sol - 3 problems (0 errors, 3 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
12:14 | The state variable visibility is not set. It is best practice to set the visibility of state variables explicitly. The default visibility for "contractKeys" is internal. Other possible visibility values are public and private. | SWC-108 |
Warning |
19:40 | The state variable visibility is not set. It is best practice to set the visibility of state variables explicitly. The default visibility for "registry" is internal. Other possible visibility values are public and private. | SWC-108 |
Warning |
35:19 | precondition violation A precondition was violated. Make sure valid inputs are provided to both callees (e.g, via passed arguments) and callers (e.g., via return values). | SWC-123 |
NodeRulesList.sol - 1 problem (0 errors, 1 warning)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
15:4 | assertion violation An assertion was violated. Make sure your program logic is correct (e.g., no division by zero) and that you add appropriate validation for inputs from both callers (e.g, passed arguments) and callees (e.g., return values). | SWC-110 |
NodeIngress.sol - 1 problem (0 errors, 1 warning)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
9:9 | The state variable visibility is not set. It is best practice to set the visibility of state variables explicitly. The default visibility for "version" is internal. Other possible visibility values are public and private. | SWC-108 |
NodeRulesProxy.sol - 8 problems (0 errors, 8 warnings)
Type | Line | Description | SWC |
---|---|---|---|
Warning |
5:8 | Unused local variable "sourceEnodeHigh" The local variable "sourceEnodeHigh" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
6:8 | Unused local variable "sourceEnodeLow" The local variable "sourceEnodeLow" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
7:8 | Unused local variable "sourceEnodeIp" The local variable "sourceEnodeIp" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
8:8 | Unused local variable "sourceEnodePort" The local variable "sourceEnodePort" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
9:8 | Unused local variable "destinationEnodeHigh" The local variable "destinationEnodeHigh" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
10:8 | Unused local variable "destinationEnodeLow" The local variable "destinationEnodeLow" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
11:8 | Unused local variable "destinationEnodeIp" The local variable "destinationEnodeIp" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
Warning |
12:8 | Unused local variable "destinationEnodePort" The local variable "destinationEnodePort" is created within the contract "NodeRulesProxy" but does not seem to be used anywhere. | SWC-131 |
AccountIngress.sol - 0 problems
Admin.sol - 0 problems
ExposedAccountRulesList.sol - 0 problems
ExposedAdminList.sol - 0 problems
ExposedNodeRulesList.sol - 0 problems
Generated on Thu Aug 29 2019 15:16:37 GMT-0700 (Pacific Daylight Time)
MythX Logs:
AccountRules.sol
UUID: 6db36465-5d19-43b8-8318-20d038616ffb
info: skipped automated fuzz testing due to incompatible bytecode input
AccountRulesList.sol
UUID: 17faa2da-60ed-4e9c-8f76-c9d87ebfa025
AccountRulesProxy.sol
UUID: 0579eb33-82ef-4ac7-99e1-948ba46955df
Admin.sol
UUID: da4012ea-98e3-4116-9ee9-896da7904e7c
AdminList.sol
UUID: 6a5da947-d87d-4f3a-b3e6-94d76712aa73
AdminProxy.sol
UUID: ef18baac-d986-4bcd-aefc-1d0801e214d2
ExposedAccountRulesList.sol
UUID: 706738e2-35a4-4def-b7c4-f680920db1a1
ExposedAdminList.sol
UUID: ea78f05f-c0f2-46e0-84eb-0168d35fccc4
ExposedNodeRulesList.sol
UUID: 33d4d1a4-2f85-4d6d-99c7-dd76c738d305
Ingress.sol
UUID: 162745bf-308e-4cc8-a07b-b5e1564f7764
NodeIngress.sol
UUID: a40eebe4-d51e-40fd-8b0b-913491e63411
NodeRulesList.sol
UUID: c5d7bd11-591d-4bd6-8364-883d8db35bb9
NodeRulesProxy.sol
UUID: 851c3349-b9f2-459c-a3ec-5bbd7cb6d616
8.2 Ethlint
Ethlint is an open source project for linting Solidity code. Only security-related issues were reviewed by the audit team.
Ethlint didn’t find any issues.
8.3 Surya
Surya is an utility tool for smart contract systems. It provides a number of visual outputs and information about structure of smart contracts. It also supports querying the function call graph in multiple ways to aid in the manual inspection and control flow analysis of contracts.
Below is a complete list of functions with their visibility and modifiers:
Files Description Table
File Name | SHA-1 Hash |
---|---|
AccountIngress.sol | 57207a6878535bc2f3d40216d96f07eef9bbdfd9 |
AccountRulesList.sol | 73ffd92be5b6c3b1e18d1b860344dac578c9aa31 |
Admin.sol | e13931323093f1555f4dfcc74fad6a2c457c1082 |
AdminProxy.sol | eecd073b4e05a4445fb00888074b48c443c5bbf4 |
Ingress.sol | b0fcff06fa7d55136cfe483331280e4e9bb9def4 |
NodeIngress.sol | 3f46f78e4c1b9a546287135a13ffa303f62a826b |
NodeRulesList.sol | fa9382c4cf3f4d800aa3d0e89bb9a712d5aa5f0c |
AccountRules.sol | c730212300e070ed22b1490f6e67347d1f36c051 |
AccountRulesProxy.sol | 1024d00149ee0258f5ee4c0671a09ada723c3645 |
AdminList.sol | 0304e06bfc4c87abc4d2f4c0361633590c5ef830 |
NodeRules.sol | 8f0dc9efd5bc09a8c6346495e23a398c907baf21 |
NodeRulesProxy.sol | 01967d8481a3f1497ecdfcfcd5e7dd2ea9f9c17e |
Contracts Description Table
Contract | Type | Bases | ||
---|---|---|---|---|
└ | Function Name | Visibility | Mutability | Modifiers |
AccountIngress | Implementation | Ingress | ||
└ | getContractVersion | Public ❗️ | NO❗️ | |
└ | emitRulesChangeEvent | Public ❗️ | 🛑 | NO❗️ |
└ | transactionAllowed | Public ❗️ | NO❗️ | |
AccountRulesList | Implementation | |||
└ | size | Internal 🔒 | ||
└ | exists | Internal 🔒 | ||
└ | add | Internal 🔒 | 🛑 | |
└ | addAll | Internal 🔒 | 🛑 | |
└ | remove | Internal 🔒 | 🛑 | |
Admin | Implementation | AdminProxy, AdminList | ||
└ | <Constructor> | Public ❗️ | 🛑 | |
└ | isAuthorized | Public ❗️ | NO❗️ | |
└ | addAdmin | Public ❗️ | 🛑 | onlyAdmin |
└ | removeAdmin | Public ❗️ | 🛑 | onlyAdmin notSelf |
└ | getAdmins | Public ❗️ | NO❗️ | |
└ | addAdmins | Public ❗️ | 🛑 | onlyAdmin |
AdminProxy | Interface | |||
└ | isAuthorized | External ❗️ | NO❗️ | |
Ingress | Implementation | |||
└ | getContractAddress | Public ❗️ | NO❗️ | |
└ | isAuthorized | Public ❗️ | NO❗️ | |
└ | setContractAddress | Public ❗️ | 🛑 | NO❗️ |
└ | removeContract | Public ❗️ | 🛑 | NO❗️ |
└ | getAllContractKeys | Public ❗️ | NO❗️ | |
NodeIngress | Implementation | Ingress | ||
└ | getContractVersion | Public ❗️ | NO❗️ | |
└ | emitRulesChangeEvent | Public ❗️ | 🛑 | NO❗️ |
└ | connectionAllowed | Public ❗️ | NO❗️ | |
NodeRulesList | Implementation | |||
└ | calculateKey | Internal 🔒 | ||
└ | size | Internal 🔒 | ||
└ | exists | Internal 🔒 | ||
└ | add | Internal 🔒 | 🛑 | |
└ | remove | Internal 🔒 | 🛑 | |
AccountRules | Implementation | AccountRulesProxy, AccountRulesList | ||
└ | <Constructor> | Public ❗️ | 🛑 | |
└ | getContractVersion | Public ❗️ | NO❗️ | |
└ | isReadOnly | Public ❗️ | NO❗️ | |
└ | enterReadOnly | Public ❗️ | 🛑 | onlyAdmin |
└ | exitReadOnly | Public ❗️ | 🛑 | onlyAdmin |
└ | transactionAllowed | Public ❗️ | NO❗️ | |
└ | accountInWhitelist | Public ❗️ | NO❗️ | |
└ | addAccount | Public ❗️ | 🛑 | onlyAdmin onlyOnEditMode |
└ | removeAccount | Public ❗️ | 🛑 | onlyAdmin onlyOnEditMode |
└ | getSize | Public ❗️ | NO❗️ | |
└ | getByIndex | Public ❗️ | NO❗️ | |
└ | getAccounts | Public ❗️ | NO❗️ | |
└ | addAccounts | Public ❗️ | 🛑 | onlyAdmin |
AccountRulesProxy | Interface | |||
└ | transactionAllowed | External ❗️ | NO❗️ | |
AdminList | Implementation | |||
└ | size | Internal 🔒 | ||
└ | exists | Internal 🔒 | ||
└ | add | Internal 🔒 | 🛑 | |
└ | addAll | Internal 🔒 | 🛑 | |
└ | remove | Internal 🔒 | 🛑 | |
NodeRules | Implementation | NodeRulesProxy, NodeRulesList | ||
└ | <Constructor> | Public ❗️ | 🛑 | |
└ | getContractVersion | Public ❗️ | NO❗️ | |
└ | isReadOnly | Public ❗️ | NO❗️ | |
└ | enterReadOnly | Public ❗️ | 🛑 | onlyAdmin |
└ | exitReadOnly | Public ❗️ | 🛑 | onlyAdmin |
└ | connectionAllowed | Public ❗️ | NO❗️ | |
└ | enodeInWhitelist | Public ❗️ | NO❗️ | |
└ | addEnode | Public ❗️ | 🛑 | onlyAdmin onlyOnEditMode |
└ | removeEnode | Public ❗️ | 🛑 | onlyAdmin onlyOnEditMode |
└ | getSize | Public ❗️ | NO❗️ | |
└ | getByIndex | Public ❗️ | NO❗️ | |
└ | triggerRulesChangeEvent | Public ❗️ | 🛑 | NO❗️ |
NodeRulesProxy | Interface | |||
└ | connectionAllowed | External ❗️ | NO❗️ |
Legend
Symbol | Meaning |
---|---|
🛑 | Function can modify state |
💵 | Function is payable |
8.4 Slither
Slither is a Solidity static analysis framework written in Python 3. It runs a suite of vulnerability detectors.
Below is the raw output of the Slither scan:
INFO:Detectors:
Pragma version ">=0.4.22<0.6.0" allows old versions (ExposedAdminList.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AccountRules.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AccountRulesList.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (Ingress.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (NodeRules.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AdminProxy.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (NodeRulesProxy.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (ExposedNodeRulesList.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AdminList.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (ExposedAccountRulesList.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (Admin.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (Migrations.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (NodeIngress.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AccountRulesProxy.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (AccountIngress.sol#1)
Pragma version ">=0.4.22<0.6.0" allows old versions (NodeRulesList.sol#1)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#incorrect-versions-of-solidity
INFO:Detectors:
Function 'ExposedAdminList._size()' (ExposedAdminList.sol#9-11) is not in mixedCase
Function 'ExposedAdminList._exists(address)' (ExposedAdminList.sol#13-15) is not in mixedCase
Parameter '_address' of _address (ExposedAdminList.sol#13) is not in mixedCase
Function 'ExposedAdminList._add(address)' (ExposedAdminList.sol#17-19) is not in mixedCase
Parameter '_address' of _address (ExposedAdminList.sol#17) is not in mixedCase
Function 'ExposedAdminList._remove(address)' (ExposedAdminList.sol#21-23) is not in mixedCase
Parameter '_address' of _address (ExposedAdminList.sol#21) is not in mixedCase
Function 'ExposedAdminList._addBatch(address[])' (ExposedAdminList.sol#25-27) is not in mixedCase
Parameter '_addresses' of _addresses (ExposedAdminList.sol#25) is not in mixedCase
Parameter '_account' of _account (AccountRules.sol#77) is not in mixedCase
Parameter '_account' of _account (AccountRulesList.sol#22) is not in mixedCase
Parameter '_account' of _account (AccountRulesList.sol#26) is not in mixedCase
Parameter '_account' of _account (AccountRulesList.sol#45) is not in mixedCase
Variable 'Ingress.RULES_CONTRACT' (Ingress.sol#8) is not in mixedCase
Variable 'Ingress.ADMIN_CONTRACT' (Ingress.sol#9) is not in mixedCase
Function 'ExposedNodeRulesList._calculateKey(bytes32,bytes32,bytes16,uint16)' (ExposedNodeRulesList.sol#8-10) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (ExposedNodeRulesList.sol#8) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (ExposedNodeRulesList.sol#8) is not in mixedCase
Parameter '_ip' of _ip (ExposedNodeRulesList.sol#8) is not in mixedCase
Parameter '_port' of _port (ExposedNodeRulesList.sol#8) is not in mixedCase
Function 'ExposedNodeRulesList._size()' (ExposedNodeRulesList.sol#12-14) is not in mixedCase
Function 'ExposedNodeRulesList._exists(bytes32,bytes32,bytes16,uint16)' (ExposedNodeRulesList.sol#16-18) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (ExposedNodeRulesList.sol#16) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (ExposedNodeRulesList.sol#16) is not in mixedCase
Parameter '_ip' of _ip (ExposedNodeRulesList.sol#16) is not in mixedCase
Parameter '_port' of _port (ExposedNodeRulesList.sol#16) is not in mixedCase
Function 'ExposedNodeRulesList._add(bytes32,bytes32,bytes16,uint16)' (ExposedNodeRulesList.sol#20-22) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (ExposedNodeRulesList.sol#20) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (ExposedNodeRulesList.sol#20) is not in mixedCase
Parameter '_ip' of _ip (ExposedNodeRulesList.sol#20) is not in mixedCase
Parameter '_port' of _port (ExposedNodeRulesList.sol#20) is not in mixedCase
Function 'ExposedNodeRulesList._remove(bytes32,bytes32,bytes16,uint16)' (ExposedNodeRulesList.sol#24-26) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (ExposedNodeRulesList.sol#24) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (ExposedNodeRulesList.sol#24) is not in mixedCase
Parameter '_ip' of _ip (ExposedNodeRulesList.sol#24) is not in mixedCase
Parameter '_port' of _port (ExposedNodeRulesList.sol#24) is not in mixedCase
Parameter '_account' of _account (AdminList.sol#24) is not in mixedCase
Parameter '_account' of _account (AdminList.sol#28) is not in mixedCase
Parameter '_account' of _account (AdminList.sol#56) is not in mixedCase
Function 'ExposedAccountRulesList._size()' (ExposedAccountRulesList.sol#8-10) is not in mixedCase
Function 'ExposedAccountRulesList._exists(address)' (ExposedAccountRulesList.sol#12-14) is not in mixedCase
Parameter '_account' of _account (ExposedAccountRulesList.sol#12) is not in mixedCase
Function 'ExposedAccountRulesList._add(address)' (ExposedAccountRulesList.sol#16-18) is not in mixedCase
Parameter '_account' of _account (ExposedAccountRulesList.sol#16) is not in mixedCase
Function 'ExposedAccountRulesList._addAll(address[])' (ExposedAccountRulesList.sol#20-22) is not in mixedCase
Function 'ExposedAccountRulesList._remove(address)' (ExposedAccountRulesList.sol#24-26) is not in mixedCase
Parameter '_account' of _account (ExposedAccountRulesList.sol#24) is not in mixedCase
Parameter '_address' of _address (Admin.sol#22) is not in mixedCase
Parameter '_address' of _address (Admin.sol#26) is not in mixedCase
Parameter '_address' of _address (Admin.sol#38) is not in mixedCase
Parameter 'new_address' of new_address (Migrations.sol#20) is not in mixedCase
Variable 'Migrations.last_completed_migration' (Migrations.sol#6) is not in mixedCase
Struct 'NodeRulesList.enode' (NodeRulesList.sol#8-13) is not in CapWords
Parameter '_enodeHigh' of _enodeHigh (NodeRulesList.sol#18) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (NodeRulesList.sol#18) is not in mixedCase
Parameter '_ip' of _ip (NodeRulesList.sol#18) is not in mixedCase
Parameter '_port' of _port (NodeRulesList.sol#18) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (NodeRulesList.sol#26) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (NodeRulesList.sol#26) is not in mixedCase
Parameter '_ip' of _ip (NodeRulesList.sol#26) is not in mixedCase
Parameter '_port' of _port (NodeRulesList.sol#26) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (NodeRulesList.sol#30) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (NodeRulesList.sol#30) is not in mixedCase
Parameter '_ip' of _ip (NodeRulesList.sol#30) is not in mixedCase
Parameter '_port' of _port (NodeRulesList.sol#30) is not in mixedCase
Parameter '_enodeHigh' of _enodeHigh (NodeRulesList.sol#39) is not in mixedCase
Parameter '_enodeLow' of _enodeLow (NodeRulesList.sol#39) is not in mixedCase
Parameter '_ip' of _ip (NodeRulesList.sol#39) is not in mixedCase
Parameter '_port' of _port (NodeRulesList.sol#39) is not in mixedCase
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#conformance-to-solidity-naming-conventions
INFO:Detectors:
AccountRules.slitherConstructorVariables (AccountRules.sol#9-113) uses literals with too many digits:
- version = 1000000
NodeRules.slitherConstructorVariables (NodeRules.sol#9-170) uses literals with too many digits:
- version = 1000000
NodeIngress.getContractAddress (Ingress.sol#26-29) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
NodeIngress.setContractAddress (Ingress.sol#39-62) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
NodeIngress.removeContract (Ingress.sol#64-81) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
NodeIngress.slitherConstructorVariables (NodeIngress.sol#7-49) uses literals with too many digits:
- RULES_CONTRACT = 0x72756c6573000000000000000000000000000000000000000000000000000000
NodeIngress.slitherConstructorVariables (NodeIngress.sol#7-49) uses literals with too many digits:
- ADMIN_CONTRACT = 0x61646d696e697374726174696f6e000000000000000000000000000000000000
NodeIngress.slitherConstructorVariables (NodeIngress.sol#7-49) uses literals with too many digits:
- version = 1000000
AccountIngress.getContractAddress (Ingress.sol#26-29) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
AccountIngress.setContractAddress (Ingress.sol#39-62) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
AccountIngress.removeContract (Ingress.sol#64-81) uses literals with too many digits:
- require(bool,string)(name > 0x0000000000000000000000000000000000000000000000000000000000000000,Contract name must not be empty.)
AccountIngress.slitherConstructorVariables (AccountIngress.sol#7-40) uses literals with too many digits:
- RULES_CONTRACT = 0x72756c6573000000000000000000000000000000000000000000000000000000
AccountIngress.slitherConstructorVariables (AccountIngress.sol#7-40) uses literals with too many digits:
- ADMIN_CONTRACT = 0x61646d696e697374726174696f6e000000000000000000000000000000000000
AccountIngress.slitherConstructorVariables (AccountIngress.sol#7-40) uses literals with too many digits:
- version = 1000000
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#too-many-digits
INFO:Detectors:
AccountIngress.version should be constant (AccountIngress.sol#9)
AccountRules.version should be constant (AccountRules.sol#14)
Ingress.ADMIN_CONTRACT should be constant (Ingress.sol#9)
Ingress.RULES_CONTRACT should be constant (Ingress.sol#8)
NodeIngress.version should be constant (NodeIngress.sol#9)
NodeRules.version should be constant (NodeRules.sol#30)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-constant
INFO:Detectors:
ExposedAdminList._size() (ExposedAdminList.sol#9-11) should be declared external
ExposedAdminList._exists(address) (ExposedAdminList.sol#13-15) should be declared external
ExposedAdminList._add(address) (ExposedAdminList.sol#17-19) should be declared external
ExposedAdminList._remove(address) (ExposedAdminList.sol#21-23) should be declared external
ExposedAdminList._addBatch(address[]) (ExposedAdminList.sol#25-27) should be declared external
AccountRules.getContractVersion() (AccountRules.sol#38-40) should be declared external
AccountRules.isReadOnly() (AccountRules.sol#43-45) should be declared external
AccountRules.enterReadOnly() (AccountRules.sol#47-51) should be declared external
AccountRules.exitReadOnly() (AccountRules.sol#53-57) should be declared external
AccountRules.transactionAllowed(address,address,uint256,uint256,uint256,bytes) (AccountRules.sol#59-74) should be declared external
AccountRulesProxy.transactionAllowed(address,address,uint256,uint256,uint256,bytes) (AccountRulesProxy.sol#4-11) should be declared external
AccountRules.addAccount(address) (AccountRules.sol#82-88) should be declared external
AccountRules.removeAccount(address) (AccountRules.sol#90-96) should be declared external
AccountRules.getSize() (AccountRules.sol#98-100) should be declared external
AccountRules.getByIndex(uint256) (AccountRules.sol#102-104) should be declared external
AccountRules.getAccounts() (AccountRules.sol#106-108) should be declared external
AccountRules.addAccounts(address[]) (AccountRules.sol#110-112) should be declared external
Ingress.setContractAddress(bytes32,address) (Ingress.sol#39-62) should be declared external
Ingress.removeContract(bytes32) (Ingress.sol#64-81) should be declared external
Ingress.getAllContractKeys() (Ingress.sol#83-85) should be declared external
NodeRules.getContractVersion() (NodeRules.sol#53-55) should be declared external
NodeRules.isReadOnly() (NodeRules.sol#58-60) should be declared external
NodeRules.enterReadOnly() (NodeRules.sol#62-66) should be declared external
NodeRules.exitReadOnly() (NodeRules.sol#68-72) should be declared external
NodeRulesProxy.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16) (NodeRulesProxy.sol#4-13) should be declared external
NodeRules.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16) (NodeRules.sol#74-101) should be declared external
NodeRules.addEnode(bytes32,bytes32,bytes16,uint16) (NodeRules.sol#112-132) should be declared external
NodeRules.removeEnode(bytes32,bytes32,bytes16,uint16) (NodeRules.sol#134-154) should be declared external
NodeRules.getSize() (NodeRules.sol#156-158) should be declared external
NodeRules.getByIndex(uint256) (NodeRules.sol#160-165) should be declared external
ExposedNodeRulesList._calculateKey(bytes32,bytes32,bytes16,uint16) (ExposedNodeRulesList.sol#8-10) should be declared external
ExposedNodeRulesList._size() (ExposedNodeRulesList.sol#12-14) should be declared external
ExposedNodeRulesList._exists(bytes32,bytes32,bytes16,uint16) (ExposedNodeRulesList.sol#16-18) should be declared external
ExposedNodeRulesList._add(bytes32,bytes32,bytes16,uint16) (ExposedNodeRulesList.sol#20-22) should be declared external
ExposedNodeRulesList._remove(bytes32,bytes32,bytes16,uint16) (ExposedNodeRulesList.sol#24-26) should be declared external
ExposedAccountRulesList._size() (ExposedAccountRulesList.sol#8-10) should be declared external
ExposedAccountRulesList._exists(address) (ExposedAccountRulesList.sol#12-14) should be declared external
ExposedAccountRulesList._add(address) (ExposedAccountRulesList.sol#16-18) should be declared external
ExposedAccountRulesList._addAll(address[]) (ExposedAccountRulesList.sol#20-22) should be declared external
ExposedAccountRulesList._remove(address) (ExposedAccountRulesList.sol#24-26) should be declared external
Admin.addAdmin(address) (Admin.sol#26-36) should be declared external
Admin.removeAdmin(address) (Admin.sol#38-42) should be declared external
Admin.getAdmins() (Admin.sol#44-46) should be declared external
Admin.addAdmins(address[]) (Admin.sol#48-50) should be declared external
Migrations.setCompleted(uint256) (Migrations.sol#16-18) should be declared external
Migrations.upgrade(address) (Migrations.sol#20-23) should be declared external
NodeIngress.getContractVersion() (NodeIngress.sol#15-17) should be declared external
NodeIngress.emitRulesChangeEvent(bool) (NodeIngress.sol#19-22) should be declared external
NodeIngress.connectionAllowed(bytes32,bytes32,bytes16,uint16,bytes32,bytes32,bytes16,uint16) (NodeIngress.sol#24-48) should be declared external
AccountIngress.getContractVersion() (AccountIngress.sol#15-17) should be declared external
AccountIngress.emitRulesChangeEvent(bool) (AccountIngress.sol#19-22) should be declared external
AccountIngress.transactionAllowed(address,address,uint256,uint256,uint256,bytes) (AccountIngress.sol#24-39) should be declared external
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#public-function-that-could-be-declared-as-external
INFO:Slither:. analyzed (16 contracts), 157 result(s) found
Appendix 1 - Disclosure
ConsenSys Diligence (“CD”) typically receives compensation from one or more clients (the “Clients”) for performing the analysis contained in these reports (the “Reports”). The Reports may be distributed through other means, including via ConsenSys publications and other distributions.
The Reports are not an endorsement or indictment of any particular project or team, and the Reports do not guarantee the security of any particular project. This Report does not consider, and should not be interpreted as considering or having any bearing on, the potential economics of a token, token sale or any other product, service or other asset. Cryptographic tokens are emergent technologies and carry with them high levels of technical risk and uncertainty. No Report provides any warranty or representation to any Third-Party in any respect, including regarding the bugfree nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third party should rely on the Reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this Report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project. CD owes no duty to any Third-Party by virtue of publishing these Reports.
PURPOSE OF REPORTS The Reports and the analysis described therein are created solely for Clients and published with their consent. The scope of our review is limited to a review of Solidity code and only the Solidity code we note as being within the scope of our review within this report. The Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond Solidity that could present security risks. Cryptographic tokens are emergent technologies and carry with them high levels of technical risk and uncertainty.
CD makes the Reports available to parties other than the Clients (i.e., “third parties”) – on its website. CD hopes that by making these analyses publicly available, it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.
LINKS TO OTHER WEB SITES FROM THIS WEB SITE You may, through hypertext or other computer links, gain access to web sites operated by persons other than ConsenSys and CD. Such hyperlinks are provided for your reference and convenience only, and are the exclusive responsibility of such web sites’ owners. You agree that ConsenSys and CD are not responsible for the content or operation of such Web sites, and that ConsenSys and CD shall have no liability to you or any other person or entity for the use of third party Web sites. Except as described below, a hyperlink from this web Site to another web site does not imply or mean that ConsenSys and CD endorses the content on that Web site or the operator or operations of that site. You are solely responsible for determining the extent to which you may use any content at any other web sites to which you link from the Reports. ConsenSys and CD assumes no responsibility for the use of third party software on the Web Site and shall have no liability whatsoever to any person or entity for the accuracy or completeness of any outcome generated by such software.
TIMELINESS OF CONTENT The content contained in the Reports is current as of the date appearing on the Report and is subject to change without notice. Unless indicated otherwise, by ConsenSys and CD.