This report presents our engineering engagement with YuzuSwap, one of the first DEX projects for the Emerald paratime on the Oasis Network. YuzuSwap is an AMM DEX with innovative trading incentive designs, such as the trading pool share token (TPST). YuzuSwap’s TPST design keeps track of DEX users’ swap operations and provides rewards for these users.
YuzuSwap is a decentralized exchange on the Oasis Emerald paratime that includes incentives such as liquidity mining and trade mining. YuzuSwap follows a non-custodial, peer-to-peer, automated-market-maker model and aims to provide a safe, swift, and low-cost tool to discover and swap tokens within the Oasis ecosystem. The YuzuSwap platform itself is fully open to developers and members of the Yuzu DAO.
Our auditing service for YuzuSwap includes the following two stages:
Pre-Audit Consulting Service
Audit Service
Pre-Audit Consulting Service
As a part of the pre-audit service, the Verilog team worked closely with the YuzuSwap development to discuss potential vulnerability and smart contract development best practices in a timely fashion. Verilog team is very appreciative of establishing an efficient and effective communication channel with the YuzuSwap team, as new findings are often exchanged promptly and fixes were deployed quickly, during the preliminary report stage.
Audit Service
The Verilog team conducted a thorough study of the YuzuSwap code, with the YuzuSwap architecture graph and UML graph presented below in the YuzuSwap Architecture section. The list of findings, along with the severity and solution, is available under section Findings & Improvement Suggestions.
YuzuSwap Architecture
Yuzu Swap Architecture
These are the major smart contracts in YuzuSwap:
YuzuToken.sol
YuzuKeeper.sol
YuzuPark.sol
YuzuParkExt.sol
YuzuRouter.sol
YuzuSwapMining.sol
YuzuZap.sol
YuzuKeeper.sol YuzuKeeper has the privilege to mint yuzu tokens to the registered applications and dev address.
YuzuToken.sol YuzuToken is a standard ERC20 token contract, that can be minted by owner.
YuzuPark.sol YuzuPark is the contract where it distributes yuzu tokens half-attenuationally as rewards for staking eligible tokens.
YuzuParkExt.sol YuzuParkExt is a extenstion for YuzuPark. Multiple tokens can be set as reward tokens besides the yuzu token.
YuzuRouter.sol It’s where users can swap tokens and accumulate yuzu rewards for eligible pairs.
YuzuSwapMining.sol It’s where users can withdraw their accumulated yuzu rewards when user use YuzuRouter to swap tokens of eligible pair.
YuzuZap.sol In YuzuZap, users can get lp tokens by supplying a single token. Users can also swap back to a single token with the lp token.
YUZUTokenBlackHole.sol @ address 0x00b9dCA177aa3DB6F344A455d9E0511a6Aa7ad8D Its a blank contract deployed by YuzuSwap team acts like a blackhole( address(0) ) to burn all buy backed $YUZU token.
Privileged Roles
There is one main privileged role owner. It can:
Mint yuzu tokens in YuzuToken.sol
Add and publish applications in YuzuKeeper.sol
Add, set pools, set reward rate and set swap mining at YuzuPark.sol, YuzuParkExt.sol, YuzuSwapMining.sol, YuzuRouter.sol, StandardReward.sol.
Findings & Improvement Suggestions
InformationalMinorMediumMajorCritical
Total
Acknowledged
Resolved
Critical
3
3
3
Major
0
0
0
Medium
2
1
1
Minor
9
7
5
Informational
7
3
3
Critical
Router address should be a variable set by owner (YuzuZap.sol: L48, L93, L98, L112, L144, 165, L171).Critical Description: Router address is being passed in as argument and token allowance for router is set to maximum. Attackers can deploy a set of swap and router contracts with the same interface to drain contracts’ funds. Recommendation: Router address should be a variable set by owner to prevent exploits. Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
<address>.call() should be used instead of <address>.transfer() to transfer native tokens (YuzuZap.sol:L448). Critical Description: <address>.call() should be used instead of <address>.transfer to transfer native tokens. Recommendation: Use uniswap’s TransferHelper.safeTransferETH() to transfer native token. Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Reset amount of rewarder contract at emergencyWithdraw(YuzuParkExt.sol: L313). Critical Description: User amounts of rewarder contracts are not reset to zero. Recommendation: Reset User amounts of rewarder contracts to zero.
for (uint256 i = 0;i < _rewarders.length ; i ++ ) {
IRewarder _rewarder = _rewarders[i];
if(address(_rewarder) != address(0)) {
_rewarder.onYUZUReward(_pid,msg.sender, 0,0);
}
}
Add nonRentrant modifier for external functions:zapInToken(), zapIn(), zapAcross(), zapOut(), zapOutToken(), swapToken(), swapToNative() (YuzuZap.sol:L48, L93, L98, L112, L144, 165, L171). Medium Description: No nonReentrant modifier for those functions. Recommendation: Add nonReentrant modifier. Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Approve actual amount instead of maximum amount (YuzuZap.sol:L180). Medium Description: Maximum amount is used for approval here. Recommendation: Modify the functions to approve actual amount instead of maximum amount. Result: This suggestion is not adopted.
Minor
Require only receive native tokens from router address (YuzuZap.sol:L46). Minor Description: Anyone can send native tokens to the contract Recommendation: Require only router can send native tokens to current contract. Result: This suggestion is not adopted.
Add check for pool Id to make sure the pool does not exist at addPool() and add() (StandardReward.sol:L70, YuzuPark.sol:L96). Minor Description: Pool might already exist. Recommendation: For example, add the following requirement to check if pool id is valid.
Add check for pool Id to make sure pool exist at updatePool() and setPool() (YuzuParkExt.sol:L219, YuzuPark.sol:L167, StandardReward.sol:L89, L99). Minor Description: Pool might not exist. Recommendation: For example, add the following requirement to check if pool already added.
require(poolInfo[_pid].lastRewardBlock != 0, "Pool not exists");
// orrequire(_pid < poolInfo.length, "Pool not exists");
Result: Not Resolved.
Some varibales can be immutable. (YuzuZap.sol:L35, HalfAttenuationYuzuReward.sol:L13-L17). Minor Description: WNATIVE at YuzuZap and startBlock, blockNumberOfHalfAttenuationCycle and yuzuPerBlock at HalfAttenuationYuzuReward can be immutable. Recommendation: add immutable keyword to WNATIVE. Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
The visibility of functiongetYuzuFromStartblock() can be pure (L41). Minor Description: Function visibility can be restricted to pure. Recommendation: Change function visibility to pure. Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
Add Solidity pragma version. Minor Description: There is no soldity version been added to the YuzuSwapMining.sol. Recommendation: Add pragma solidity 0.6.12; as other smart contracts. Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Multiply before dividing (YuzuKeeper: L117). Minor
Seperate interface. Informational Description: Currently, interfaces is inside the same file with contract. Recommendation: Seperate interface. Result: This suggestion is not adopted.
Call massUpdatePools() directly at functions add and set (YuzuParkExt.sol:L130, L157, YuzuPark.sol:L102, L126). Informational Description: The _withUpdate is always true. massUpdatePools() can be called directly. Recommendation: Remove ifelse check for _withUpdate. massUpdatePools() can be called directly. Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Modifies the logic of function duplicatedTokenDetect(). (YuzuPark.sol:L254, YuzuParkExt.sol:L345). Informational Description: the check for dulipcate tokens detection can be optimized. Recommendation: For example, use a mapping to track added tokens. Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
Input Multicheck and Limitation (YuzuKeeper: L62). Informational
Description: As one of the most important functions, input _totalValue should be limited into a certain range (less than 10% of the total token supply), input _perBlockLimit should be limited into a certain range, input _startBlock should be limited after certain date. Recommendation: Add requirement for each of the input.
// suggested changes, limitation should be determined by the project teamfunctionaddApplication(address _yuzuMember , uint256 _totalValue, uint256 _perBlockLimit,uint256 _startBlock ) publiconlyOwnerappNotPublished{
require(_yuzuMember != address(0), "YUZUKEEPER: ZERO ADDRESS");
require(_totalValue <= yuzu.totalSupply().div(10), "YUZUKEEPER: NO MORE THAN 10% OF TOTAL SUPPLY");
require(_perBlockLimit <= 1e18, "YUZUKEEPER: PER BLOCK LIMITATION");
require(_startBlock >= block.timestamp, "YUZUKEEPER: START AFTER CERTAIN TIME");
......
}
Result: This suggestion is not adopted. We suggest that the owner of the smart contract must be very careful when calling this function.
Logic Improvement for Function RequestForYUZU() (YuzuKeeper: L79). Informational
Description: When 1 $YUZU is mint, 0.1 for investor, 0.1 for foundation, 0.1 for dev. The current logic is to send the above 0.3 $YUZU first before sending the leftAmount to the user. This design is a bit unfair for the unlucky users who mint the last bit of Yuzu. Recommendation: step 1: check how many $YUZU is left. step 2: adjust the mint amount to the leftover amount of $YUZU if the mint amount exceeds the leftover amount. step 3: mint based on the distribution. *external changes required: YuzuToken.sol needs to add a circulatingSupply() external view function to feed YuzuKeeper how many tokens have been mint out. Result: This suggestion is not adopted.
Add public view functions for poolInfo.length at StandardReward.sol.Informational Description: A view function can be added to check the poolInfo.length for the convenience of adding pools in the future. Recommendation: Add a public view function for poolInfo.length Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Unused variable _pendingYUZU at onYUZUReward() and pendingToken() (StandardReward.sol:L145, L168). Informational Description: Unused variable _pendingYUZU. Recommendation: Change the code to followings to remove compiler warnings for unused variables.
// onYUZURewardfunctiononYUZUReward(uint256 pid,
address _user,
uint256 lpToken,
uint256// using just uint256 without variable name will remove the warning) { ... }
// similarly for pendingTokenfunctionpendingToken(uint256 _pid, address _user, uint256)
{ ... }
Result: This suggestion is not adopted.
Disclaimer
Verilog receives compensation from one or more clients for performing the smart contract and auditing analysis contained in these reports. The report created is solely for Clients and published with their consent. As such, the scope of our audit is limited to a review of code, and only the code we note as being within the scope of our audit detailed in this report. It is important to note that the Solidity code itself presents unique and unquantifiable risks since the Solidity language itself remains under current development and is subject to unknown risks and flaws. Our sole goal is to help reduce the attack vectors and the high level of variance associated with utilizing new and consistently changing technologies. Thus, Verilog in no way claims any guarantee of security or functionality of the technology we agree to analyze.
In addition, Verilog reports do not provide any indication of the technologies proprietors, business, business model, or legal compliance. As such, reports do not provide investment advice and should not be used to make decisions about investment or involvement with any particular project. Verilog has the right to distribute the Report through other means, including via Verilog publications and other distributions. Verilog makes the reports available to parties other than the Clients (i.e., “third parties”) – on its website in hopes that it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.
tags:
Final Report
YuzuSwap Audit
This report presents our engineering engagement with YuzuSwap, one of the first DEX projects for the Emerald paratime on the Oasis Network. YuzuSwap is an AMM DEX with innovative trading incentive designs, such as the trading pool share token (TPST). YuzuSwap’s TPST design keeps track of DEX users’ swap operations and provides rewards for these users.
Table of Content
Project Summary
YuzuSwap is a decentralized exchange on the Oasis Emerald paratime that includes incentives such as liquidity mining and trade mining. YuzuSwap follows a non-custodial, peer-to-peer, automated-market-maker model and aims to provide a safe, swift, and low-cost tool to discover and swap tokens within the Oasis ecosystem. The YuzuSwap platform itself is fully open to developers and members of the Yuzu DAO.
Service Scope
Our review focused on the main branch, specifically, commit hash 12b06a57c53ec9eed3eadaded2afd93362d44d8b.
Our auditing service for YuzuSwap includes the following two stages:
Pre-Audit Consulting Service
As a part of the pre-audit service, the Verilog team worked closely with the YuzuSwap development to discuss potential vulnerability and smart contract development best practices in a timely fashion. Verilog team is very appreciative of establishing an efficient and effective communication channel with the YuzuSwap team, as new findings are often exchanged promptly and fixes were deployed quickly, during the preliminary report stage.
Audit Service
The Verilog team conducted a thorough study of the YuzuSwap code, with the YuzuSwap architecture graph and UML graph presented below in the YuzuSwap Architecture section. The list of findings, along with the severity and solution, is available under section Findings & Improvement Suggestions.
YuzuSwap Architecture
These are the major smart contracts in YuzuSwap:
YuzuToken.sol
YuzuKeeper.sol
YuzuPark.sol
YuzuParkExt.sol
YuzuRouter.sol
YuzuSwapMining.sol
YuzuZap.sol
YuzuKeeper.sol
YuzuKeeper
has the privilege to mint yuzu tokens to the registered applications anddev
address.YuzuToken.sol
YuzuToken
is a standard ERC20 token contract, that can be minted byowner
.YuzuPark.sol
YuzuPark
is the contract where it distributes yuzu tokens half-attenuationally as rewards for staking eligible tokens.YuzuParkExt.sol
YuzuParkExt
is a extenstion forYuzuPark
. Multiple tokens can be set as reward tokens besides the yuzu token.YuzuRouter.sol
It’s where users can swap tokens and accumulate yuzu rewards for eligible pairs.
YuzuSwapMining.sol
It’s where users can withdraw their accumulated yuzu rewards when user use
YuzuRouter
to swap tokens of eligible pair.YuzuZap.sol
In
YuzuZap
, users can get lp tokens by supplying a single token. Users can also swap back to a single token with the lp token.YUZUTokenBlackHole.sol
@ address 0x00b9dCA177aa3DB6F344A455d9E0511a6Aa7ad8DIts a blank contract deployed by YuzuSwap team acts like a blackhole( address(0) ) to burn all buy backed $YUZU token.
Privileged Roles
There is one main privileged role
owner
.It can:
YuzuToken.sol
applications
inYuzuKeeper.sol
YuzuPark.sol
,YuzuParkExt.sol
,YuzuSwapMining.sol
,YuzuRouter.sol
,StandardReward.sol
.Findings & Improvement Suggestions
InformationalMinorMediumMajorCritical
Critical
Router address should be a variable set by owner (
YuzuZap.sol
: L48, L93, L98, L112, L144, 165, L171).CriticalDescription: Router address is being passed in as argument and token allowance for router is set to maximum. Attackers can deploy a set of swap and router contracts with the same interface to drain contracts’ funds.
Recommendation: Router address should be a variable set by owner to prevent exploits.
Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
<address>.call()
should be used instead of<address>.transfer()
to transfer native tokens (YuzuZap.sol
:L448). CriticalDescription:
<address>.call()
should be used instead of<address>.transfer
to transfer native tokens.Recommendation: Use uniswap’s
TransferHelper.safeTransferETH()
to transfer native token.Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Reset amount of rewarder contract at
emergencyWithdraw
(YuzuParkExt.sol
: L313). CriticalDescription: User amounts of rewarder contracts are not reset to zero.
Recommendation: Reset User amounts of rewarder contracts to zero.
for (uint256 i = 0;i < _rewarders.length ; i ++ ) { IRewarder _rewarder = _rewarders[i]; if(address(_rewarder) != address(0)) { _rewarder.onYUZUReward(_pid,msg.sender, 0,0); } }
Result: Resolved in commit 6867b4b00980862cefc5feb8487e9bb98ae4e31c.
Major
No major issue was found.
Medium
Add nonRentrant modifier for external functions:
zapInToken()
,zapIn()
,zapAcross()
,zapOut()
,zapOutToken()
,swapToken()
,swapToNative()
(YuzuZap.sol
:L48, L93, L98, L112, L144, 165, L171). MediumDescription: No nonReentrant modifier for those functions.
Recommendation: Add nonReentrant modifier.
Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Approve actual amount instead of maximum amount (
YuzuZap.sol
:L180). MediumDescription: Maximum amount is used for approval here.
Recommendation: Modify the functions to approve actual amount instead of maximum amount.
Result: This suggestion is not adopted.
Minor
Require only receive native tokens from router address (
YuzuZap.sol
:L46). MinorDescription: Anyone can send native tokens to the contract
Recommendation: Require only router can send native tokens to current contract.
Result: This suggestion is not adopted.
Change
public
toexternal
for external call only functions(YuzuParkExt.sol
:L123, L149, L242, L280, L313,YuzuPark.sol
:L96, L120, L190, L217, L234). MinorDescription:
public
andexternal
differs in gas usage. Alsopublic
allows calls made inside the contract.Recommendation: Change
public
toexternal
for external call only functions.Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923 and in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
Add check for pool Id to make sure the pool does not exist at
addPool()
andadd()
(StandardReward.sol
:L70,YuzuPark.sol
:L96). MinorDescription: Pool might already exist.
Recommendation: For example, add the following requirement to check if pool id is valid.
require(poolInfo[_pid].lastRewardBlock == 0, "Pool already exists"); // or require(_pid >= poolInfo.length, "Pool already exists");
Result: Not Resolved.
Add check for pool Id to make sure pool exist at
updatePool()
andsetPool()
(YuzuParkExt.sol
:L219,YuzuPark.sol
:L167,StandardReward.sol
:L89, L99). MinorDescription: Pool might not exist.
Recommendation: For example, add the following requirement to check if pool already added.
require(poolInfo[_pid].lastRewardBlock != 0, "Pool not exists"); // or require(_pid < poolInfo.length, "Pool not exists");
Result: Not Resolved.
Some varibales can be immutable. (
YuzuZap.sol
:L35,HalfAttenuationYuzuReward.sol
:L13-L17). MinorDescription:
WNATIVE
atYuzuZap
andstartBlock
,blockNumberOfHalfAttenuationCycle
andyuzuPerBlock
atHalfAttenuationYuzuReward
can be immutable.Recommendation: add
immutable
keyword toWNATIVE
.Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
The visibility of function
getYuzuFromStartblock()
can bepure
(L41). MinorDescription: Function visibility can be restricted to
pure
.Recommendation: Change function visibility to
pure
.Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
Use
div
fromSafeMath
(StandardReward.sol
:L107, L109, L152, L177, L178, L182). MinorDescription: The
/
is used for division instead ofdiv
.Recommendation: Use
div
fromSafeMath
.Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Add Solidity pragma version. Minor
Description: There is no soldity version been added to the YuzuSwapMining.sol.
Recommendation: Add
pragma solidity 0.6.12;
as other smart contracts.Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Multiply before dividing (
YuzuKeeper
: L117). Minorfunction _queryActualYUZUReward(uint256 _amount) internal view returns (uint256) { uint256 actualAmount = _amount.div(10).mul(7); return actualAmount; }
Description: Use
div
beforemul
.Recommendation: Use
mul
beforediv
to prevent precision lost.// suggested changes function _queryActualYUZUReward(uint256 _amount) internal view returns (uint256) { uint256 actualAmount = _amount.mul(7).div(10); return actualAmount; }
Result: This suggestion is not adopted.
Informational
Seperate
interface
. InformationalDescription: Currently, interfaces is inside the same file with contract.
Recommendation: Seperate
interface
.Result: This suggestion is not adopted.
Call
massUpdatePools()
directly at functionsadd
andset
(YuzuParkExt.sol
:L130, L157,YuzuPark.sol
:L102, L126). InformationalDescription: The
_withUpdate
is always true.massUpdatePools()
can be called directly.Recommendation: Remove
if
else
check for_withUpdate
.massUpdatePools()
can be called directly.Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Modifies the logic of function
duplicatedTokenDetect()
. (YuzuPark.sol
:L254,YuzuParkExt.sol
:L345). InformationalDescription: the check for dulipcate tokens detection can be optimized.
Recommendation: For example, use a mapping to track added tokens.
Result: Resolved in commit 0d0caf24d4898dcd13ef803d8f29b1e6f2022eaf.
Input Multicheck and Limitation (
YuzuKeeper
: L62). Informationalfunction addApplication(address _yuzuMember , uint256 _totalValue, uint256 _perBlockLimit,uint256 _startBlock ) public onlyOwner appNotPublished { YuzuApplicatioin storage app = applications[_yuzuMember]; app.yuzuMember = _yuzuMember; app.totalValue = _totalValue; app.transferedValue = 0; app.perBlockLimit = _perBlockLimit; app.startBlock = _startBlock; emit ApplicationAdded(_yuzuMember,_totalValue,_perBlockLimit,_startBlock); }
Description: As one of the most important functions, input
_totalValue
should be limited into a certain range (less than 10% of the total token supply), input_perBlockLimit
should be limited into a certain range, input_startBlock
should be limited after certain date.Recommendation: Add requirement for each of the input.
// suggested changes, limitation should be determined by the project team function addApplication(address _yuzuMember , uint256 _totalValue, uint256 _perBlockLimit,uint256 _startBlock ) public onlyOwner appNotPublished { require(_yuzuMember != address(0), "YUZUKEEPER: ZERO ADDRESS"); require(_totalValue <= yuzu.totalSupply().div(10), "YUZUKEEPER: NO MORE THAN 10% OF TOTAL SUPPLY"); require(_perBlockLimit <= 1e18, "YUZUKEEPER: PER BLOCK LIMITATION"); require(_startBlock >= block.timestamp, "YUZUKEEPER: START AFTER CERTAIN TIME"); ...... }
Result: This suggestion is not adopted. We suggest that the owner of the smart contract must be very careful when calling this function.
Logic Improvement for Function
RequestForYUZU()
(YuzuKeeper
: L79). InformationalDescription: When 1 $YUZU is mint, 0.1 for investor, 0.1 for foundation, 0.1 for dev. The current logic is to send the above 0.3 $YUZU first before sending the leftAmount to the user. This design is a bit unfair for the unlucky users who mint the last bit of Yuzu.
Recommendation:
step 1: check how many $YUZU is left.
step 2: adjust the mint amount to the leftover amount of $YUZU if the mint amount exceeds the leftover amount.
step 3: mint based on the distribution.
*external changes required: YuzuToken.sol needs to add a
circulatingSupply()
external view function to feed YuzuKeeper how many tokens have been mint out.Result: This suggestion is not adopted.
Add public view functions for
poolInfo.length
atStandardReward.sol
.InformationalDescription: A view function can be added to check the
poolInfo.length
for the convenience of adding pools in the future.Recommendation: Add a public view function for
poolInfo.length
Result: Resolved in commit 7333cda08cf6afabeb633e03cbc07143e8fb6923.
Unused variable
_pendingYUZU
atonYUZUReward()
andpendingToken()
(StandardReward.sol
:L145, L168). InformationalDescription: Unused variable
_pendingYUZU
.Recommendation: Change the code to followings to remove compiler warnings for unused variables.
// onYUZUReward function onYUZUReward( uint256 pid, address _user, uint256 lpToken, uint256 // using just uint256 without variable name will remove the warning ) { ... } // similarly for pendingToken function pendingToken(uint256 _pid, address _user, uint256) { ... }
Result: This suggestion is not adopted.
Disclaimer
Verilog receives compensation from one or more clients for performing the smart contract and auditing analysis contained in these reports. The report created is solely for Clients and published with their consent. As such, the scope of our audit is limited to a review of code, and only the code we note as being within the scope of our audit detailed in this report. It is important to note that the Solidity code itself presents unique and unquantifiable risks since the Solidity language itself remains under current development and is subject to unknown risks and flaws. Our sole goal is to help reduce the attack vectors and the high level of variance associated with utilizing new and consistently changing technologies. Thus, Verilog in no way claims any guarantee of security or functionality of the technology we agree to analyze.
In addition, Verilog reports do not provide any indication of the technologies proprietors, business, business model, or legal compliance. As such, reports do not provide investment advice and should not be used to make decisions about investment or involvement with any particular project. Verilog has the right to distribute the Report through other means, including via Verilog publications and other distributions. Verilog makes the reports available to parties other than the Clients (i.e., “third parties”) – on its website in hopes that it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.