Skip to content

akiratechhq/review-xave-lending-market-2021-10

Repository files navigation

Project
Xave Lending Market
Client
Xave Finance
Date
October 2021
Reviewers
Andrei Simion
@andreiashu
Daniel Luca
@cleanunicorn

Table of Contents

Details

  • Client Xave Finance
  • Date October 2021
  • Lead reviewer Andrei Simion (@andreiashu)
  • Reviewers Daniel Luca (@cleanunicorn), Andrei Simion (@andreiashu)
  • Repository: Xave Lending Market
  • Commit hash 01486a398b0aa36b9798ba06fce11b5d3376909d
  • Technologies
    • Solidity
    • Typescript

Issues Summary

SEVERITY OPEN CLOSED
Informational 1 0
Minor 3 0
Medium 1 0
Major 0 0

Executive summary

This report represents the results of the engagement with Xave Finance to review Xave Lending Market.

The review is part of a broader engagement with Xave Finance that also includes the Xave AMM component.

The full review was conducted over the course of 2 weeks from October 18th to October 29th, 2021. We spent a total of 15 person-days reviewing the code.

Scope

The initial review focused on the Xave Lending Market repository, identified by the commit hash 01486a398b0aa36b9798ba06fce11b5d3376909d.

We focused on manually reviewing the codebase, searching for security issues such as, but not limited to, re-entrancy problems, transaction ordering, block timestamp dependency, exception handling, call stack depth limitation, integer overflow/underflow, self-destructible contracts, unsecured balance, use of origin, costly gas patterns, architectural problems, code readability.

Includes:

  • code/contracts/buyback/Treasury.sol
  • code/contracts/buyback/interfaces/ICurve.sol
  • code/contracts/buyback/interfaces/ICurveFactory.sol
  • code/contracts/buyback/interfaces/IUniswapV2Router01.sol
  • code/contracts/buyback/interfaces/IUniswapV2Router02.sol
  • code/contracts/incentives/RnbwDistributionManager.sol
  • code/contracts/incentives/RnbwIncentivesController.sol
  • code/contracts/incentives/VersionedInitializable.sol
  • code/contracts/incentives/interfaces/IAToken.sol
  • code/contracts/incentives/interfaces/IERC20.sol
  • code/contracts/incentives/interfaces/IERC20Detailed.sol
  • code/contracts/incentives/interfaces/IRnbwDistributionManager.sol
  • code/contracts/incentives/interfaces/IRnbwIncentivesController.sol
  • code/contracts/incentives/interfaces/IStakedAave.sol
  • code/contracts/incentives/lib/Context.sol
  • code/contracts/incentives/lib/DistributionTypes.sol
  • code/contracts/incentives/lib/ERC20.sol
  • code/contracts/incentives/lib/SafeMath.sol

Recommendations

We identified a few possible general improvements that are not security issues during the review, which will bring value to the developers and the community reviewing and using the product.

Increase the number of tests

A good rule of thumb is to have 100% test coverage. This does not guarantee the lack of security problems, but it means that the desired functionality behaves as intended. The negative tests also bring a lot of value because not allowing some actions to happen is also part of the desired behavior.

Issues

Issue status: Open Medium

Description

The owner of the Treasury can call the buybackRnbw function to convert one or more of the underlying tokens within a lending pool to rnbw tokens:

code/contracts/buyback/Treasury.sol#L44

  function buybackRnbw(address[] calldata _underlyings) external onlyOwner returns (uint256) {

The function first uses the cloned DFX protocol to convert the token into USDC:

code/contracts/buyback/Treasury.sol#L81-L88

    uint256 targetAmount =
      ICurve(curveAddress).originSwap(
        _underlying,
        USDC,
        _underlyingAmount,
        0,
        block.timestamp + 60
      );

After that the Uniswap V2 protocol is used to convert from USDC to RNBW tokens:

code/contracts/buyback/Treasury.sol#L59-L69

    address[] memory path = new address[](3);
    path[0] = USDC;
    path[1] = WETH9;
    path[2] = rnbw;
    rnbwBought = IUniswapV2Router02(router).swapExactTokensForTokens(
      usdcBalance,
      0,
      path,
      address(this),
      block.timestamp + 60
    )[0];

The issue is that in both token swap cases above, the arguments amountOutMin (for Uniswap) and _minTargetAmount (for DFX Curve contract) are passed as 0 values. This means that the Treasury contract does not enforce any minimum amount expected for the output of RNBW tokens swapped.

The reason why the above two implementations are vulnerable to price manipulation is explained in the Uniswap V2 Safety Considerations section:

Because Ethereum transactions occur in an adversarial environment, smart contracts that do not perform safety checks can be exploited for profit. If a smart contract assumes that the current price on Uniswap is a "fair" price without performing safety checks, it is vulnerable to manipulation. A bad actor could e.g. easily insert transactions before and after the swap (a "sandwich" attack) causing the smart contract to trade at a much worse price, profit from this at the trader's expense, and then return the contracts to their original state. (One important caveat is that these types of attacks are mitigated by trading in extremely liquid pools, and/or at low values.)

Recommendation

The best way to protect against these attacks is to use an external price feed or "price oracle". The best "oracle" is simply traders' off-chain observation of the current price, which can be passed into the trade as a safety check.

The buybackRnbw function can accept an additional parameter minRNBWAmount that can be checked after the two above steps are performed, or passed to the swapExactTokensForTokens Uniswap function, to ensure that an expected minimum amount of RNBW tokens were received by the Treasury contract.

For example, Uniswap V2 getAmountsOut can be used by a frontend to calculate a fair value for USDC / RNBW:

Given an input asset amount and an array of token addresses calculates all subsequent maximum output token amounts by calling getReserves for each pair of token addresses in the path in turn, and using these to call getAmountOut.

Useful for calculating optimal token amounts before calling swap.

References

Uniswap V2 Documentation: Implement a Swap

DEFI Sandwich Attack Explaination

Rapid Rise of MEV in Ethereum


Issue status: Open Minor

Description

WETH9 state variable never changes therefore it can be defined as a constant to save gas costs:

code/contracts/buyback/Treasury.sol#L26

  address public WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

Issue status: Open Minor

Description

In most cases the code makes use of the OpenZeppelin's standard libraries:

code/contracts/buyback/Treasury.sol#L7-L9

import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';

In other cases, however, the code uses copy-pasted versions of the same libraries:

code/contracts/incentives/RnbwIncentivesController.sol#L6-L8

import {SafeMath} from './lib/SafeMath.sol';

import {IERC20} from './interfaces/IERC20.sol';

Below we show that there are not functional differences between the ./incentives/lib/Context.sol file and the one that comes with OpenZeppelin:

$ diff -uN --ignore-all-space ./incentives/lib/Context.sol ../node_modules/@openzeppelin/contracts/GSN/Context.sol
--- ./incentives/lib/Context.sol        2021-10-22 08:00:48.000000000 +0700
+++ ../node_modules/@openzeppelin/contracts/GSN/Context.sol     2021-10-22 13:39:41.000000000 +0700
@@ -1,10 +1,9 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity 0.6.12;
+pragma solidity ^0.6.0;
 
-/**
- * @dev From https://github.com/OpenZeppelin/openzeppelin-contracts
- * Provides information about the current execution context, including the
+/*
+ * @dev Provides information about the current execution context, including the
  * sender of the transaction and its data. While these are generally available

SafeMath.sol is identical but the diff is bigger because of different code formatting:

$ diff -uN --ignore-all-space ./incentives/lib/SafeMath.sol ../node_modules/@openzeppelin/contracts/math/SafeMath.sol
--- ./incentives/lib/SafeMath.sol       2021-10-22 08:00:48.000000000 +0700
+++ ../node_modules/@openzeppelin/contracts/math/SafeMath.sol   2021-10-22 13:39:41.000000000 +0700
@@ -1,9 +1,9 @@
-// SPDX-License-Identifier: agpl-3.0
-pragma solidity 0.6.12;
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.6.0;
 
 /**
- * @dev From https://github.com/OpenZeppelin/openzeppelin-contracts
- * Wrappers over Solidity's arithmetic operations with added overflow
+ * @dev Wrappers over Solidity's arithmetic operations with added overflow
  * checks.
  *
  * Arithmetic operations in Solidity wrap on overflow. This can easily result
@@ -23,11 +23,12 @@
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
+     *
    * - Addition cannot overflow.
    */
   function add(uint256 a, uint256 b) internal pure returns (uint256) {
     uint256 c = a + b;
-    require(c >= a, 'SafeMath: addition overflow');
+        require(c >= a, "SafeMath: addition overflow");
 
     return c;
   }
@@ -39,10 +40,11 @@
    * Counterpart to Solidity's `-` operator.
    *
    * Requirements:
+     *
    * - Subtraction cannot overflow.
    */
   function sub(uint256 a, uint256 b) internal pure returns (uint256) {
-    return sub(a, b, 'SafeMath: subtraction overflow');
+        return sub(a, b, "SafeMath: subtraction overflow");
   }
 
   /**
@@ -52,13 +54,10 @@
    * Counterpart to Solidity's `-` operator.
    *
    * Requirements:
+     *
    * - Subtraction cannot overflow.
    */
-  function sub(
-    uint256 a,
-    uint256 b,
-    string memory errorMessage
-  ) internal pure returns (uint256) {
+    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
     require(b <= a, errorMessage);
     uint256 c = a - b;
 
@@ -72,6 +71,7 @@
    * Counterpart to Solidity's `*` operator.
    *
    * Requirements:
+     *
    * - Multiplication cannot overflow.
    */
   function mul(uint256 a, uint256 b) internal pure returns (uint256) {
@@ -83,7 +83,7 @@
     }
 
     uint256 c = a * b;
-    require(c / a == b, 'SafeMath: multiplication overflow');
+        require(c / a == b, "SafeMath: multiplication overflow");
 
     return c;
   }
@@ -97,10 +97,11 @@
    * uses an invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
+     *
    * - The divisor cannot be zero.
    */
   function div(uint256 a, uint256 b) internal pure returns (uint256) {
-    return div(a, b, 'SafeMath: division by zero');
+        return div(a, b, "SafeMath: division by zero");
   }
 
   /**
@@ -112,14 +113,10 @@
    * uses an invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
+     *
    * - The divisor cannot be zero.
    */
-  function div(
-    uint256 a,
-    uint256 b,
-    string memory errorMessage
-  ) internal pure returns (uint256) {
-    // Solidity only automatically asserts when dividing by 0
+    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
     require(b > 0, errorMessage);
     uint256 c = a / b;
     // assert(a == b * c + a % b); // There is no case in which this doesn't hold
@@ -136,10 +133,11 @@
    * invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
+     *
    * - The divisor cannot be zero.
    */
   function mod(uint256 a, uint256 b) internal pure returns (uint256) {
-    return mod(a, b, 'SafeMath: modulo by zero');
+        return mod(a, b, "SafeMath: modulo by zero");
   }
 
   /**
@@ -151,13 +149,10 @@
    * invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
+     *
    * - The divisor cannot be zero.
    */
-  function mod(
-    uint256 a,
-    uint256 b,
-    string memory errorMessage
-  ) internal pure returns (uint256) {
+    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
     require(b != 0, errorMessage);
     return a % b;
   }

Recommendation

Remove the following contracts from ./code/contracts/incentives/lib/ folder and make use of the version provided with OpenZeppelin: Context, ERC20, MintableErc20, SafeMath.


Issue status: Open Minor

Description

Treasury.buybackRnbw() uses Uniswap V2 to convert underlying tokens into USDC:

code/contracts/buyback/Treasury.sol#L63-L69

    rnbwBought = IUniswapV2Router02(router).swapExactTokensForTokens(
      usdcBalance,
      0,
      path,
      address(this),
      block.timestamp + 60
    )[0];

The deadline argument passed to swapExactTokensForTokens function is 60 blocks into the future. The deadline parameter is useful for frontend and other off-chain software to ensure there's a deadline after which a swap transaction will revert.

In this case, passing just block.timestamp is enough to ensure correct behavior:

Uniswap's swapExactTokensForTokens definition:

    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external override ensure(deadline) returns (uint[] memory amounts) {

Uniswap ensure modifier:

    modifier ensure(uint deadline) {
        require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED');
        _;
    }

Recommendation

Instead of block.timestamp + 60 just pass block.timestamp as the deadline argument to swapExactTokensForTokens call.

Notes

A similar change can be made to the originSwap call:

code/contracts/buyback/Treasury.sol#L81-L88

    uint256 targetAmount =
      ICurve(curveAddress).originSwap(
        _underlying,
        USDC,
        _underlyingAmount,
        0,
        block.timestamp + 60
      );

The issue here though is that you still need to add +1 to the block.timestamp because of the way the deadline modifier in Curve.sol is defined. Because of this, we leave it to the Xave Finance team the decision change the call to originSwap since there are no (gas) benefits, although it might provide more clarity to the reader:

    modifier deadline(uint256 _deadline) {
        require(block.timestamp < _deadline, "Curve/tx-deadline-passed");
        _;
    }

Issue status: Open Informational

Description

The onlyEOA modifier is obsolete and can be removed:

code/contracts/buyback/Treasury.sol#L98-L101

  modifier onlyEOA() {
    require(msg.sender == tx.origin, 'Only EOA allowed');
    _;
  }

Artifacts

Surya

Sūrya is a utility tool for smart contract systems. It provides a number of visual outputs and information about the 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.

Sūrya's Description Report

Files Description Table

File Name SHA-1 Hash
code/contracts/buyback/Treasury.sol aabfa1b294af1775a30ad7cc1432aca3adaef48a
code/contracts/buyback/interfaces/ICurve.sol 6709bd40881023198aa153762c2680cf5825c1c5
code/contracts/buyback/interfaces/ICurveFactory.sol 6818643831d3b11ae062df66ac13478a9e7a458c
code/contracts/buyback/interfaces/IUniswapV2Router01.sol 2acc9e5833363f28ed4da6a17ca9ff5aec263a16
code/contracts/buyback/interfaces/IUniswapV2Router02.sol c6896849a13dcbff97b81a39a29a6b8aec28d8e8
code/contracts/incentives/RnbwDistributionManager.sol d7e6fda899a3c2b76edd3f02535b9f8fe1bae20b
code/contracts/incentives/RnbwIncentivesController.sol 4f54f90c53d3c635c7d198b3514040d65b728c0c
code/contracts/incentives/VersionedInitializable.sol 8727598c2af3d69e992d12074c5cb63f77ed0357
code/contracts/incentives/interfaces/IAToken.sol b973c8ceb01f4b43092435f8a79c7422093351bf
code/contracts/incentives/interfaces/IERC20.sol ecd6d26d76013b7dc7c7c309e651200895d3eba7
code/contracts/incentives/interfaces/IERC20Detailed.sol 552c23c3ba74003da1d837e52e8c9d2caee8c7a2
code/contracts/incentives/interfaces/IRnbwDistributionManager.sol b01e2e6b38a815e6a18faf1ba8d4a5cd427995ed
code/contracts/incentives/interfaces/IRnbwIncentivesController.sol 1e27c32483aeb95b80f3d859fc6094c702001cfe
code/contracts/incentives/interfaces/IStakedAave.sol af981d723fa5ab19fb6fc8bfa494283e58d4eddc
code/contracts/incentives/lib/Context.sol ff1e49ddb3ef87789448a17c39e3ee1992ebfad7
code/contracts/incentives/lib/DistributionTypes.sol 1cf4903d754a79c147c94142915d8c34cc710bf7
code/contracts/incentives/lib/ERC20.sol 4e48c68a0c7125c0cda79e9c22dd950eb835742a
code/contracts/incentives/lib/SafeMath.sol 6b776dc4a284a7c92f78c37360f8abcf5b8bec72
code/contracts/protocol/tokenization/IncentivizedERC20.sol 4e0442ef5b1ff0d01e993f67624f397e76fec335

Contracts Description Table

Contract Type Bases
Function Name Visibility Mutability Modifiers
Treasury Implementation Ownable
Public ❗️ 🛑 NO❗️
buybackRnbw External ❗️ 🛑 onlyOwner
convertToUsdc Internal 🔒 🛑
sendToVestingContract External ❗️ 🛑 onlyOwner
ICurve Interface
originSwap External ❗️ 🛑 NO❗️
ICurveFactory Interface
getCurve External ❗️ NO❗️
IUniswapV2Router01 Interface
factory External ❗️ NO❗️
WETH External ❗️ NO❗️
addLiquidity External ❗️ 🛑 NO❗️
addLiquidityETH External ❗️ 💵 NO❗️
removeLiquidity External ❗️ 🛑 NO❗️
removeLiquidityETH External ❗️ 🛑 NO❗️
removeLiquidityWithPermit External ❗️ 🛑 NO❗️
removeLiquidityETHWithPermit External ❗️ 🛑 NO❗️
swapExactTokensForTokens External ❗️ 🛑 NO❗️
swapTokensForExactTokens External ❗️ 🛑 NO❗️
swapExactETHForTokens External ❗️ 💵 NO❗️
swapTokensForExactETH External ❗️ 🛑 NO❗️
swapExactTokensForETH External ❗️ 🛑 NO❗️
swapETHForExactTokens External ❗️ 💵 NO❗️
quote External ❗️ NO❗️
getAmountOut External ❗️ NO❗️
getAmountIn External ❗️ NO❗️
getAmountsOut External ❗️ NO❗️
getAmountsIn External ❗️ NO❗️
IUniswapV2Router02 Interface IUniswapV2Router01
removeLiquidityETHSupportingFeeOnTransferTokens External ❗️ 🛑 NO❗️
removeLiquidityETHWithPermitSupportingFeeOnTransferTokens External ❗️ 🛑 NO❗️
swapExactTokensForTokensSupportingFeeOnTransferTokens External ❗️ 🛑 NO❗️
swapExactETHForTokensSupportingFeeOnTransferTokens External ❗️ 💵 NO❗️
swapExactTokensForETHSupportingFeeOnTransferTokens External ❗️ 🛑 NO❗️
RnbwDistributionManager Implementation IRnbwDistributionManager
Public ❗️ 🛑 NO❗️
configureAssets External ❗️ 🛑 NO❗️
_updateAssetStateInternal Internal 🔒 🛑
_updateUserAssetInternal Internal 🔒 🛑
_claimRewards Internal 🔒 🛑
_getUnclaimedRewards Internal 🔒
_getRewards Internal 🔒
_getAssetIndex Internal 🔒
getUserAssetData Public ❗️ NO❗️
RnbwIncentivesController Implementation IRnbwIncentivesController, VersionedInitializable, RnbwDistributionManager
Public ❗️ 🛑 RnbwDistributionManager
handleAction External ❗️ 🛑 NO❗️
getRewardsBalance External ❗️ NO❗️
claimRewards External ❗️ 🛑 NO❗️
getUserUnclaimedRewards External ❗️ NO❗️
getRevision Internal 🔒
VersionedInitializable Implementation
getRevision Internal 🔒
IAToken Interface
getScaledUserBalanceAndSupply External ❗️ NO❗️
IERC20 Interface
totalSupply External ❗️ NO❗️
balanceOf External ❗️ NO❗️
transfer External ❗️ 🛑 NO❗️
allowance External ❗️ NO❗️
approve External ❗️ 🛑 NO❗️
transferFrom External ❗️ 🛑 NO❗️
IERC20Detailed Interface IERC20
name External ❗️ NO❗️
symbol External ❗️ NO❗️
decimals External ❗️ NO❗️
IRnbwDistributionManager Interface
configureAssets External ❗️ 🛑 NO❗️
IRnbwIncentivesController Interface
handleAction External ❗️ 🛑 NO❗️
getRewardsBalance External ❗️ NO❗️
claimRewards External ❗️ 🛑 NO❗️
IStakedAave Interface
stake External ❗️ 🛑 NO❗️
redeem External ❗️ 🛑 NO❗️
cooldown External ❗️ 🛑 NO❗️
claimRewards External ❗️ 🛑 NO❗️
Context Implementation
_msgSender Internal 🔒
_msgData Internal 🔒
DistributionTypes Library
ERC20 Implementation Context, IERC20, IERC20Detailed
Public ❗️ 🛑 NO❗️
name Public ❗️ NO❗️
symbol Public ❗️ NO❗️
decimals Public ❗️ NO❗️
totalSupply Public ❗️ NO❗️
balanceOf Public ❗️ NO❗️
transfer Public ❗️ 🛑 NO❗️
allowance Public ❗️ NO❗️
approve Public ❗️ 🛑 NO❗️
transferFrom Public ❗️ 🛑 NO❗️
increaseAllowance Public ❗️ 🛑 NO❗️
decreaseAllowance Public ❗️ 🛑 NO❗️
_transfer Internal 🔒 🛑
_mint Internal 🔒 🛑
_burn Internal 🔒 🛑
_approve Internal 🔒 🛑
_setName Internal 🔒 🛑
_setSymbol Internal 🔒 🛑
_setDecimals Internal 🔒 🛑
_beforeTokenTransfer Internal 🔒 🛑
SafeMath Library
add Internal 🔒
sub Internal 🔒
sub Internal 🔒
mul Internal 🔒
div Internal 🔒
div Internal 🔒
mod Internal 🔒
mod Internal 🔒
IncentivizedERC20 Implementation Context, IERC20, IERC20Detailed
Public ❗️ 🛑 NO❗️
name Public ❗️ NO❗️
symbol Public ❗️ NO❗️
decimals Public ❗️ NO❗️
totalSupply Public ❗️ NO❗️
balanceOf Public ❗️ NO❗️
_getIncentivesController Internal 🔒
transfer Public ❗️ 🛑 NO❗️
allowance Public ❗️ NO❗️
approve Public ❗️ 🛑 NO❗️
transferFrom Public ❗️ 🛑 NO❗️
increaseAllowance Public ❗️ 🛑 NO❗️
decreaseAllowance Public ❗️ 🛑 NO❗️
_transfer Internal 🔒 🛑
_mint Internal 🔒 🛑
_burn Internal 🔒 🛑
_approve Internal 🔒 🛑
_setName Internal 🔒 🛑
_setSymbol Internal 🔒 🛑
_setDecimals Internal 🔒 🛑
_beforeTokenTransfer Internal 🔒 🛑

Legend

Symbol Meaning
🛑 Function can modify state
💵 Function is payable

Graphs

Treasury Graph

RnbwDistributionManager Graph

RnbwIncentivesController Graph

Describe

$ npx surya describe code/contracts/buyback/Treasury.sol
 +  Treasury (Ownable)
    - [Pub] <Constructor> #
    - [Ext] buybackRnbw #
       - modifiers: onlyOwner
    - [Int] convertToUsdc #
    - [Ext] sendToVestingContract #
       - modifiers: onlyOwner


 ($) = payable function
 # = non-constant function
$ npx surya describe code/contracts/incentives/RnbwDistributionManager.sol
 +  RnbwDistributionManager (IRnbwDistributionManager)
    - [Pub] <Constructor> #
    - [Ext] configureAssets #
    - [Int] _updateAssetStateInternal #
    - [Int] _updateUserAssetInternal #
    - [Int] _claimRewards #
    - [Int] _getUnclaimedRewards
    - [Int] _getRewards
    - [Int] _getAssetIndex
    - [Pub] getUserAssetData


 ($) = payable function
 # = non-constant function
$ npx surya describe code/contracts/incentives/RnbwIncentivesController.sol
 +  RnbwIncentivesController (IRnbwIncentivesController, VersionedInitializable, RnbwDistributionManager)
    - [Pub] <Constructor> #
       - modifiers: RnbwDistributionManager
    - [Ext] handleAction #
    - [Ext] getRewardsBalance
    - [Ext] claimRewards #
    - [Ext] getUserUnclaimedRewards
    - [Int] getRevision


 ($) = payable function
 # = non-constant function

Tests

npm run testhalo

> @aave/[email protected] testhalo
> npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/_*.spec.ts


> @aave/[email protected] compile
> SKIP_LOAD=true hardhat compile

Compiling 137 files with 0.6.12
contracts/buyback/interfaces/IUniswapV2Router01.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/buyback/interfaces/IUniswapV2Router02.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/buyback/interfaces/IUniswapV2RouterMock.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/buyback/mocks/UniswapMock.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/incentives/interfaces/IAToken.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/protocol/lendingpool/LendingPoolConfigurator.sol:70:25: Warning: This declaration shadows an existing declaration.
  function _initReserve(ILendingPool pool, InitReserveInput calldata input) internal {
                        ^---------------^
contracts/protocol/lendingpool/LendingPoolConfigurator.sol:34:3: The shadowed declaration is here:
  ILendingPool internal pool;
  ^------------------------^

contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol:14:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/dependencies/openzeppelin/upgradeability/AdminUpgradeabilityProxy.sol:11:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol:11:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy {
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/dependencies/openzeppelin/upgradeability/InitializableAdminUpgradeabilityProxy.sol:12:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract InitializableAdminUpgradeabilityProxy is
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/protocol/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol:16:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract BaseImmutableAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/protocol/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol:11:1: Warning: This contract has a payable fallback function, but no receive ether function. Consider adding a receive ether function.
contract InitializableImmutableAdminUpgradeabilityProxy is
^ (Relevant source part starts here and spans across multiple lines).
contracts/dependencies/openzeppelin/upgradeability/Proxy.sol:16:3: The payable fallback function is defined here.
  fallback() external payable {
  ^ (Relevant source part starts here and spans across multiple lines).

contracts/buyback/mocks/CurveMock.sol:38:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    address _target,
    ^-------------^

contracts/buyback/mocks/CurveMock.sol:40:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    uint256 _minTargetAmount,
    ^----------------------^

contracts/buyback/mocks/CurveMock.sol:41:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    uint256 _deadline
    ^---------------^

contracts/buyback/mocks/UniswapMock.sol:18:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    uint256 amountOutMin,
    ^------------------^

contracts/buyback/mocks/UniswapMock.sol:20:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    address to,
    ^--------^

contracts/buyback/mocks/UniswapMock.sol:21:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    uint256 deadline
    ^--------------^

contracts/incentives/RnbwIncentivesController.sol:119:5: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
    bool stake
    ^--------^

contracts/mocks/dependencies/weth/WETH9.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: <SPDX-License>" to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information.

contracts/mocks/oracle/CLAggregators/MockAggregator.sol:18:3: Warning: Function state mutability can be restricted to pure
  function getTokenType() external view returns (uint256) {
  ^ (Relevant source part starts here and spans across multiple lines).

Compilation finished successfully
Creating Typechain artifacts in directory types for target ethers-v5
Successfully generated Typechain artifacts!
Creating Typechain artifacts in directory types for target ethers-v5
Successfully generated Typechain artifacts!

- Enviroment
  - Network : hardhat
-> Deploying test environment...
Deployed mocks
Mock aggs deployed
- Oracle borrow initalization in 1 txs
  - Setted Oracle Borrow Rates for: WETH, DAI, USDC, XSGD, THKD
Initialize configuration
- Skipping init of AAVE due token address is not set at markets config
- Skipping init of BAT due token address is not set at markets config
- Skipping init of BUSD due token address is not set at markets config
Strategy address for asset DAI: 0xBbC60A8fAf66552554e460d55Ac0563Fb9e76c01
Strategy address for asset XSGD: 0xdDD96662ea11dA6F289A5D00da41Ec5F3b67d2b4
Strategy address for asset THKD: 0xdDD96662ea11dA6F289A5D00da41Ec5F3b67d2b4
- Skipping init of ENJ due token address is not set at markets config
- Skipping init of KNC due token address is not set at markets config
- Skipping init of LINK due token address is not set at markets config
- Skipping init of MANA due token address is not set at markets config
- Skipping init of MKR due token address is not set at markets config
- Skipping init of REN due token address is not set at markets config
- Skipping init of SNX due token address is not set at markets config
- Skipping init of SUSD due token address is not set at markets config
- Skipping init of TUSD due token address is not set at markets config
- Skipping init of UNI due token address is not set at markets config
Strategy address for asset USDC: 0xdDD96662ea11dA6F289A5D00da41Ec5F3b67d2b4
- Skipping init of USDT due token address is not set at markets config
- Skipping init of WBTC due token address is not set at markets config
Strategy address for asset WETH: 0xecE50C63d1Ae02Ba306c2b2E1579d0327220196e
- Skipping init of YFI due token address is not set at markets config
- Skipping init of ZRX due token address is not set at markets config
- Skipping init of xSUSHI due token address is not set at markets config
- Reserves initialization in 2 txs
  - Reserve ready for: DAI, XSGD, THKD, USDC
    * gasUsed 7972709
  - Reserve ready for: WETH
    * gasUsed 2039566
- Skipping init of AAVE due token address is not set at markets config
- Skipping init of BAT due token address is not set at markets config
- Skipping init of BUSD due token address is not set at markets config
- Skipping init of ENJ due token address is not set at markets config
- Skipping init of KNC due token address is not set at markets config
- Skipping init of LINK due token address is not set at markets config
- Skipping init of MANA due token address is not set at markets config
- Skipping init of MKR due token address is not set at markets config
- Skipping init of REN due token address is not set at markets config
- Skipping init of SNX due token address is not set at markets config
- Skipping init of SUSD due token address is not set at markets config
- Skipping init of TUSD due token address is not set at markets config
- Skipping init of UNI due token address is not set at markets config
- Skipping init of USDT due token address is not set at markets config
- Skipping init of WBTC due token address is not set at markets config
- Skipping init of YFI due token address is not set at markets config
- Skipping init of ZRX due token address is not set at markets config
- Skipping init of xSUSHI due token address is not set at markets config
- Configure reserves in 1 txs
  - Init for: DAI, XSGD, THKD, USDC, WETH
setup: 6.226s

***************
Setup and snapshot finished
***************

  Fee BuyBack
Rnbw Address: 0xE4C10Db67595aF2Cb4166c8C274e0140f7E43059
0x099d9fF8F818290C8b5B7Db5bFca84CEebd2714c
0x00aD4926D7613c8e00cB6CFa61831D5668265724
BigNumber { _hex: '0x0458fd2d9341', _isBigNumber: true }
BigNumber { _hex: '0x00', _isBigNumber: true }
BigNumber { _hex: '0x00', _isBigNumber: true }
Deployer has rnbw tokens: 10000000000000000000000000
curveMockDaiAddress: 0xe1B3b8F6b298b52bCd15357ED29e65e66a4045fF
Deployer has usdc tokens: 10000000000000000000000000
Uniswap Contract Rnbw balance initial: 10000000000000000000000000
Treasury Contract Rnbw balance initial: 0
Buy back rnbw ...
Treasury Contract Rnbw balance final: 9560502593770
Vesting Contract Rnbw balance initial: 0
Send rnbw to vesting ...
Vesting Contract Rnbw balance final: 9560502593770
    ✓ buyback test

  Incentives Controller
deployer.address: 0xc783df8a850f42e7F7e57013759C285caa701eB6
secondaryWallet.address: 0xeAD9C93b79Ae7C1591b1FB5323BD777E86e150d4
Rnbw Address: 0xE4C10Db67595aF2Cb4166c8C274e0140f7E43059
emissionManager: 0x79dC3dA279A2ADc72210BD00e10951AB9dC70ABc
rnbwIncentivesController: 0xF0B4ACda6D679ea22AC5C4fD1973D0d58eA10ec1
emissionManager rnbwIncentivesController: 0x79dC3dA279A2ADc72210BD00e10951AB9dC70ABc
incentives Controller set on emission manager: 0xF0B4ACda6D679ea22AC5C4fD1973D0d58eA10ec1
incentivesController dai: 1000000000000000000,1635484852,0
incentivesController xsgd: 1000000000000000000,1635484852,0
aDAI balance user after deposit: 2000000000000000000000
0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F
User Unclaimed rewards: 606000000000000000000
User RewardsBalance: 1205999988832760484000
User 2 Unclaimed rewards: 603000000000000000000
User 2 RewardsBalance: 603000000000000000000
    ✓ steak

·----------------------------------------------------------------------------|---------------------------|-------------|-----------------------------·
|                            Solc version: 0.6.12                            ·  Optimizer enabled: true  ·  Runs: 200  ·  Block limit: 12450000 gas  │
·············································································|···························|·············|······························
|  Methods                                                                                                                                           │
·········································|···································|·············|·············|·············|···············|··············
|  Contract                              ·  Method                           ·  Min        ·  Max        ·  Avg        ·  # calls      ·  eur (avg)  │
·········································|···································|·············|·············|·············|···············|··············
|  ATokensAndRatesHelper                 ·  configureReserves                ·          -  ·          -  ·     243281  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPool                           ·  borrow                           ·     312133  ·     397054  ·     352671  ·            4  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPool                           ·  deposit                          ·     245995  ·     285665  ·     261744  ·            6  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPool                           ·  setUserUseReserveAsCollateral    ·          -  ·          -  ·      75575  ·            3  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setEmergencyAdmin                ·          -  ·          -  ·      47243  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setLendingPoolCollateralManager  ·          -  ·          -  ·      47176  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setLendingPoolConfiguratorImpl   ·          -  ·          -  ·     537594  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setLendingPoolImpl               ·          -  ·          -  ·     578804  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setLendingRateOracle             ·          -  ·          -  ·      47198  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setPoolAdmin                     ·      30121  ·      47221  ·      35821  ·            6  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider          ·  setPriceOracle                   ·          -  ·          -  ·      47198  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProviderRegistry  ·  registerAddressesProvider        ·          -  ·          -  ·      91923  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingPoolConfigurator               ·  batchInitReserve                 ·    2039566  ·    7972709  ·    5006138  ·            4  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  LendingRateOracle                     ·  transferOwnership                ·          -  ·          -  ·      28605  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  MintableERC20                         ·  approve                          ·          -  ·          -  ·      46195  ·            4  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  MintableERC20                         ·  mint                             ·          -  ·          -  ·      68102  ·            5  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  MintableERC20                         ·  transfer                         ·          -  ·          -  ·      36723  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  MockEmissionManager                   ·  configure                        ·          -  ·          -  ·      87183  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  MockEmissionManager                   ·  setIncentivesController          ·          -  ·          -  ·      46153  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  PriceOracle                           ·  setAssetPrice                    ·      45615  ·      45639  ·      45629  ·           10  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  PriceOracle                           ·  setEthUsdPrice                   ·          -  ·          -  ·      44944  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  RnbwMock                              ·  mint                             ·          -  ·          -  ·      70769  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  RnbwMock                              ·  transfer                         ·          -  ·          -  ·      36849  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  StableAndVariableTokensHelper         ·  setOracleBorrowRates             ·          -  ·          -  ·     149397  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  StableAndVariableTokensHelper         ·  setOracleOwnership               ·          -  ·          -  ·      35516  ·            2  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  Treasury                              ·  buybackRnbw                      ·          -  ·          -  ·     358844  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  Treasury                              ·  sendToVestingContract            ·          -  ·          -  ·      44369  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  WETHGateway                           ·  authorizeLendingPool             ·          -  ·          -  ·      51538  ·            1  ·          -  │
·········································|···································|·············|·············|·············|···············|··············
|  Deployments                                                               ·                                         ·  % of limit   ·             │
·············································································|·············|·············|·············|···············|··············
|  AaveOracle                                                                ·          -  ·          -  ·     814172  ·        6.5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  AaveProtocolDataProvider                                                  ·          -  ·          -  ·    1555866  ·       12.5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  AToken                                                                    ·          -  ·          -  ·    2325625  ·       18.7 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  ATokensAndRatesHelper                                                     ·          -  ·          -  ·    3792708  ·       30.5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  CurveFactoryMock                                                          ·          -  ·          -  ·     179087  ·        1.4 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  CurveMock                                                                 ·          -  ·          -  ·     323519  ·        2.6 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  DefaultReserveInterestRateStrategy                                        ·          -  ·          -  ·     790705  ·        6.4 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  DelegationAwareAToken                                                     ·          -  ·          -  ·    2437054  ·       19.6 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  FlashLiquidationAdapter                                                   ·          -  ·          -  ·    2402171  ·       19.3 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  GenericLogic                                                              ·          -  ·          -  ·     851914  ·        6.8 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingPool                                                               ·          -  ·          -  ·    4797964  ·       38.5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProvider                                              ·          -  ·          -  ·    1604832  ·       12.9 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingPoolAddressesProviderRegistry                                      ·          -  ·          -  ·     543411  ·        4.4 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingPoolCollateralManager                                              ·          -  ·          -  ·    2372785  ·       19.1 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingPoolConfigurator                                                   ·          -  ·          -  ·    3484625  ·         28 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  LendingRateOracle                                                         ·          -  ·          -  ·     345146  ·        2.8 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  MintableERC20                                                             ·     748708  ·     748732  ·     748726  ·          6 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  MockAggregator                                                            ·     111522  ·     111546  ·     111539  ·        0.9 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  MockEmissionManager                                                       ·          -  ·          -  ·     360267  ·        2.9 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  MockFlashLoanReceiver                                                     ·          -  ·          -  ·     590093  ·        4.7 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  MockUniswapV2Router02                                                     ·          -  ·          -  ·     819241  ·        6.6 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  PriceOracle                                                               ·          -  ·          -  ·     153505  ·        1.2 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  ReserveLogic                                                              ·          -  ·          -  ·     176615  ·        1.4 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  RnbwIncentivesController                                                  ·          -  ·          -  ·    1143673  ·        9.2 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  RnbwMock                                                                  ·          -  ·          -  ·     986100  ·        7.9 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  StableAndVariableTokensHelper                                             ·          -  ·          -  ·    3699874  ·       29.7 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  StableDebtToken                                                           ·          -  ·          -  ·    1716647  ·       13.8 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  Treasury                                                                  ·          -  ·          -  ·     964133  ·        7.7 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  UniswapLiquiditySwapAdapter                                               ·          -  ·          -  ·    3053726  ·       24.5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  UniswapMock                                                               ·          -  ·          -  ·     266919  ·        2.1 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  UniswapRepayAdapter                                                       ·          -  ·          -  ·    2897716  ·       23.3 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  ValidationLogic                                                           ·          -  ·          -  ·    1838521  ·       14.8 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  VariableDebtToken                                                         ·          -  ·          -  ·    1421292  ·       11.4 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  VestingContractMock                                                       ·          -  ·          -  ·    1135439  ·        9.1 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  WalletBalanceProvider                                                     ·          -  ·          -  ·     627128  ·          5 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  WETH9Mocked                                                               ·          -  ·          -  ·     538638  ·        4.3 %  ·          -  │
·············································································|·············|·············|·············|···············|··············
|  WETHGateway                                                               ·          -  ·          -  ·    1217607  ·        9.8 %  ·          -  │
·----------------------------------------------------------------------------|-------------|-------------|-------------|---------------|-------------·

  2 passing (19s)

License

This report falls under the terms described in the included LICENSE.

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.4.1/highlight.min.js"></script> <script>hljs.initHighlightingOnLoad();</script> <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/solidity.min.js"></script> <script type="text/javascript"> hljs.registerLanguage('solidity', window.hljsDefineSolidity); hljs.initHighlightingOnLoad(); </script>