diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..e2afc20d --- /dev/null +++ b/.envrc @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +PROJECT_DIR="$(pwd)" + +PATH_add ${PROJECT_DIR} +PATH_add ${PROJECT_DIR}/node_modules/.bin diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..cd5f4a0e --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "extends": [ + "eslint:recommended", + "prettier" + ], + "env": { + "node": true, + "es6": true, + "commonjs": true, + "mocha": true, + "truffle/globals": true + }, + "parserOptions": { + "ecmaVersion": 2018 + }, + "plugins": [ + "truffle" + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index a56ca6cb..a595f181 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ node_modules /build .etherlime-store /localDeploy +/run # Secrets .secret @@ -21,8 +22,8 @@ node_modules *.ipr .idea/ -#Test Coverage +# Test Coverage coverage* -#Personal Preferences +# Personal Preferences .vscode \ No newline at end of file diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..ea711f11 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +10.23.0 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..6b8acc94 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,25 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "printWidth": 80, + "tabWidth": 4, + "useTabs": false, + "singleQuote": false, + "bracketSpacing": false, + "explicitTypes": "always" + } + }, + { + "files": "*.js", + "options": { + "printWidth": 80, + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "bracketSpacing": false + } + } + ] +} \ No newline at end of file diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 00000000..fbafd6b6 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.2 \ No newline at end of file diff --git a/.solcover.js b/.solcover.js index 65e7e0c6..2f0ab8f7 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,40 +1,16 @@ +const fs = require('fs'); + +const privateKeys = + JSON.parse(fs.readFileSync('config/accounts.json'))["private_keys"] +const accounts = Object.entries(privateKeys) + .map(entry => ({ + secretKey: `0x${entry[1]}`, + balance: '0x8ac7230489e80000' + })) + module.exports = { port: 8555, testCommand: 'mocha --timeout 5000', measureStatementCoverage: false, - providerOptions: { - //Default Accounts with preminted 10ETH - accounts: [ - { secretKey: '0x7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0x2030b463177db2da82908ef90fa55ddfcef56e8183caf60db464bc398e736e6f', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0x62ecd49c4ccb41a70ad46532aed63cf815de15864bc415c87d507afd6a5e8da2', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0xf473040b1a83739a9c7cc1f5719fab0f5bf178f83314d98557c58aae1910e03a', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0x823d590ed2cb5e8493bb0efc834771c1cde36f9fc49b9fe3620ebd0754ad6ea2', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0xd6d710943471e4c37ceb787857e7a2b41ca57f9cb4307ee9a9b21436a8e709c3', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0x187bb12e927c1652377405f81d93ce948a593f7d66cfba383ee761858b05921a', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0xf41486fdb04505e7966c8720a353ed92ce0d6830f8a5e915fbde735106a06d25', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0x6ca40ba4cca775643398385022264c0c414da1abd21d08d9e7136796a520a543', - balance: "0x8ac7230489e80000" - }, - { secretKey: '0xfac0bc9325ad342033afe956e83f0bf8f1e863c1c3e956bc75d66961fe4cd186', - balance: "0x8ac7230489e80000" - }, - ] - } -}; \ No newline at end of file + providerOptions: { accounts } +}; diff --git a/.solhint.json b/.solhint.json new file mode 100644 index 00000000..5207f68c --- /dev/null +++ b/.solhint.json @@ -0,0 +1,15 @@ +{ + "extends": "solhint:recommended", + "rules": { + "compiler-version": [ + "error", + "^0.6.6" + ], + "reason-string": [ + "warn", + { + "maxLength": 64 + } + ] + } +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 0375ea9e..797c4121 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,3 @@ - # Contributor Covenant Code of Conduct ## Our Pledge diff --git a/Gemfile b/Gemfile new file mode 100644 index 00000000..e5517651 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org' + +gem 'rake', '~> 13.0' +gem 'random-port', '~> 0.5' +gem 'childprocess', '~> 4.0' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 00000000..923be140 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,17 @@ +GEM + remote: https://rubygems.org/ + specs: + childprocess (4.0.0) + rake (13.0.3) + random-port (0.5.1) + +PLATFORMS + x86_64-darwin-19 + +DEPENDENCIES + childprocess (~> 4.0) + rake (~> 13.0) + random-port (~> 0.5) + +BUNDLED WITH + 2.2.6 diff --git a/README.md b/README.md index 12847220..ae38cb27 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,162 @@ -# Core prototype -Code repository for Boson Protocol smart contracts. The description of the contracts and process can be found in [doc_contracts.md](doc_contracts.md). +[![banner](docs/assets/banner.png)](https://bosonprotocol.io) -## Install -Install dependencies from project root folder: +

Boson Protocol Contracts

+ +Smart contracts for Boson Protocol. + +**Table of Contents** + +- [Local Development](#local-development) +- [Testing](#testing) +- [Code Linting](#code-linting) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [License](#license) + +## Local Development + +### Prerequisites + +For local development of the contracts, your development machine will need a few +tools installed. + +At a minimum, you'll need: +* Node (10.23.0) +* NPM (> 6) +* Ruby (2.7.2) +* Bundler (> 2) + +For instructions on how to get set up with these specific versions: +* See the [OS X guide](docs/setup/osx.md) if you are on a Mac. +* See the [Linux guide](docs/setup/linux.md) if you use a Linux distribution. + +### Running the build + +We have a fully automated local build process to check that your changes are +good to be merged. To run the build: + +```shell script +./go +```` + +By default, the build process fetches all dependencies, compiles, lints, +formats and tests the codebase. There are also tasks for each step. This and +subsequent sections provide more details of each of the tasks. + +To fetch dependencies: + +```shell script +./go dependencies:install ``` - $ npm install @openzeppelin/contracts truffle-assertions ethers + +To compile the contracts: + +```shell script +./go contracts:compile ``` -Migrations are using HDWalletProvider, install it if you need it: +## Testing + +### Unit Tests + +All contracts are thoroughly unit tested using +[Truffle's JavaScript testing](https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-javascript) +support. + +To run the unit tests: + +```shell script +./go tests:unit ``` - $ npm install @truffle/hdwallet-provider + +By default, the build system automates starting and stopping +[Ganache](https://www.trufflesuite.com/docs/ganache/overview) on a free port in +the background ready for each test run. + +If instead, you want to run the tests against an existing node, Ganache or +otherwise, create a JSON file creating accounts in the same format as +`config/accounts.json` and execute: + +```shell script +./go "tests:unit[,]" ``` -## Contracts initialization -[Migrations script](./migrations/2_deploy_contracts.js) for Truffle also does this initialization: -- ERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true') -- ERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address) -- VoucherKernel.setBosonRouterAddress(bosonRouter.address) +### Coverage + +We use [solidity-coverage](https://github.com/sc-forks/solidity-coverage) to +provide test coverage reports. + +To check the test coverage: + +```shell script +./go tests:coverage +``` + +`solidity-coverage` runs its own instance of Ganache internally, as well as +instrumenting contracts before running. + +### Interaction Tests + +To run the interaction tests, follow the instructions in the +[interaction tests README.md](testUserInteractions/README.md). + +## Code Linting + +Both the contracts themselves and the tests are linted and formatted as part of +the build process. + +For the contracts, we use: +* [solhint](https://protofire.github.io/solhint/) for linting +* [prettier-solidity](https://github.com/prettier-solidity/prettier-plugin-solidity) + for formatting + +For the tests, we use: +* [eslint](https://eslint.org/) for linting +* [prettier](https://prettier.io/) for formatting + +To lint the contracts: + +```shell script +./go contracts:lint +``` + +This will check if the linter is satisfied. If instead you want to attempt to +automatically fix any linting issues: + +```shell script +./go contracts:lint_fix +``` + +To check the formatting of the contracts: + +```shell script +./go contracts:format +``` + +To automatically fix formatting issues: + +```shell script +./go contracts:format_fix +``` + +Similarly, for the tests, to perform the same tasks: + +```shell script +./go tests:lint +./go tests:lint_fix +./go tests:format +./go tests:format_fix +``` -## Deployed contracts -Contract are deployed on Kovan testnet at addresses: -ERC1155ERC721: 0xF3aA8eB3812303F6c86c136557bC23E48d634B58 -VoucherKernel: 0x1806312211bd1521430C953683038d6263580feE -Cashier: 0xaaf749c8e6e37b51410F1810ADcAEED18d0C166F -The frontend is currently pointing to Kovan deployment. +## Documentation -Contract are also deployed on Ropsten testnet at addresses: -ERC1155ERC721: 0xe7028d66222aD1AfEB0098956347A6284443bd16 -VoucherKernel: 0xa93f95bf0039CE30957b77A6638e2e273598D576 -Cashier: 0x014b8baF57bA77FaE23075aa93c2B768eeb440bD +For an overview of the contracts and their responsibilities, see +[Overview](docs/contracts/overview.md). -## Progress -See the project board at [https://github.com/bosonprotocol/bsn-core-prototype/projects/2](https://github.com/bosonprotocol/bsn-core-prototype/projects/2). +## Contributing +TODO: Add contribution notes. -## Coverage -Test coverage is executed by running the following command: +## License -``` -npm run coverage \ No newline at end of file +Licensed under [LGPL v3](LICENSE). diff --git a/Rakefile b/Rakefile new file mode 100644 index 00000000..75bfe49e --- /dev/null +++ b/Rakefile @@ -0,0 +1,127 @@ +require_relative 'lib/ganache' + +task :default => [ + :"contracts:compile", + :"contracts:lint_fix", + :"contracts:format_fix", + :"tests:lint_fix", + :"tests:format_fix", + :"tests:unit" +] + +namespace :ganache do + desc "Start ganache on provided port, default 8545" + task :start, [:port] => [:'dependencies:install'] do |_, args| + args.with_defaults(port: 8545) + + puts "Starting ganache on port #{args.port}..." + ganache = Ganache.builder + .on_port(args.port) + .allowing_unlimited_contract_size + .build + ganache.start + puts "Started ganache on port #{args.port}" + puts " - with pidfile at #{ganache.pidfile}" + puts " - with account keys file at #{ganache.account_keys_file}" + end + + desc "Stop ganache on provided port, default 8545" + task :stop, [:port] => [:'dependencies:install'] do |_, args| + args.with_defaults(port: 8545) + + puts "Stopping ganache on port #{args.port}..." + ganache = Ganache.builder + .on_port(args.port) + .build + ganache.stop + puts "Stopped ganache on port #{args.port}" + end +end + +namespace :dependencies do + desc "Install all dependencies" + task :install do + sh('npm', 'install') + end +end + +namespace :contracts do + desc "Compile all contracts" + task :compile => [:'dependencies:install'] do + sh('npm', 'run', 'contracts:compile') + end + + desc "Lint all contracts" + task :lint => [:'dependencies:install'] do + sh('npm', 'run', 'contracts:lint') + end + + desc "Lint & fix all contracts" + task :lint_fix => [:'dependencies:install'] do + sh('npm', 'run', 'contracts:lint-fix') + end + + desc "Format all contracts" + task :format => [:'dependencies:install'] do + sh('npm', 'run', 'contracts:format') + end + + desc "Format & fix all contracts" + task :format_fix => [:'dependencies:install'] do + sh('npm', 'run', 'contracts:format-fix') + end +end + +namespace :tests do + desc "Lint all tests" + task :lint => [:'dependencies:install'] do + sh('npm', 'run', 'tests:lint') + end + + desc "Lint & fix all tests" + task :lint_fix => [:'dependencies:install'] do + sh('npm', 'run', 'tests:lint-fix') + end + + desc "Format all test files" + task :format => [:'dependencies:install'] do + sh('npm', 'run', 'tests:format') + end + + desc "Format & fix all test files" + task :format_fix => [:'dependencies:install'] do + sh('npm', 'run', 'tests:format-fix') + end + + desc "Run all contract unit tests" + task :unit, [:port, :account_keys_file] => + [:'dependencies:install'] do |_, args| + run_unit_tests = lambda do |port, account_keys_file| + sh({ + "HOST" => "127.0.0.1", + "PORT" => "#{port}", + "ACCOUNT_KEYS_FILE" => "#{account_keys_file}" + }, 'npm', 'run', 'tests:unit') + end + + if args.port + puts "Running unit tests against node listening on #{args.port}..." + run_unit_tests.call( + args.port, + args.account_keys_file || 'config/accounts.json') + else + puts "Running unit tests against node listening on random available " + + "port..." + Ganache.on_available_port( + allow_unlimited_contract_size: true) do |ganache| + run_unit_tests.call(ganache.port, ganache.account_keys_file) + end + end + end + + desc "Run test coverage for contract unit tests" + task :coverage => [:'dependencies:install'] do + puts "Running test coverage for contract unit tests..." + sh('npm', 'run', 'tests:coverage') + end +end diff --git a/config/accounts.json b/config/accounts.json new file mode 100644 index 00000000..8e9ca574 --- /dev/null +++ b/config/accounts.json @@ -0,0 +1,14 @@ +{ + "private_keys": { + "0xd9995bae12fee327256ffec1e3184d492bd94c31": "7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8", + "0xd4fa489eacc52ba59438993f37be9fcc20090e39": "2030b463177db2da82908ef90fa55ddfcef56e8183caf60db464bc398e736e6f", + "0x760bf27cd45036a6c486802d30b5d90cffbe31fe": "62ecd49c4ccb41a70ad46532aed63cf815de15864bc415c87d507afd6a5e8da2", + "0x56a32fff5e5a8b40d6a21538579fb8922df5258c": "f473040b1a83739a9c7cc1f5719fab0f5bf178f83314d98557c58aae1910e03a", + "0xfec44e15328b7d1d8885a8226b0858964358f1d6": "823d590ed2cb5e8493bb0efc834771c1cde36f9fc49b9fe3620ebd0754ad6ea2", + "0xda8a06f1c910cab18ad187be1faa2b8606c2ec86": "d6d710943471e4c37ceb787857e7a2b41ca57f9cb4307ee9a9b21436a8e709c3", + "0x8199de05654e9afa5c081bce38f140082c9a7733": "187bb12e927c1652377405f81d93ce948a593f7d66cfba383ee761858b05921a", + "0x28bf45680ca598708e5cdacc1414fcac04a3f1ed": "f41486fdb04505e7966c8720a353ed92ce0d6830f8a5e915fbde735106a06d25", + "0xf0508f89e26bd6b00f66a9d467678c7ed16a3c5a": "6ca40ba4cca775643398385022264c0c414da1abd21d08d9e7136796a520a543", + "0x87e0ED760fb316eeb94Bd9cF23D1d2BE87aCe3d8": "fac0bc9325ad342033afe956e83f0bf8f1e863c1c3e956bc75d66961fe4cd186" + } +} diff --git a/contracts/BosonRouter.sol b/contracts/BosonRouter.sol index b448dc6e..236e610a 100644 --- a/contracts/BosonRouter.sol +++ b/contracts/BosonRouter.sol @@ -7,7 +7,7 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/Address.sol"; import "./IVoucherKernel.sol"; -import "./usingHelpers.sol"; +import "./UsingHelpers.sol"; import "./IERC20WithPermit.sol"; import "./ERC1155ERC721.sol"; import "./IFundLimitsOracle.sol"; @@ -16,14 +16,18 @@ import "./ICashier.sol"; /** * @title Contract for managing funds - * @dev Warning: the contract hasn't been audited yet! * Roughly following OpenZeppelin's Escrow at https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/payment/ */ -contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, Ownable - { +contract BosonRouter is + IBosonRouter, + UsingHelpers, + Pausable, + ReentrancyGuard, + Ownable +{ using Address for address payable; - using SafeMath for uint; - + using SafeMath for uint256; + address public cashierAddress; address public voucherKernel; address public tokensContractAddress; @@ -35,11 +39,8 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O uint256 _quantity, uint8 _paymentType ); - - event LogTokenContractSet( - address _newTokenContract, - address _triggeredBy - ); + + event LogTokenContractSet(address _newTokenContract, address _triggeredBy); modifier notZeroAddress(address tokenAddress) { require(tokenAddress != address(0), "INVALID_TOKEN_ADDRESS"); @@ -50,13 +51,25 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O require(msg.sender == tokensContractAddress, "UNAUTHORIZED_TK"); _; } - - function notAboveETHLimit(uint256 value) internal view{ - require(value <= IFundLimitsOracle(fundLimitsOracle).getETHLimit(), "VALUE_ABOVE_ETH_LIMIT"); + + function notAboveETHLimit(uint256 value) internal view { + require( + value <= IFundLimitsOracle(fundLimitsOracle).getETHLimit(), + "VALUE_ABOVE_ETH_LIMIT" + ); } - function notAboveTokenLimit(address _tokenAddress, uint256 value) internal view{ - require(value <= IFundLimitsOracle(fundLimitsOracle).getTokenLimit(_tokenAddress), "VALUE_ABOVE_TKN_LIMIT"); + function notAboveTokenLimit(address _tokenAddress, uint256 value) + internal + view + { + require( + value <= + IFundLimitsOracle(fundLimitsOracle).getTokenLimit( + _tokenAddress + ), + "VALUE_ABOVE_TKN_LIMIT" + ); } constructor( @@ -64,21 +77,18 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O address _tokensContractAddress, address _fundLimitsOracle, address _cashierAddress - ) - public - { + ) public { voucherKernel = _voucherKernel; tokensContractAddress = _tokensContractAddress; fundLimitsOracle = _fundLimitsOracle; cashierAddress = _cashierAddress; } - /** - * @notice Pause the Cashier && the Voucher Kernel contracts in case of emergency. - * All functions related to creating new batch, requestVoucher or withdraw will be paused, hence cannot be executed. - * There is special function for withdrawing funds if contract is paused. - */ + * @notice Pause the Cashier && the Voucher Kernel contracts in case of emergency. + * All functions related to creating new batch, requestVoucher or withdraw will be paused, hence cannot be executed. + * There is special function for withdrawing funds if contract is paused. + */ function pause() external override onlyOwner { _pause(); IVoucherKernel(voucherKernel).pause(); @@ -86,14 +96,14 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O } /** - * @notice Unpause the Cashier && the Voucher Kernel contracts. - * All functions related to creating new batch, requestVoucher or withdraw will be unpaused. - */ + * @notice Unpause the Cashier && the Voucher Kernel contracts. + * All functions related to creating new batch, requestVoucher or withdraw will be unpaused. + */ function unpause() external override onlyOwner { _unpause(); IVoucherKernel(voucherKernel).unpause(); ICashier(cashierAddress).unpause(); - } + } /** * @notice Issuer/Seller offers promises as supply tokens and needs to escrow the deposit @@ -109,38 +119,55 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O uint256 _depositBu = metadata[4]; uint256 _quantity = metadata[5]; */ - function requestCreateOrder_ETH_ETH(uint256[] calldata metadata) + function requestCreateOrderETHETH(uint256[] calldata metadata) external payable override whenNotPaused { - notAboveETHLimit(metadata[2]); + notAboveETHLimit(metadata[2]); notAboveETHLimit(metadata[3]); notAboveETHLimit(metadata[4]); - require(metadata[3].mul(metadata[5]) == msg.value, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - - uint256 tokenIdSupply = IVoucherKernel(voucherKernel).createTokenSupplyID(msg.sender, metadata[0], metadata[1], metadata[2], metadata[3], metadata[4], metadata[5]); - - IVoucherKernel(voucherKernel).createPaymentMethod(tokenIdSupply, ETH_ETH, address(0), address(0)); + require(metadata[3].mul(metadata[5]) == msg.value, "INCORRECT_FUNDS"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + uint256 tokenIdSupply = + IVoucherKernel(voucherKernel).createTokenSupplyID( + msg.sender, + metadata[0], + metadata[1], + metadata[2], + metadata[3], + metadata[4], + metadata[5] + ); + + IVoucherKernel(voucherKernel).createPaymentMethod( + tokenIdSupply, + ETHETH, + address(0), + address(0) + ); //checks //(i) this is for separate promise allocation, not in prototype //uint256 depositSe = IVoucherKernel(voucherKernel).getPromiseDepositSe(promiseId); //require(depositSe * _quantity == weiReceived, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) //(ii) prototype check - - + //record funds in escrow ... uint256 amount = ICashier(cashierAddress).getEscrowAmount(msg.sender); - ICashier(cashierAddress).updateEscrowAmount(msg.sender, amount.add(msg.value)); + ICashier(cashierAddress).updateEscrowAmount( + msg.sender, + amount.add(msg.value) + ); require(payable(cashierAddress).send(msg.value)); - emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], ETH_ETH); + emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], ETHETH); } - function requestCreateOrder_TKN_TKN_WithPermit( + function requestCreateOrderTKNTKNWithPermit( address _tokenPriceAddress, address _tokenDepositAddress, uint256 _tokensSent, @@ -149,31 +176,58 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O bytes32 r, bytes32 s, uint256[] calldata metadata - ) - notZeroAddress(_tokenPriceAddress) - notZeroAddress(_tokenDepositAddress) + ) external override + notZeroAddress(_tokenPriceAddress) + notZeroAddress(_tokenDepositAddress) whenNotPaused { notAboveTokenLimit(_tokenPriceAddress, metadata[2]); notAboveTokenLimit(_tokenDepositAddress, metadata[3]); notAboveTokenLimit(_tokenDepositAddress, metadata[4]); - require(metadata[3].mul(metadata[5]) == _tokensSent, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - - IERC20WithPermit(_tokenDepositAddress).permit(msg.sender, address(this), _tokensSent, deadline, v, r, s); - - uint256 tokenIdSupply = IVoucherKernel(voucherKernel).createTokenSupplyID(msg.sender, metadata[0], metadata[1], metadata[2], metadata[3], metadata[4], metadata[5]); - - IVoucherKernel(voucherKernel).createPaymentMethod(tokenIdSupply, TKN_TKN, _tokenPriceAddress, _tokenDepositAddress); - - IERC20WithPermit(_tokenDepositAddress).transferFrom(msg.sender, address(cashierAddress), _tokensSent); - - emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], TKN_TKN); + require(metadata[3].mul(metadata[5]) == _tokensSent, "INCORRECT_FUNDS"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + IERC20WithPermit(_tokenDepositAddress).permit( + msg.sender, + address(this), + _tokensSent, + deadline, + v, + r, + s + ); + + uint256 tokenIdSupply = + IVoucherKernel(voucherKernel).createTokenSupplyID( + msg.sender, + metadata[0], + metadata[1], + metadata[2], + metadata[3], + metadata[4], + metadata[5] + ); + + IVoucherKernel(voucherKernel).createPaymentMethod( + tokenIdSupply, + TKNTKN, + _tokenPriceAddress, + _tokenDepositAddress + ); + + IERC20WithPermit(_tokenDepositAddress).transferFrom( + msg.sender, + address(cashierAddress), + _tokensSent + ); + + emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], TKNTKN); } - function requestCreateOrder_ETH_TKN_WithPermit( + function requestCreateOrderETHTKNWithPermit( address _tokenDepositAddress, uint256 _tokensSent, uint256 deadline, @@ -181,62 +235,102 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O bytes32 r, bytes32 s, uint256[] calldata metadata - ) - notZeroAddress(_tokenDepositAddress) - external - override - whenNotPaused - { - notAboveETHLimit(metadata[2]); + ) external override notZeroAddress(_tokenDepositAddress) whenNotPaused { + notAboveETHLimit(metadata[2]); notAboveTokenLimit(_tokenDepositAddress, metadata[3]); notAboveTokenLimit(_tokenDepositAddress, metadata[4]); - require(metadata[3].mul(metadata[5]) == _tokensSent, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - - IERC20WithPermit(_tokenDepositAddress).permit(msg.sender, address(this), _tokensSent, deadline, v, r, s); - - uint256 tokenIdSupply = IVoucherKernel(voucherKernel).createTokenSupplyID(msg.sender, metadata[0], metadata[1], metadata[2], metadata[3], metadata[4], metadata[5]); - - IVoucherKernel(voucherKernel).createPaymentMethod(tokenIdSupply, ETH_TKN, address(0), _tokenDepositAddress); - - IERC20WithPermit(_tokenDepositAddress).transferFrom(msg.sender, address(cashierAddress), _tokensSent); - - emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], ETH_TKN); + require(metadata[3].mul(metadata[5]) == _tokensSent, "INCORRECT_FUNDS"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + IERC20WithPermit(_tokenDepositAddress).permit( + msg.sender, + address(this), + _tokensSent, + deadline, + v, + r, + s + ); + + uint256 tokenIdSupply = + IVoucherKernel(voucherKernel).createTokenSupplyID( + msg.sender, + metadata[0], + metadata[1], + metadata[2], + metadata[3], + metadata[4], + metadata[5] + ); + + IVoucherKernel(voucherKernel).createPaymentMethod( + tokenIdSupply, + ETHTKN, + address(0), + _tokenDepositAddress + ); + + IERC20WithPermit(_tokenDepositAddress).transferFrom( + msg.sender, + address(cashierAddress), + _tokensSent + ); + + emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], ETHTKN); } - function requestCreateOrder_TKN_ETH( + function requestCreateOrderTKNETH( address _tokenPriceAddress, uint256[] calldata metadata - ) - notZeroAddress(_tokenPriceAddress) + ) external payable override + notZeroAddress(_tokenPriceAddress) whenNotPaused { notAboveTokenLimit(_tokenPriceAddress, metadata[2]); notAboveETHLimit(metadata[3]); notAboveETHLimit(metadata[4]); - require(metadata[3].mul(metadata[5]) == msg.value, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - - uint256 tokenIdSupply = IVoucherKernel(voucherKernel).createTokenSupplyID(msg.sender, metadata[0], metadata[1], metadata[2], metadata[3], metadata[4], metadata[5]); - IVoucherKernel(voucherKernel).createPaymentMethod(tokenIdSupply, TKN_ETH, _tokenPriceAddress, address(0)); + require(metadata[3].mul(metadata[5]) == msg.value, "INCORRECT_FUNDS"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + uint256 tokenIdSupply = + IVoucherKernel(voucherKernel).createTokenSupplyID( + msg.sender, + metadata[0], + metadata[1], + metadata[2], + metadata[3], + metadata[4], + metadata[5] + ); + IVoucherKernel(voucherKernel).createPaymentMethod( + tokenIdSupply, + TKNETH, + _tokenPriceAddress, + address(0) + ); uint256 amount = ICashier(cashierAddress).getEscrowAmount(msg.sender); - ICashier(cashierAddress).updateEscrowAmount(msg.sender, amount.add(msg.value)); + ICashier(cashierAddress).updateEscrowAmount( + msg.sender, + amount.add(msg.value) + ); require(payable(cashierAddress).send(msg.value)); - emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], TKN_ETH); + emit LogOrderCreated(tokenIdSupply, msg.sender, metadata[5], TKNETH); } - + /** * @notice Consumer requests/buys a voucher by filling an order and receiving a Voucher Token in return * @param _tokenIdSupply ID of the supply token * @param _issuer Address of the issuer of the supply token */ - function requestVoucher_ETH_ETH(uint256 _tokenIdSupply, address _issuer) + function requestVoucherETHETH(uint256 _tokenIdSupply, address _issuer) external payable override @@ -246,285 +340,409 @@ contract BosonRouter is IBosonRouter, usingHelpers, Pausable, ReentrancyGuard, O uint256 weiReceived = msg.value; //checks - (uint256 price, uint256 depositSe, uint256 depositBu) = IVoucherKernel(voucherKernel).getOrderCosts(_tokenIdSupply); - require(price.add(depositBu) == weiReceived, "INCORRECT_FUNDS"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + (uint256 price, , uint256 depositBu) = + IVoucherKernel(voucherKernel).getOrderCosts(_tokenIdSupply); + require(price.add(depositBu) == weiReceived, "INCORRECT_FUNDS"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - IVoucherKernel(voucherKernel).fillOrder(_tokenIdSupply, _issuer, msg.sender); + IVoucherKernel(voucherKernel).fillOrder( + _tokenIdSupply, + _issuer, + msg.sender + ); //record funds in escrow ... uint256 amount = ICashier(cashierAddress).getEscrowAmount(msg.sender); - ICashier(cashierAddress).updateEscrowAmount(msg.sender, amount.add(weiReceived)); + ICashier(cashierAddress).updateEscrowAmount( + msg.sender, + amount.add(weiReceived) + ); require(payable(cashierAddress).send(msg.value)); } - - function requestVoucher_TKN_TKN_WithPermit( - uint256 _tokenIdSupply, + + function requestVoucherTKNTKNWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensSent, uint256 deadline, - uint8 vPrice, bytes32 rPrice, bytes32 sPrice, // tokenPrice - uint8 vDeposit, bytes32 rDeposit, bytes32 sDeposit // tokenDeposits - ) - external - override - nonReentrant - whenNotPaused - { - + uint8 vPrice, + bytes32 rPrice, + bytes32 sPrice, // tokenPrice + uint8 vDeposit, + bytes32 rDeposit, + bytes32 sDeposit // tokenDeposits + ) external override nonReentrant whenNotPaused { //checks - (uint256 price, uint256 depositBu) = IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); + (uint256 price, uint256 depositBu) = + IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); require(_tokensSent.sub(depositBu) == price, "INCORRECT_FUNDS"); - address tokenPriceAddress = IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); - address tokenDepositAddress = IVoucherKernel(voucherKernel).getVoucherDepositToken(_tokenIdSupply); - - IERC20WithPermit(tokenPriceAddress).permit(msg.sender, address(this), price, deadline, vPrice, rPrice, sPrice); - IERC20WithPermit(tokenDepositAddress).permit(msg.sender, address(this), depositBu, deadline, vDeposit, rDeposit, sDeposit); - - IVoucherKernel(voucherKernel).fillOrder(_tokenIdSupply, _issuer, msg.sender); - - IERC20WithPermit(tokenPriceAddress).transferFrom(msg.sender, address(cashierAddress), price); - IERC20WithPermit(tokenDepositAddress).transferFrom(msg.sender, address(cashierAddress), depositBu); + address tokenPriceAddress = + IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); + address tokenDepositAddress = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + _tokenIdSupply + ); + + IERC20WithPermit(tokenPriceAddress).permit( + msg.sender, + address(this), + price, + deadline, + vPrice, + rPrice, + sPrice + ); + IERC20WithPermit(tokenDepositAddress).permit( + msg.sender, + address(this), + depositBu, + deadline, + vDeposit, + rDeposit, + sDeposit + ); + + IVoucherKernel(voucherKernel).fillOrder( + _tokenIdSupply, + _issuer, + msg.sender + ); + + IERC20WithPermit(tokenPriceAddress).transferFrom( + msg.sender, + address(cashierAddress), + price + ); + IERC20WithPermit(tokenDepositAddress).transferFrom( + msg.sender, + address(cashierAddress), + depositBu + ); } - function requestVoucher_TKN_TKN_Same_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherTKNTKNSameWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensSent, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external - override - nonReentrant - whenNotPaused - { + uint8 v, + bytes32 r, + bytes32 s + ) external override nonReentrant whenNotPaused { //checks - (uint256 price, uint256 depositBu) = IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); + (uint256 price, uint256 depositBu) = + IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); require(_tokensSent.sub(depositBu) == price, "INCORRECT_FUNDS"); - address tokenPriceAddress = IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); - address tokenDepositAddress = IVoucherKernel(voucherKernel).getVoucherDepositToken(_tokenIdSupply); + address tokenPriceAddress = + IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); + address tokenDepositAddress = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + _tokenIdSupply + ); require(tokenPriceAddress == tokenDepositAddress, "INVALID_CALL"); - // If tokenPriceAddress && tokenPriceAddress are the same + // If tokenPriceAddress && tokenPriceAddress are the same // practically it's not of importance to each we are sending the funds - IERC20WithPermit(tokenPriceAddress).permit(msg.sender, address(this), _tokensSent, deadline, v, r, s); - - IVoucherKernel(voucherKernel).fillOrder(_tokenIdSupply, _issuer, msg.sender); - - IERC20WithPermit(tokenPriceAddress).transferFrom(msg.sender, address(cashierAddress), _tokensSent); + IERC20WithPermit(tokenPriceAddress).permit( + msg.sender, + address(this), + _tokensSent, + deadline, + v, + r, + s + ); + + IVoucherKernel(voucherKernel).fillOrder( + _tokenIdSupply, + _issuer, + msg.sender + ); + + IERC20WithPermit(tokenPriceAddress).transferFrom( + msg.sender, + address(cashierAddress), + _tokensSent + ); } - function requestVoucher_ETH_TKN_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherETHTKNWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensDeposit, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external - payable - override - nonReentrant - whenNotPaused - { - + uint8 v, + bytes32 r, + bytes32 s + ) external payable override nonReentrant whenNotPaused { //checks - (uint256 price, uint256 depositBu) = IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); - require(price == msg.value, "INCORRECT_PRICE"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - require(depositBu == _tokensDeposit, "INCORRECT_DE"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - - address tokenDepositAddress = IVoucherKernel(voucherKernel).getVoucherDepositToken(_tokenIdSupply); - IERC20WithPermit(tokenDepositAddress).permit(msg.sender, address(this), _tokensDeposit, deadline, v, r, s); - - IVoucherKernel(voucherKernel).fillOrder(_tokenIdSupply, _issuer, msg.sender); + (uint256 price, uint256 depositBu) = + IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); + require(price == msg.value, "INCORRECT_PRICE"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + require(depositBu == _tokensDeposit, "INCORRECT_DE"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + address tokenDepositAddress = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + _tokenIdSupply + ); + IERC20WithPermit(tokenDepositAddress).permit( + msg.sender, + address(this), + _tokensDeposit, + deadline, + v, + r, + s + ); + + IVoucherKernel(voucherKernel).fillOrder( + _tokenIdSupply, + _issuer, + msg.sender + ); + + IERC20WithPermit(tokenDepositAddress).transferFrom( + msg.sender, + address(cashierAddress), + _tokensDeposit + ); - IERC20WithPermit(tokenDepositAddress).transferFrom(msg.sender, address(cashierAddress), _tokensDeposit); - - //record funds in escrow ... + //record funds in escrow ... uint256 amount = ICashier(cashierAddress).getEscrowAmount(msg.sender); - ICashier(cashierAddress).updateEscrowAmount(msg.sender, amount.add(msg.value)); + ICashier(cashierAddress).updateEscrowAmount( + msg.sender, + amount.add(msg.value) + ); require(payable(cashierAddress).send(msg.value)); } - function requestVoucher_TKN_ETH_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherTKNETHWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensPrice, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external - payable - override - nonReentrant - whenNotPaused - { - + uint8 v, + bytes32 r, + bytes32 s + ) external payable override nonReentrant whenNotPaused { //checks - (uint256 price, uint256 depositBu) = IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); - require(price == _tokensPrice, "INCORRECT_PRICE"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) - require(depositBu == msg.value, "INCORRECT_DE"); //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + (uint256 price, uint256 depositBu) = + IVoucherKernel(voucherKernel).getBuyerOrderCosts(_tokenIdSupply); + require(price == _tokensPrice, "INCORRECT_PRICE"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + require(depositBu == msg.value, "INCORRECT_DE"); + //hex"54" FISSION.code(FISSION.Category.Finance, FISSION.Status.InsufficientFunds) + + address tokenPriceAddress = + IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); + IERC20WithPermit(tokenPriceAddress).permit( + msg.sender, + address(this), + price, + deadline, + v, + r, + s + ); + + IVoucherKernel(voucherKernel).fillOrder( + _tokenIdSupply, + _issuer, + msg.sender + ); + + IERC20WithPermit(tokenPriceAddress).transferFrom( + msg.sender, + address(cashierAddress), + price + ); - address tokenPriceAddress = IVoucherKernel(voucherKernel).getVoucherPriceToken(_tokenIdSupply); - IERC20WithPermit(tokenPriceAddress).permit(msg.sender, address(this), price, deadline, v, r, s); - - IVoucherKernel(voucherKernel).fillOrder(_tokenIdSupply, _issuer, msg.sender); - - IERC20WithPermit(tokenPriceAddress).transferFrom(msg.sender, address(cashierAddress), price); - - //record funds in escrow ... + //record funds in escrow ... uint256 amount = ICashier(cashierAddress).getEscrowAmount(msg.sender); - ICashier(cashierAddress).updateEscrowAmount(msg.sender, amount.add(msg.value)); + ICashier(cashierAddress).updateEscrowAmount( + msg.sender, + amount.add(msg.value) + ); require(payable(cashierAddress).send(msg.value)); } /** - * @notice Redemption of the vouchers promise - * @param _tokenIdVoucher ID of the voucher - */ - function redeem(uint256 _tokenIdVoucher) - external - override - { + * @notice Redemption of the vouchers promise + * @param _tokenIdVoucher ID of the voucher + */ + function redeem(uint256 _tokenIdVoucher) external override { IVoucherKernel(voucherKernel).redeem(_tokenIdVoucher, msg.sender); } /** - * @notice Refunding a voucher - * @param _tokenIdVoucher ID of the voucher - */ - function refund(uint256 _tokenIdVoucher) - external - override - { + * @notice Refunding a voucher + * @param _tokenIdVoucher ID of the voucher + */ + function refund(uint256 _tokenIdVoucher) external override { IVoucherKernel(voucherKernel).refund(_tokenIdVoucher, msg.sender); } /** - * @notice Issue a complain for a voucher - * @param _tokenIdVoucher ID of the voucher - */ - function complain(uint256 _tokenIdVoucher) - external - override - { + * @notice Issue a complain for a voucher + * @param _tokenIdVoucher ID of the voucher + */ + function complain(uint256 _tokenIdVoucher) external override { IVoucherKernel(voucherKernel).complain(_tokenIdVoucher, msg.sender); } /** - * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal - * @param _tokenIdVoucher ID of the voucher - */ - function cancelOrFault(uint256 _tokenIdVoucher) - external - override - { - IVoucherKernel(voucherKernel).cancelOrFault(_tokenIdVoucher, msg.sender); + * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal + * @param _tokenIdVoucher ID of the voucher + */ + function cancelOrFault(uint256 _tokenIdVoucher) external override { + IVoucherKernel(voucherKernel).cancelOrFault( + _tokenIdVoucher, + msg.sender + ); } /** - * @notice Hook which will be triggered when a _tokenIdVoucher will be transferred. Escrow funds should be allocated to the new owner. - * @param _from prev owner of the _tokenIdVoucher - * @param _to next owner of the _tokenIdVoucher - * @param _tokenIdVoucher _tokenIdVoucher that has been transferred - */ - function _onERC721Transfer(address _from, address _to, uint256 _tokenIdVoucher) - external - override - onlyTokensContract - { - uint256 tokenSupplyId = IVoucherKernel(voucherKernel).getIdSupplyFromVoucher(_tokenIdVoucher); - uint8 paymentType = IVoucherKernel(voucherKernel).getVoucherPaymentMethod(tokenSupplyId); - - (uint256 price, uint256 depositBu) = IVoucherKernel(voucherKernel).getBuyerOrderCosts(tokenSupplyId); - - if(paymentType == ETH_ETH) - { + * @notice Hook which will be triggered when a _tokenIdVoucher will be transferred. Escrow funds should be allocated to the new owner. + * @param _from prev owner of the _tokenIdVoucher + * @param _to next owner of the _tokenIdVoucher + * @param _tokenIdVoucher _tokenIdVoucher that has been transferred + */ + function _onERC721Transfer( + address _from, + address _to, + uint256 _tokenIdVoucher + ) external override onlyTokensContract { + uint256 tokenSupplyId = + IVoucherKernel(voucherKernel).getIdSupplyFromVoucher( + _tokenIdVoucher + ); + uint8 paymentType = + IVoucherKernel(voucherKernel).getVoucherPaymentMethod( + tokenSupplyId + ); + + (uint256 price, uint256 depositBu) = + IVoucherKernel(voucherKernel).getBuyerOrderCosts(tokenSupplyId); + + if (paymentType == ETHETH) { uint256 totalAmount = price.add(depositBu); uint256 amount = ICashier(cashierAddress).getEscrowAmount(_from); - ICashier(cashierAddress).updateEscrowAmount(_from, amount.sub(totalAmount)); + ICashier(cashierAddress).updateEscrowAmount( + _from, + amount.sub(totalAmount) + ); amount = ICashier(cashierAddress).getEscrowAmount(_to); - ICashier(cashierAddress).updateEscrowAmount(_to, amount.add(totalAmount)); + ICashier(cashierAddress).updateEscrowAmount( + _to, + amount.add(totalAmount) + ); } - if(paymentType == ETH_TKN) { + if (paymentType == ETHTKN) { uint256 amount = ICashier(cashierAddress).getEscrowAmount(_from); - ICashier(cashierAddress).updateEscrowAmount(_from, amount.sub(price)); + ICashier(cashierAddress).updateEscrowAmount( + _from, + amount.sub(price) + ); amount = ICashier(cashierAddress).getEscrowAmount(_to); ICashier(cashierAddress).updateEscrowAmount(_to, amount.add(price)); } - if(paymentType == TKN_ETH) { + if (paymentType == TKNETH) { uint256 amount = ICashier(cashierAddress).getEscrowAmount(_from); - ICashier(cashierAddress).updateEscrowAmount(_from, amount.sub(depositBu)); + ICashier(cashierAddress).updateEscrowAmount( + _from, + amount.sub(depositBu) + ); amount = ICashier(cashierAddress).getEscrowAmount(_to); - ICashier(cashierAddress).updateEscrowAmount(_to, amount.add(depositBu)); + ICashier(cashierAddress).updateEscrowAmount( + _to, + amount.add(depositBu) + ); } } - /** - * @notice Pre-validation when a transfer from the the Tokens contract is triggered. Only the whole supply is allowed for transfer, otherwise reverts. - * @param _from owner of the _tokenSupplyId - * @param _tokenSupplyId _tokenSupplyId which will be validated - * @param _value qty which is desired to be transferred - */ - function _beforeERC1155Transfer(address _from, uint256 _tokenSupplyId, uint256 _value) - external - view - override - onlyTokensContract - { - uint256 _tokenSupplyQty = IVoucherKernel(voucherKernel).getRemQtyForSupply(_tokenSupplyId, _from); + * @notice Pre-validation when a transfer from the the Tokens contract is triggered. Only the whole supply is allowed for transfer, otherwise reverts. + * @param _from owner of the _tokenSupplyId + * @param _tokenSupplyId _tokenSupplyId which will be validated + * @param _value qty which is desired to be transferred + */ + function _beforeERC1155Transfer( + address _from, + uint256 _tokenSupplyId, + uint256 _value + ) external view override onlyTokensContract { + uint256 _tokenSupplyQty = + IVoucherKernel(voucherKernel).getRemQtyForSupply( + _tokenSupplyId, + _from + ); require(_tokenSupplyQty == _value, "INVALID_QTY"); } /** - * @notice After the transfer happens the _tokenSupplyId should be updated in the promise. Escrow funds for the seller's deposits (If in ETH) should be allocated to the new owner as well. - * @param _from prev owner of the _tokenSupplyId - * @param _to nex owner of the _tokenSupplyId - * @param _tokenSupplyId _tokenSupplyId for transfer - * @param _value qty which has been transferred - */ - function _onERC1155Transfer(address _from, address _to, uint256 _tokenSupplyId, uint256 _value) - external - override - onlyTokensContract - { - uint8 paymentType = IVoucherKernel(voucherKernel).getVoucherPaymentMethod(_tokenSupplyId); - - if(paymentType == ETH_ETH || paymentType == TKN_ETH) { - uint256 depositSe = IVoucherKernel(voucherKernel).getSellerDeposit(_tokenSupplyId); + * @notice After the transfer happens the _tokenSupplyId should be updated in the promise. Escrow funds for the seller's deposits (If in ETH) should be allocated to the new owner as well. + * @param _from prev owner of the _tokenSupplyId + * @param _to nex owner of the _tokenSupplyId + * @param _tokenSupplyId _tokenSupplyId for transfer + * @param _value qty which has been transferred + */ + function _onERC1155Transfer( + address _from, + address _to, + uint256 _tokenSupplyId, + uint256 _value + ) external override onlyTokensContract { + uint8 paymentType = + IVoucherKernel(voucherKernel).getVoucherPaymentMethod( + _tokenSupplyId + ); + + if (paymentType == ETHETH || paymentType == TKNETH) { + uint256 depositSe = + IVoucherKernel(voucherKernel).getSellerDeposit(_tokenSupplyId); uint256 totalAmount = depositSe.mul(_value); uint256 amount = ICashier(cashierAddress).getEscrowAmount(_from); - ICashier(cashierAddress).updateEscrowAmount(_from, amount.sub(totalAmount)); + ICashier(cashierAddress).updateEscrowAmount( + _from, + amount.sub(totalAmount) + ); amount = ICashier(cashierAddress).getEscrowAmount(_to); - ICashier(cashierAddress).updateEscrowAmount(_to, amount.add(totalAmount)); + ICashier(cashierAddress).updateEscrowAmount( + _to, + amount.add(totalAmount) + ); } - IVoucherKernel(voucherKernel).setSupplyHolderOnTransfer(_tokenSupplyId, _to); + IVoucherKernel(voucherKernel).setSupplyHolderOnTransfer( + _tokenSupplyId, + _to + ); } // // // // // // // // - // UTILS - // // // // // // // // - + // UTILS + // // // // // // // // + /** * @notice Set the address of the ERC1155ERC721 contract * @param _tokensContractAddress The address of the ERC1155ERC721 contract - */ + */ function setTokenContractAddress(address _tokensContractAddress) external override diff --git a/contracts/BosonTokenDeposit.sol b/contracts/BosonTokenDeposit.sol index de4f15ae..bb8109ab 100644 --- a/contracts/BosonTokenDeposit.sol +++ b/contracts/BosonTokenDeposit.sol @@ -1,23 +1,23 @@ // SPDX-License-Identifier: LGPL-3.0-or-later pragma solidity >=0.6.6 <0.7.0; + import "./ERC20WithPermit.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /** -* @notice This contract is only used for, while deploying on rinkeby with verifying contracts, -so that we have 2 distinguished contracts concerning tokens for the price of the products, and for the deposits. -Will not be used while deploying on prod. -*/ + * @notice This contract is only used for, while deploying on rinkeby with verifying contracts, + * so that we have 2 distinguished contracts concerning tokens for the price of the products, and for the deposits. + * Will not be used while deploying on prod. + */ contract BosonTokenDeposit is ERC20WithPermit, AccessControl, Ownable { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); constructor(string memory name, string memory symbol) + public ERC20WithPermit(name, symbol) - public { _setupRole(MINTER_ROLE, owner()); _setupRole(ADMIN_ROLE, owner()); @@ -29,7 +29,10 @@ contract BosonTokenDeposit is ERC20WithPermit, AccessControl, Ownable { } function mint(address to, uint256 amount) public { - require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint"); + require( + hasRole(MINTER_ROLE, _msgSender()), + "ERC20PresetMinterPauser: must have minter role to mint" + ); _mint(to, amount); } -} \ No newline at end of file +} diff --git a/contracts/BosonTokenPrice.sol b/contracts/BosonTokenPrice.sol index 102aff49..d0db8279 100644 --- a/contracts/BosonTokenPrice.sol +++ b/contracts/BosonTokenPrice.sol @@ -1,18 +1,18 @@ // SPDX-License-Identifier: LGPL-3.0-or-later pragma solidity >=0.6.6 <0.7.0; + import "./ERC20WithPermit.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract BosonTokenPrice is ERC20WithPermit, AccessControl, Ownable { - bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); constructor(string memory name, string memory symbol) + public ERC20WithPermit(name, symbol) - public { _setupRole(MINTER_ROLE, owner()); _setupRole(ADMIN_ROLE, owner()); @@ -24,7 +24,10 @@ contract BosonTokenPrice is ERC20WithPermit, AccessControl, Ownable { } function mint(address to, uint256 amount) public { - require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint"); + require( + hasRole(MINTER_ROLE, _msgSender()), + "ERC20PresetMinterPauser: must have minter role to mint" + ); _mint(to, amount); } -} \ No newline at end of file +} diff --git a/contracts/Cashier.sol b/contracts/Cashier.sol index badf9f72..5f9f79f4 100644 --- a/contracts/Cashier.sol +++ b/contracts/Cashier.sol @@ -1,94 +1,77 @@ // SPDX-License-Identifier: LGPL-3.0-or-later pragma solidity >=0.6.6 <0.7.0; -import "./usingHelpers.sol"; -import "./IVoucherKernel.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; - +import "@openzeppelin/contracts/utils/Address.sol"; import "./IVoucherKernel.sol"; +import "./UsingHelpers.sol"; import "./IERC20WithPermit.sol"; import "./ICashier.sol"; /** * @title Contract for managing funds - * @dev Warning: the contract hasn't been audited yet! - * Roughly following OpenZeppelin's Escrow at https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/payment/ + * Roughly following OpenZeppelin's Escrow at https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/payment/ */ -contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { +contract Cashier is ICashier, UsingHelpers, ReentrancyGuard, Ownable, Pausable { using Address for address payable; - using SafeMath for uint; - + using SafeMath for uint256; + address public voucherKernel; address public bosonRouterAddress; - mapping(address => uint256) public escrow; //both types of deposits AND payments >> can be released token-by-token if checks pass - //slashedDepositPool can be obtained through getEscrowAmount(poolAddress) + enum PaymentType {PAYMENT, DEPOSIT_SELLER, DEPOSIT_BUYER} - enum PaymentType { PAYMENT, DEPOSIT_SELLER, DEPOSIT_BUYER } + mapping(address => uint256) public escrow; // both types of deposits AND payments >> can be released token-by-token if checks pass + // slashedDepositPool can be obtained through getEscrowAmount(poolAddress) uint256 internal constant CANCELFAULT_SPLIT = 2; //for POC purposes, this is hardcoded; e.g. each party gets depositSe / 2 - event LogBosonRouterSet( - address _newBosonRouter, - address _triggeredBy - ); + event LogBosonRouterSet(address _newBosonRouter, address _triggeredBy); - event LogWithdrawal( - address _caller, - address _payee, - uint256 _payment - ); + event LogWithdrawal(address _caller, address _payee, uint256 _payment); - event LogAmountDistribution ( + event LogAmountDistribution( uint256 indexed _tokenIdVoucher, - address _to, + address _to, uint256 _payment, PaymentType _type ); + event LogTokenContractSet(address _newTokenContract, address _triggeredBy); + modifier onlyFromRouter() { - require(bosonRouterAddress != address(0), "UNSPECIFIED_BR"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(msg.sender == bosonRouterAddress, "UNAUTHORIZED_BR"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require(bosonRouterAddress != address(0), "UNSPECIFIED_BR"); // hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(msg.sender == bosonRouterAddress, "UNAUTHORIZED_BR"); // hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; } - event LogTokenContractSet( - address _newTokenContract, - address _triggeredBy - ); - modifier notZeroAddress(address tokenAddress) { require(tokenAddress != address(0), "INVALID_TOKEN_ADDRESS"); _; } - constructor( - address _voucherKernel - ) - public - { + constructor(address _voucherKernel) public { voucherKernel = _voucherKernel; } /** - * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. - * Only BR contract is in control of this function. - */ + * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. + * Only BR contract is in control of this function. + */ function pause() external override onlyFromRouter { _pause(); } /** - * @notice Unpause the process of interaction with voucherID's (ERC-721). - * Only BR contract is in control of this function. - */ + * @notice Unpause the process of interaction with voucherID's (ERC-721). + * Only BR contract is in control of this function. + */ function unpause() external override onlyFromRouter { _unpause(); - } + } /** * @notice Trigger withdrawals of what funds are releasable @@ -106,47 +89,67 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { //TODO: check to pass 2 diff holders and how the amounts will be distributed VoucherDetails memory voucherDetails; - + //in the future might want to (i) check the gasleft() (but UNGAS proposal might make it impossible), and/or (ii) set upper loop limit to sth like .length < 2**15 - require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - - voucherDetails.tokenIdVoucher = _tokenIdVoucher; - voucherDetails.tokenIdSupply = IVoucherKernel(voucherKernel).getIdSupplyFromVoucher(voucherDetails.tokenIdVoucher); - voucherDetails.paymentMethod = IVoucherKernel(voucherKernel).getVoucherPaymentMethod(voucherDetails.tokenIdSupply); + require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(voucherDetails.paymentMethod > 0 && voucherDetails.paymentMethod <= 4, "INVALID PAYMENT METHOD"); + voucherDetails.tokenIdVoucher = _tokenIdVoucher; + voucherDetails.tokenIdSupply = IVoucherKernel(voucherKernel) + .getIdSupplyFromVoucher(voucherDetails.tokenIdVoucher); + voucherDetails.paymentMethod = IVoucherKernel(voucherKernel) + .getVoucherPaymentMethod(voucherDetails.tokenIdSupply); + + require( + voucherDetails.paymentMethod > 0 && + voucherDetails.paymentMethod <= 4, + "INVALID PAYMENT METHOD" + ); - (voucherDetails.currStatus.status, + ( + voucherDetails.currStatus.status, voucherDetails.currStatus.isPaymentReleased, voucherDetails.currStatus.isDepositsReleased - ) = IVoucherKernel(voucherKernel).getVoucherStatus(voucherDetails.tokenIdVoucher); - - (voucherDetails.price, - voucherDetails.depositSe, + ) = IVoucherKernel(voucherKernel).getVoucherStatus( + voucherDetails.tokenIdVoucher + ); + + ( + voucherDetails.price, + voucherDetails.depositSe, voucherDetails.depositBu - ) = IVoucherKernel(voucherKernel).getOrderCosts(voucherDetails.tokenIdSupply); - - voucherDetails.issuer = payable(IVoucherKernel(voucherKernel).getSupplyHolder(voucherDetails.tokenIdSupply)); - voucherDetails.holder = payable(IVoucherKernel(voucherKernel).getVoucherHolder(voucherDetails.tokenIdVoucher)); - + ) = IVoucherKernel(voucherKernel).getOrderCosts( + voucherDetails.tokenIdSupply + ); + + voucherDetails.issuer = payable( + IVoucherKernel(voucherKernel).getSupplyHolder( + voucherDetails.tokenIdSupply + ) + ); + voucherDetails.holder = payable( + IVoucherKernel(voucherKernel).getVoucherHolder( + voucherDetails.tokenIdVoucher + ) + ); + //process the RELEASE OF PAYMENTS - only depends on the redeemed/not-redeemed, a voucher need not be in the final status - if (!voucherDetails.currStatus.isPaymentReleased) - { + if (!voucherDetails.currStatus.isPaymentReleased) { releasePayments(voucherDetails); } - //process the RELEASE OF DEPOSITS - only when vouchers are in the FINAL status - if (!voucherDetails.currStatus.isDepositsReleased && - isStatus(voucherDetails.currStatus.status, idxFinal)) - { + //process the RELEASE OF DEPOSITS - only when vouchers are in the FINAL status + if ( + !voucherDetails.currStatus.isDepositsReleased && + isStatus(voucherDetails.currStatus.status, IDX_FINAL) + ) { releaseDeposits(voucherDetails); } - + if (voucherDetails.amount2pool > 0) { address payable poolAddress = payable(owner()); //this is required as we could not implicitly cast the owner address to payable _withdraw(poolAddress, voucherDetails.amount2pool); } - + if (voucherDetails.amount2issuer > 0) { _withdraw(voucherDetails.issuer, voucherDetails.amount2issuer); } @@ -171,49 +174,73 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { whenPaused { VoucherDetails memory voucherDetails; - + //in the future might want to (i) check the gasleft() (but UNGAS proposal might make it impossible), and/or (ii) set upper loop limit to sth like .length < 2**15 - require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - - voucherDetails.tokenIdVoucher = _tokenIdVoucher; - voucherDetails.tokenIdSupply = IVoucherKernel(voucherKernel).getIdSupplyFromVoucher(voucherDetails.tokenIdVoucher); - voucherDetails.paymentMethod = IVoucherKernel(voucherKernel).getVoucherPaymentMethod(voucherDetails.tokenIdSupply); + require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(voucherDetails.paymentMethod > 0 && voucherDetails.paymentMethod <= 4, "INVALID PAYMENT METHOD"); + voucherDetails.tokenIdVoucher = _tokenIdVoucher; + voucherDetails.tokenIdSupply = IVoucherKernel(voucherKernel) + .getIdSupplyFromVoucher(voucherDetails.tokenIdVoucher); + voucherDetails.paymentMethod = IVoucherKernel(voucherKernel) + .getVoucherPaymentMethod(voucherDetails.tokenIdSupply); + + require( + voucherDetails.paymentMethod > 0 && + voucherDetails.paymentMethod <= 4, + "INVALID PAYMENT METHOD" + ); - (voucherDetails.currStatus.status, + ( + voucherDetails.currStatus.status, voucherDetails.currStatus.isPaymentReleased, voucherDetails.currStatus.isDepositsReleased - ) = IVoucherKernel(voucherKernel).getVoucherStatus(voucherDetails.tokenIdVoucher); - - (voucherDetails.price, - voucherDetails.depositSe, + ) = IVoucherKernel(voucherKernel).getVoucherStatus( + voucherDetails.tokenIdVoucher + ); + + ( + voucherDetails.price, + voucherDetails.depositSe, voucherDetails.depositBu - ) = IVoucherKernel(voucherKernel).getOrderCosts(voucherDetails.tokenIdSupply); - - voucherDetails.issuer = payable(IVoucherKernel(voucherKernel).getSupplyHolder(voucherDetails.tokenIdSupply)); - voucherDetails.holder = payable(IVoucherKernel(voucherKernel).getVoucherHolder(voucherDetails.tokenIdVoucher)); - - require(msg.sender == voucherDetails.issuer || msg.sender == voucherDetails.holder, "INVALID CALLER"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + ) = IVoucherKernel(voucherKernel).getOrderCosts( + voucherDetails.tokenIdSupply + ); + + voucherDetails.issuer = payable( + IVoucherKernel(voucherKernel).getSupplyHolder( + voucherDetails.tokenIdSupply + ) + ); + voucherDetails.holder = payable( + IVoucherKernel(voucherKernel).getVoucherHolder( + voucherDetails.tokenIdVoucher + ) + ); + + require( + msg.sender == voucherDetails.issuer || + msg.sender == voucherDetails.holder, + "INVALID CALLER" + ); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + //process the RELEASE OF PAYMENTS - only depends on the redeemed/not-redeemed, a voucher need not be in the final status - if (!voucherDetails.currStatus.isPaymentReleased) - { + if (!voucherDetails.currStatus.isPaymentReleased) { releasePayments(voucherDetails); } - //process the RELEASE OF DEPOSITS - only when vouchers are in the FINAL status - if (!voucherDetails.currStatus.isDepositsReleased && - isStatus(voucherDetails.currStatus.status, idxFinal)) - { + //process the RELEASE OF DEPOSITS - only when vouchers are in the FINAL status + if ( + !voucherDetails.currStatus.isDepositsReleased && + isStatus(voucherDetails.currStatus.status, IDX_FINAL) + ) { releaseDeposits(voucherDetails); } - + if (voucherDetails.amount2pool > 0) { address payable poolAddress = payable(owner()); _withdraw(poolAddress, voucherDetails.amount2pool); } - + if (voucherDetails.amount2issuer > 0) { _withdraw(voucherDetails.issuer, voucherDetails.amount2issuer); } @@ -223,289 +250,452 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { } delete voucherDetails; - } function releasePayments(VoucherDetails memory voucherDetails) internal { - - if (isStatus(voucherDetails.currStatus.status, idxRedeem)) { + if (isStatus(voucherDetails.currStatus.status, IDX_REDEEM)) { releasePaymentToSeller(voucherDetails); - } else if (isStatus(voucherDetails.currStatus.status, idxRefund) - || isStatus(voucherDetails.currStatus.status, idxExpire) - || (isStatus(voucherDetails.currStatus.status, idxCancelFault) - && !isStatus(voucherDetails.currStatus.status, idxRedeem))) - { - releasePaymentToBuyer(voucherDetails); + } else if ( + isStatus(voucherDetails.currStatus.status, IDX_REFUND) || + isStatus(voucherDetails.currStatus.status, IDX_EXPIRE) || + (isStatus(voucherDetails.currStatus.status, IDX_CANCEL_FAULT) && + !isStatus(voucherDetails.currStatus.status, IDX_REDEEM)) + ) { + releasePaymentToBuyer(voucherDetails); } } - function releasePaymentToSeller(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == ETH_TKN) { + function releasePaymentToSeller(VoucherDetails memory voucherDetails) + internal + { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == ETHTKN + ) { escrow[voucherDetails.holder] -= voucherDetails.price; voucherDetails.amount2issuer += voucherDetails.price; } // TODO Chris - Can we have the same approach as above, first collect all amounts in one variable and do the payout at the end? So we save gas from multiple transfers - if(voucherDetails.paymentMethod == TKN_ETH || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenPrice = IVoucherKernel(voucherKernel).getVoucherPriceToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenPrice).transfer(voucherDetails.issuer, voucherDetails.price); + if ( + voucherDetails.paymentMethod == TKNETH || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenPrice = + IVoucherKernel(voucherKernel).getVoucherPriceToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenPrice).transfer( + voucherDetails.issuer, + voucherDetails.price + ); } - IVoucherKernel(voucherKernel).setPaymentReleased(voucherDetails.tokenIdVoucher); + IVoucherKernel(voucherKernel).setPaymentReleased( + voucherDetails.tokenIdVoucher + ); LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.issuer, - voucherDetails.price, + voucherDetails.tokenIdVoucher, + voucherDetails.issuer, + voucherDetails.price, PaymentType.PAYMENT ); } - function releasePaymentToBuyer(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == ETH_TKN) { + function releasePaymentToBuyer(VoucherDetails memory voucherDetails) + internal + { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == ETHTKN + ) { escrow[voucherDetails.holder] -= voucherDetails.price; voucherDetails.amount2holder += voucherDetails.price; } - if(voucherDetails.paymentMethod == TKN_ETH || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenPrice = IVoucherKernel(voucherKernel).getVoucherPriceToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenPrice).transfer(voucherDetails.holder, voucherDetails.price); + if ( + voucherDetails.paymentMethod == TKNETH || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenPrice = + IVoucherKernel(voucherKernel).getVoucherPriceToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenPrice).transfer( + voucherDetails.holder, + voucherDetails.price + ); } - IVoucherKernel(voucherKernel).setPaymentReleased(voucherDetails.tokenIdVoucher); + IVoucherKernel(voucherKernel).setPaymentReleased( + voucherDetails.tokenIdVoucher + ); LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.holder, - voucherDetails.price, + voucherDetails.tokenIdVoucher, + voucherDetails.holder, + voucherDetails.price, PaymentType.PAYMENT ); } function releaseDeposits(VoucherDetails memory voucherDetails) internal { - //first, depositSe - if (isStatus(voucherDetails.currStatus.status, idxComplain)) { + if (isStatus(voucherDetails.currStatus.status, IDX_COMPLAIN)) { //slash depositSe distributeIssuerDepositOnHolderComplain(voucherDetails); } else { - if (isStatus(voucherDetails.currStatus.status, idxCancelFault)) { + if (isStatus(voucherDetails.currStatus.status, IDX_CANCEL_FAULT)) { //slash depositSe distributeIssuerDepositOnIssuerCancel(voucherDetails); } else { //release depositSe - distributeFullIssuerDeposit(voucherDetails); + distributeFullIssuerDeposit(voucherDetails); } } - - //second, depositBu - if (isStatus(voucherDetails.currStatus.status, idxRedeem) || - isStatus(voucherDetails.currStatus.status, idxCancelFault) - ) { + + //second, depositBu + if ( + isStatus(voucherDetails.currStatus.status, IDX_REDEEM) || + isStatus(voucherDetails.currStatus.status, IDX_CANCEL_FAULT) + ) { //release depositBu distributeFullHolderDeposit(voucherDetails); } else { //slash depositBu distributeHolderDepositOnNotRedeemedNotCancelled(voucherDetails); - } - IVoucherKernel(voucherKernel).setDepositsReleased(voucherDetails.tokenIdVoucher); + IVoucherKernel(voucherKernel).setDepositsReleased( + voucherDetails.tokenIdVoucher + ); } - function distributeIssuerDepositOnHolderComplain(VoucherDetails memory voucherDetails) internal { - + function distributeIssuerDepositOnHolderComplain( + VoucherDetails memory voucherDetails + ) internal { uint256 tFraction; - if (isStatus(voucherDetails.currStatus.status, idxCancelFault)) { + if (isStatus(voucherDetails.currStatus.status, IDX_CANCEL_FAULT)) { //appease the conflict three-ways - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.issuer] -= voucherDetails.depositSe; tFraction = voucherDetails.depositSe.div(CANCELFAULT_SPLIT); voucherDetails.amount2holder += tFraction; //Bu gets, say, a half - voucherDetails.amount2issuer += tFraction.div(CANCELFAULT_SPLIT); //Se gets, say, a quarter - voucherDetails.amount2pool += voucherDetails.depositSe - tFraction - tFraction.div(CANCELFAULT_SPLIT); //slashing the rest + voucherDetails.amount2issuer += tFraction.div( + CANCELFAULT_SPLIT + ); //Se gets, say, a quarter + voucherDetails.amount2pool += + voucherDetails.depositSe - + tFraction - + tFraction.div(CANCELFAULT_SPLIT); //slashing the rest } - if(voucherDetails.paymentMethod == ETH_TKN || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - + if ( + voucherDetails.paymentMethod == ETHTKN || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + tFraction = voucherDetails.depositSe.div(CANCELFAULT_SPLIT); - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.holder, tFraction); - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.issuer, tFraction.div(CANCELFAULT_SPLIT)); - IERC20WithPermit(addressTokenDeposits).transfer(owner(), voucherDetails.depositSe - tFraction - tFraction.div(CANCELFAULT_SPLIT)); + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.holder, + tFraction + ); + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.issuer, + tFraction.div(CANCELFAULT_SPLIT) + ); + IERC20WithPermit(addressTokenDeposits).transfer( + owner(), + voucherDetails.depositSe - + tFraction - + tFraction.div(CANCELFAULT_SPLIT) + ); } - LogAmountDistribution(voucherDetails.tokenIdVoucher, voucherDetails.holder, tFraction, PaymentType.DEPOSIT_SELLER); - LogAmountDistribution(voucherDetails.tokenIdVoucher, voucherDetails.issuer, tFraction.div(CANCELFAULT_SPLIT), PaymentType.DEPOSIT_SELLER); - LogAmountDistribution(voucherDetails.tokenIdVoucher, owner(), voucherDetails.depositSe - tFraction - tFraction.div(CANCELFAULT_SPLIT), PaymentType.DEPOSIT_SELLER); - - tFraction = 0; + LogAmountDistribution( + voucherDetails.tokenIdVoucher, + voucherDetails.holder, + tFraction, + PaymentType.DEPOSIT_SELLER + ); + LogAmountDistribution( + voucherDetails.tokenIdVoucher, + voucherDetails.issuer, + tFraction.div(CANCELFAULT_SPLIT), + PaymentType.DEPOSIT_SELLER + ); + LogAmountDistribution( + voucherDetails.tokenIdVoucher, + owner(), + voucherDetails.depositSe - + tFraction - + tFraction.div(CANCELFAULT_SPLIT), + PaymentType.DEPOSIT_SELLER + ); + tFraction = 0; } else { //slash depositSe - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.issuer] -= voucherDetails.depositSe; voucherDetails.amount2pool += voucherDetails.depositSe; } else { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenDeposits).transfer(owner(), voucherDetails.depositSe); + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenDeposits).transfer( + owner(), + voucherDetails.depositSe + ); } - LogAmountDistribution(voucherDetails.tokenIdVoucher, owner(), voucherDetails.depositSe, PaymentType.DEPOSIT_SELLER); + LogAmountDistribution( + voucherDetails.tokenIdVoucher, + owner(), + voucherDetails.depositSe, + PaymentType.DEPOSIT_SELLER + ); } } - function distributeIssuerDepositOnIssuerCancel(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + function distributeIssuerDepositOnIssuerCancel( + VoucherDetails memory voucherDetails + ) internal { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.issuer] -= voucherDetails.depositSe; - voucherDetails.amount2issuer += voucherDetails.depositSe.div(CANCELFAULT_SPLIT); - voucherDetails.amount2holder += voucherDetails.depositSe - voucherDetails.depositSe.div(CANCELFAULT_SPLIT); + voucherDetails.amount2issuer += voucherDetails.depositSe.div( + CANCELFAULT_SPLIT + ); + voucherDetails.amount2holder += + voucherDetails.depositSe - + voucherDetails.depositSe.div(CANCELFAULT_SPLIT); } - if (voucherDetails.paymentMethod == ETH_TKN || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.issuer, voucherDetails.depositSe.div(CANCELFAULT_SPLIT)); - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.holder, voucherDetails.depositSe - voucherDetails.depositSe.div(CANCELFAULT_SPLIT)); + if ( + voucherDetails.paymentMethod == ETHTKN || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.issuer, + voucherDetails.depositSe.div(CANCELFAULT_SPLIT) + ); + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.holder, + voucherDetails.depositSe - + voucherDetails.depositSe.div(CANCELFAULT_SPLIT) + ); } LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.issuer, - voucherDetails.depositSe.div(CANCELFAULT_SPLIT), + voucherDetails.tokenIdVoucher, + voucherDetails.issuer, + voucherDetails.depositSe.div(CANCELFAULT_SPLIT), PaymentType.DEPOSIT_SELLER ); LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.holder, - voucherDetails.depositSe - voucherDetails.depositSe.div(CANCELFAULT_SPLIT), + voucherDetails.tokenIdVoucher, + voucherDetails.holder, + voucherDetails.depositSe - + voucherDetails.depositSe.div(CANCELFAULT_SPLIT), PaymentType.DEPOSIT_SELLER ); } - function distributeFullIssuerDeposit(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + function distributeFullIssuerDeposit(VoucherDetails memory voucherDetails) + internal + { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.issuer] -= voucherDetails.depositSe; voucherDetails.amount2issuer += voucherDetails.depositSe; } - if(voucherDetails.paymentMethod == ETH_TKN || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.issuer, voucherDetails.depositSe); + if ( + voucherDetails.paymentMethod == ETHTKN || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.issuer, + voucherDetails.depositSe + ); } LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.issuer, - voucherDetails.depositSe, + voucherDetails.tokenIdVoucher, + voucherDetails.issuer, + voucherDetails.depositSe, PaymentType.DEPOSIT_SELLER - ); + ); } - function distributeFullHolderDeposit(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + function distributeFullHolderDeposit(VoucherDetails memory voucherDetails) + internal + { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.holder] -= voucherDetails.depositBu; voucherDetails.amount2holder += voucherDetails.depositBu; } - if(voucherDetails.paymentMethod == ETH_TKN || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenDeposits).transfer(voucherDetails.holder, voucherDetails.depositBu); + if ( + voucherDetails.paymentMethod == ETHTKN || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenDeposits).transfer( + voucherDetails.holder, + voucherDetails.depositBu + ); } LogAmountDistribution( - voucherDetails.tokenIdVoucher, - voucherDetails.holder, - voucherDetails.depositBu, + voucherDetails.tokenIdVoucher, + voucherDetails.holder, + voucherDetails.depositBu, PaymentType.DEPOSIT_BUYER - ); + ); } - function distributeHolderDepositOnNotRedeemedNotCancelled(VoucherDetails memory voucherDetails) internal { - - if(voucherDetails.paymentMethod == ETH_ETH || voucherDetails.paymentMethod == TKN_ETH) { + function distributeHolderDepositOnNotRedeemedNotCancelled( + VoucherDetails memory voucherDetails + ) internal { + if ( + voucherDetails.paymentMethod == ETHETH || + voucherDetails.paymentMethod == TKNETH + ) { escrow[voucherDetails.holder] -= voucherDetails.depositBu; - voucherDetails.amount2pool += voucherDetails.depositBu; + voucherDetails.amount2pool += voucherDetails.depositBu; } - if(voucherDetails.paymentMethod == ETH_TKN || voucherDetails.paymentMethod == TKN_TKN) { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(voucherDetails.tokenIdSupply); - IERC20WithPermit(addressTokenDeposits).transfer(owner(), voucherDetails.depositBu); + if ( + voucherDetails.paymentMethod == ETHTKN || + voucherDetails.paymentMethod == TKNTKN + ) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + voucherDetails.tokenIdSupply + ); + IERC20WithPermit(addressTokenDeposits).transfer( + owner(), + voucherDetails.depositBu + ); } LogAmountDistribution( - voucherDetails.tokenIdVoucher, - owner(), - voucherDetails.depositBu, + voucherDetails.tokenIdVoucher, + owner(), + voucherDetails.depositBu, PaymentType.DEPOSIT_BUYER - ); + ); } /** - * @notice Seller triggers withdrawals of remaining deposits for a given supply, in case the contracts are paused. - * @param _tokenIdSupply an ID of a supply token (ERC-1155) which will be burned and deposits will be returned for - */ + * @notice Seller triggers withdrawals of remaining deposits for a given supply, in case the contracts are paused. + * @param _tokenIdSupply an ID of a supply token (ERC-1155) which will be burned and deposits will be returned for + */ function withdrawDeposits(uint256 _tokenIdSupply) external override nonReentrant whenPaused { - address payable seller = payable(IVoucherKernel(voucherKernel).getSupplyHolder(_tokenIdSupply)); - + address payable seller = + payable( + IVoucherKernel(voucherKernel).getSupplyHolder(_tokenIdSupply) + ); + require(msg.sender == seller, "UNAUTHORIZED_SE"); - uint256 deposit = IVoucherKernel(voucherKernel).getSellerDeposit(_tokenIdSupply); - uint256 remQty = IVoucherKernel(voucherKernel).getRemQtyForSupply(_tokenIdSupply, seller); - + uint256 deposit = + IVoucherKernel(voucherKernel).getSellerDeposit(_tokenIdSupply); + uint256 remQty = + IVoucherKernel(voucherKernel).getRemQtyForSupply( + _tokenIdSupply, + seller + ); + require(remQty > 0, "OFFER_EMPTY"); uint256 depositAmount = deposit.mul(remQty); - IVoucherKernel(voucherKernel).burnSupplyOnPause(seller, _tokenIdSupply, remQty); - - uint8 paymentMethod = IVoucherKernel(voucherKernel).getVoucherPaymentMethod(_tokenIdSupply); + IVoucherKernel(voucherKernel).burnSupplyOnPause( + seller, + _tokenIdSupply, + remQty + ); - require(paymentMethod > 0 && paymentMethod <= 4, "INVALID PAYMENT METHOD"); + uint8 paymentMethod = + IVoucherKernel(voucherKernel).getVoucherPaymentMethod( + _tokenIdSupply + ); + require( + paymentMethod > 0 && paymentMethod <= 4, + "INVALID PAYMENT METHOD" + ); - if(paymentMethod == ETH_ETH || paymentMethod == TKN_ETH) - { + if (paymentMethod == ETHETH || paymentMethod == TKNETH) { escrow[msg.sender] = escrow[msg.sender].sub(depositAmount); _withdrawDeposits(seller, depositAmount); } - if(paymentMethod == ETH_TKN || paymentMethod == TKN_TKN) - { - address addressTokenDeposits = IVoucherKernel(voucherKernel).getVoucherDepositToken(_tokenIdSupply); - IERC20WithPermit(addressTokenDeposits).transfer(seller, depositAmount); + if (paymentMethod == ETHTKN || paymentMethod == TKNTKN) { + address addressTokenDeposits = + IVoucherKernel(voucherKernel).getVoucherDepositToken( + _tokenIdSupply + ); + IERC20WithPermit(addressTokenDeposits).transfer( + seller, + depositAmount + ); } } /** * @notice Trigger withdrawals of pooled funds - */ - function withdrawPool() - external - override - onlyOwner - nonReentrant - { + */ + function withdrawPool() external override onlyOwner nonReentrant { //TODO: more requires needed? - + if (escrow[owner()] > 0) { address payable poolAddress = address(uint160(owner())); //this is required as we could not implicitly cast the owner address to payable uint256 amount = escrow[poolAddress]; escrow[poolAddress] = 0; - _withdraw(poolAddress,amount); + _withdraw(poolAddress, amount); } } @@ -513,16 +703,14 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { * @notice Internal function for withdrawing. * As unbelievable as it is, neither .send() nor .transfer() are now secure to use due to EIP-1884 * So now transferring funds via the last remaining option: .call() - * See https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ + * See https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/ * @param _recipient address of the account receiving funds from the escrow * @param _amount amount to be released from escrow */ - function _withdraw(address payable _recipient, uint256 _amount) - internal - { - require(_recipient != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + function _withdraw(address payable _recipient, uint256 _amount) internal { + require(_recipient != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) require(_amount > 0, ""); - + _recipient.sendValue(_amount); emit LogWithdrawal(msg.sender, _recipient, _amount); @@ -531,9 +719,9 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { function _withdrawDeposits(address payable _recipient, uint256 _amount) internal { - require(_recipient != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(_recipient != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) require(_amount > 0, ""); - + _recipient.sendValue(_amount); emit LogWithdrawal(msg.sender, _recipient, _amount); @@ -548,19 +736,19 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { override onlyOwner { - require(_bosonRouterAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + require(_bosonRouterAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + bosonRouterAddress = _bosonRouterAddress; - + emit LogBosonRouterSet(_bosonRouterAddress, msg.sender); } /** - * @notice Update the amount in escrow of an address wit the new value, based on VoucherSet/Voucher interaction - * @param _account The address of an account to query - * @param _newAmount New amount to be set - */ - function updateEscrowAmount(address _account, uint256 _newAmount) + * @notice Update the amount in escrow of an address wit the new value, based on VoucherSet/Voucher interaction + * @param _account The address of an account to query + * @param _newAmount New amount to be set + */ + function updateEscrowAmount(address _account, uint256 _newAmount) external override onlyFromRouter @@ -569,27 +757,27 @@ contract Cashier is ICashier, usingHelpers, ReentrancyGuard, Ownable, Pausable { } /** - * @notice Only accept ETH via fallback from the BR Contract - */ + * @notice Only accept ETH via fallback from the BR Contract + */ receive() external payable { assert(msg.sender == bosonRouterAddress); } - // // // // // // // // - // GETTERS - // // // // // // // // - + // GETTERS + // // // // // // // // + /** * @notice Get the amount in escrow of an address * @param _account The address of an account to query * @return The balance in escrow */ - function getEscrowAmount(address _account) - external view override + function getEscrowAmount(address _account) + external + view + override returns (uint256) { return escrow[_account]; } - -} \ No newline at end of file +} diff --git a/contracts/ERC1155ERC721.sol b/contracts/ERC1155ERC721.sol index 9e8b5b37..d8861087 100644 --- a/contracts/ERC1155ERC721.sol +++ b/contracts/ERC1155ERC721.sol @@ -15,63 +15,57 @@ import "./IBosonRouter.sol"; //preparing for ERC-1066, ERC-1444, EIP-838 /** - * @title Multi-token contract, implementing ERC-1155 and ERC-721 hybrid + * @title Multi-token contract, implementing ERC-1155 and ERC-721 hybrid * Inspired by: https://github.com/pixowl/sandbox-smart-contracts */ -contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { +contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { using SafeMath for uint256; using Address for address; - + //min security - address public owner; //contract owner - address public voucherKernelAddress; //address of the VoucherKernel contract - address public bosonRouterAddress; //address of the BosonRouter contract - + address public owner; //contract owner + address public voucherKernelAddress; //address of the VoucherKernel contract + address public bosonRouterAddress; //address of the BosonRouter contract + //standard reqs //ERC-1155 - mapping (uint256 => mapping(address => uint256)) private balances; //balance of token ids of an account - + mapping(uint256 => mapping(address => uint256)) private balances; //balance of token ids of an account + //ERC-721 mapping(address => uint256) private balance721; mapping(uint256 => address) private owners721; mapping(uint256 => address) private operator721; - + //shared storage: ERC-1155 & ERC-721 - mapping (address => mapping(address => bool)) private operatorApprovals; //approval of accounts of an operator + mapping(address => mapping(address => bool)) private operatorApprovals; //approval of accounts of an operator //metadata is shared, too (but ERC-1155 and ERC-721 have different metadata extension reqs) string internal metadataBase; - + //ERC-1155 metadata event: URIs are defined in RFC 3986. The URI MUST point to a JSON file that conforms to the ERC-1155 Metadata URI JSON Schema. //not used ATM //event URI(string _value, uint256 indexed _id); - event LogVoucherKernelSet( - address _newVoucherKernel, - address _triggeredBy - ); + event LogVoucherKernelSet(address _newVoucherKernel, address _triggeredBy); + + event LogBosonRouterSet(address _newBosonRouter, address _triggeredBy); - event LogBosonRouterSet( - address _newBosonRouter, - address _triggeredBy - ); - modifier onlyOwner() { - require(msg.sender == owner, "UNAUTHORIZED_O"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require(msg.sender == owner, "UNAUTHORIZED_O"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; } - + modifier onlyFromVoucherKernel() { - require(voucherKernelAddress != address(0), "UNSPECIFIED_VOUCHERKERNEL"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(msg.sender == voucherKernelAddress, "UNAUTHORIZED_VK"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require( + voucherKernelAddress != address(0), + "UNSPECIFIED_VOUCHERKERNEL" + ); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(msg.sender == voucherKernelAddress, "UNAUTHORIZED_VK"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; - } + } - constructor() - public - { + constructor() public { owner = msg.sender; } - /** * @notice Transfers amount of _tokenId from-to addresses with safety call. @@ -82,35 +76,50 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId ID of the token * @param _value Transfer amount * @param _data Additional data forwarded to onERC1155Received if _to is a contract - */ + */ function safeTransferFrom( address _from, address _to, uint256 _tokenId, uint256 _value, bytes calldata _data - ) - external - override - { + ) external override { require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(_from == msg.sender || operatorApprovals[_from][msg.sender] == true, "UNAUTHORIZED_ST"); //hex"10"FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) - - IBosonRouter(bosonRouterAddress)._beforeERC1155Transfer(_from, _tokenId, _value); + require( + _from == msg.sender || operatorApprovals[_from][msg.sender] == true, + "UNAUTHORIZED_ST" + ); //hex"10"FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + + IBosonRouter(bosonRouterAddress)._beforeERC1155Transfer( + _from, + _tokenId, + _value + ); // SafeMath throws with insufficient funds or if _id is not valid (balance will be 0) balances[_tokenId][_from] = balances[_tokenId][_from].sub(_value); balances[_tokenId][_to] = _value.add(balances[_tokenId][_to]); - IBosonRouter(bosonRouterAddress)._onERC1155Transfer(_from, _to, _tokenId, _value); + IBosonRouter(bosonRouterAddress)._onERC1155Transfer( + _from, + _to, + _tokenId, + _value + ); emit TransferSingle(msg.sender, _from, _to, _tokenId, _value); //make sure the tx was accepted - in case of a revert below, the event above is reverted, too - _doSafeTransferAcceptanceCheck(msg.sender, _from, _to, _tokenId, _value, _data); - } - - + _doSafeTransferAcceptanceCheck( + msg.sender, + _from, + _to, + _tokenId, + _value, + _data + ); + } + /** * @notice Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, @@ -123,10 +132,11 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _to address to receive the ownership of the given token ID * @param _tokenId uint256 ID of the token to be transferred */ - function safeTransferFrom(address _from, address _to, uint256 _tokenId) - public - override - { + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId + ) public override { safeTransferFrom(_from, _to, _tokenId, ""); } @@ -140,18 +150,27 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ - function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) - public - override - { + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory _data + ) public override { transferFrom(_from, _to, _tokenId); - + if (_to.isContract()) { - require(ERC721TokenReceiver(_to).onERC721Received(_from, _to, _tokenId, _data) == ERC721TokenReceiver(_to).onERC721Received.selector, "UNSUPPORTED_ERC721_RECEIVED"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) - } - } - - + require( + ERC721TokenReceiver(_to).onERC721Received( + _from, + _to, + _tokenId, + _data + ) == ERC721TokenReceiver(_to).onERC721Received.selector, + "UNSUPPORTED_ERC721_RECEIVED" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + } + } + /** * @notice Transfers the ownership of a given token ID to another address. * Usage of this method is discouraged, use `safeTransferFrom` whenever possible. @@ -161,16 +180,20 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _to address to receive the ownership of the given token ID * @param _tokenId uint256 ID of the token to be transferred */ - function transferFrom(address _from, address _to, uint256 _tokenId) - public - override - { - require(operator721[_tokenId] == msg.sender || ownerOf(_tokenId) == msg.sender, "NOT_OWNER_NOR_APPROVED"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) public override { + require( + operator721[_tokenId] == msg.sender || + ownerOf(_tokenId) == msg.sender, + "NOT_OWNER_NOR_APPROVED" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _transferFrom(_from, _to, _tokenId); - } - - + } + /** * @notice Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. @@ -179,25 +202,30 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _to address to receive the ownership of the given token ID * @param _tokenId uint256 ID of the token to be transferred */ - function _transferFrom(address _from, address _to, uint256 _tokenId) - internal - { - require(ownerOf(_tokenId) == _from, "UNAUTHORIZED_T"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) - require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + function _transferFrom( + address _from, + address _to, + uint256 _tokenId + ) internal { + require(ownerOf(_tokenId) == _from, "UNAUTHORIZED_T"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) operator721[_tokenId] = address(0); balance721[_from]--; balance721[_to]++; - + owners721[_tokenId] = _to; - IBosonRouter(bosonRouterAddress)._onERC721Transfer(_from, _to, _tokenId); + IBosonRouter(bosonRouterAddress)._onERC721Transfer( + _from, + _to, + _tokenId + ); emit Transfer(_from, _to, _tokenId); - } - - + } + /** * @notice Approves another address to transfer the given token ID * The zero address indicates there is no approved address. @@ -207,22 +235,21 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _to address to be approved for the given token ID * @param _tokenId uint256 ID of the token to be approved */ - function approve(address _to, uint256 _tokenId) - public - override - { + function approve(address _to, uint256 _tokenId) public override { address tokenOwner = ownerOf(_tokenId); require(_to != tokenOwner, "REDUNDANT_CALL"); //hex"18" FISSION.code(FISSION.Category.Permission, FISSION.Status.NotApplicatableToCurrentState) - require(msg.sender == tokenOwner || operatorApprovals[tokenOwner][msg.sender],// isApprovedForAll(owner, msg.sender), - "UNAUTHORIZED_A"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) - //"ERC721: approve caller is not owner nor approved for all" + require( + msg.sender == tokenOwner || + operatorApprovals[tokenOwner][msg.sender], // isApprovedForAll(owner, msg.sender), + "UNAUTHORIZED_A" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + //"ERC721: approve caller is not owner nor approved for all" operator721[_tokenId] = _to; emit Approval(tokenOwner, _to, _tokenId); - } - - + } + /** * @notice Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. @@ -230,18 +257,20 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ - function getApproved(uint256 _tokenId) - public + function getApproved(uint256 _tokenId) + public view override - returns (address) + returns (address) { - require(owners721[_tokenId] != address(0), "ERC721: approved query for nonexistent token"); + require( + owners721[_tokenId] != address(0), + "ERC721: approved query for nonexistent token" + ); return operator721[_tokenId]; - } - - + } + /** @notice Transfers amount of _tokenId from-to addresses with safety call. If _to is a smart contract, will call onERC1155BatchReceived @@ -258,35 +287,49 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { uint256[] calldata _tokenIds, uint256[] calldata _values, bytes calldata _data - ) - external - override - { - require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) - require(_from == msg.sender || operatorApprovals[_from][msg.sender] == true, "UNAUTHORIZED_SB"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + ) external override { + require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) + require( + _from == msg.sender || operatorApprovals[_from][msg.sender] == true, + "UNAUTHORIZED_SB" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) for (uint256 i = 0; i < _tokenIds.length; ++i) { uint256 tokenId = _tokenIds[i]; uint256 value = _values[i]; - IBosonRouter(bosonRouterAddress)._beforeERC1155Transfer(_from, tokenId, value); - + IBosonRouter(bosonRouterAddress)._beforeERC1155Transfer( + _from, + tokenId, + value + ); + // SafeMath throws with insufficient funds or if _id is not valid (balance will be 0) balances[tokenId][_from] = balances[tokenId][_from].sub(value); - balances[tokenId][_to] = value.add(balances[tokenId][_to]); - - IBosonRouter(bosonRouterAddress)._onERC1155Transfer(_from, _to, tokenId, value); - + balances[tokenId][_to] = value.add(balances[tokenId][_to]); + + IBosonRouter(bosonRouterAddress)._onERC1155Transfer( + _from, + _to, + tokenId, + value + ); } emit TransferBatch(msg.sender, _from, _to, _tokenIds, _values); //make sure the tx was accepted - in case of a revert below, the event above is reverted, too - _doSafeBatchTransferAcceptanceCheck(msg.sender, _from, _to, _tokenIds, _values, _data); - } - - + _doSafeBatchTransferAcceptanceCheck( + msg.sender, + _from, + _to, + _tokenIds, + _values, + _data + ); + } + /** * @notice Check successful transfer if recipient is a contract * @dev ERC-1155 @@ -304,16 +347,21 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { uint256 _tokenId, uint256 _value, bytes memory _data - ) - internal - { - if(_to.isContract()) { - require(ERC1155TokenReceiver(_to).onERC1155Received(_operator, _from, _tokenId, _value, _data) == - ERC1155TokenReceiver(_to).onERC1155Received.selector, "NOT_SUPPORTED"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + ) internal { + if (_to.isContract()) { + require( + ERC1155TokenReceiver(_to).onERC1155Received( + _operator, + _from, + _tokenId, + _value, + _data + ) == ERC1155TokenReceiver(_to).onERC1155Received.selector, + "NOT_SUPPORTED" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) } } - /** * @notice Check successful transfer if recipient is a contract * @dev ERC-1155 @@ -323,7 +371,7 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenIds Array of IDs of tokens * @param _values Array of values transferred * @param _data Optional data - */ + */ function _doSafeBatchTransferAcceptanceCheck( address _operator, address _from, @@ -331,16 +379,21 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { uint256[] memory _tokenIds, uint256[] memory _values, bytes memory _data - ) - internal - { - if(_to.isContract()) { - require(ERC1155TokenReceiver(_to).onERC1155BatchReceived(_operator, _from, _tokenIds, _values, _data) == - ERC1155TokenReceiver(_to).onERC1155BatchReceived.selector, "NOT_SUPPORTED"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + ) internal { + if (_to.isContract()) { + require( + ERC1155TokenReceiver(_to).onERC1155BatchReceived( + _operator, + _from, + _tokenIds, + _values, + _data + ) == ERC1155TokenReceiver(_to).onERC1155BatchReceived.selector, + "NOT_SUPPORTED" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) } - } - - + } + /** @notice Get the balance of tokens of an account @dev ERC-1155 @@ -348,31 +401,24 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { @param _tokenId ID of the token @return balance */ - function balanceOf(address _account, uint256 _tokenId) - external + function balanceOf(address _account, uint256 _tokenId) + external view override - returns (uint256) + returns (uint256) { return balances[_tokenId][_account]; - } - - + } + /// @notice Count all NFTs assigned to an owner /// @dev ERC-721 /// @param _owner An address for whom to query the balance /// @return The number of NFTs owned by `_owner`, possibly zero - function balanceOf(address _owner) - public - view - override - returns (uint256) - { - require(_owner != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + function balanceOf(address _owner) public view override returns (uint256) { + require(_owner != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) return balance721[_owner]; } - /** * @notice Gets the owner of the specified token ID. @@ -380,20 +426,13 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId uint256 ID of the token to query the owner of * @return address currently marked as the owner of the given token ID */ - function ownerOf(uint256 _tokenId) - public - view - override - returns (address) - { + function ownerOf(uint256 _tokenId) public view override returns (address) { address tokenOwner = owners721[_tokenId]; - require(tokenOwner != address(0), "UNDEFINED_OWNER"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(tokenOwner != address(0), "UNDEFINED_OWNER"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) return tokenOwner; - } - - - + } + /** @notice Get the balance of account-token pairs. @dev ERC-1155 @@ -404,13 +443,11 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { function balanceOfBatch( address[] calldata _accounts, uint256[] calldata _tokenIds - ) - external - view - override - returns (uint256[] memory) - { - require(_accounts.length == _tokenIds.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) + ) external view override returns (uint256[] memory) { + require( + _accounts.length == _tokenIds.length, + "MISMATCHED_ARRAY_LENGTHS" + ); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) uint256[] memory batchBalances = new uint256[](_accounts.length); for (uint256 i = 0; i < _accounts.length; ++i) { @@ -418,9 +455,8 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { } return batchBalances; - } - - + } + /** * @notice Approves or unapproves the operator. * will revert if the caller attempts to approve itself as it is redundant @@ -428,16 +464,15 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _operator to (un)approve * @param _approve flag to set or unset */ - function setApprovalForAll(address _operator, bool _approve) + function setApprovalForAll(address _operator, bool _approve) external override(IERC1155, IERC721) { require(msg.sender != _operator, "REDUNDANT_CALL"); //hex"18" FISSION.code(FISSION.Category.Permission, FISSION.Status.NotApplicatableToCurrentState) operatorApprovals[msg.sender][_operator] = _approve; emit ApprovalForAll(msg.sender, _operator, _approve); - } - - + } + /** @notice Gets approval status of an operator for a given account. @dev ERC-1155 & ERC-721 @@ -445,27 +480,27 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { @param _operator operator to check @return True if the operator is approved, false if not */ - function isApprovedForAll(address _account, address _operator) - public - view + function isApprovedForAll(address _account, address _operator) + public + view override(IERC1155, IERC721) - returns (bool) + returns (bool) { return operatorApprovals[_account][_operator]; - } - + } /** * @notice Returns true if this contract implements the interface defined by _interfaceId_. * This function call must use less than 30 000 gas. ATM not enforced. */ - function supportsInterface(bytes4 _interfaceId) - external - view + function supportsInterface(bytes4 _interfaceId) + external + view override returns (bool) { - return //check matching against ERC-165 identifiers + return + //check matching against ERC-165 identifiers _interfaceId == 0x01ffc9a7 || //ERC-165 _interfaceId == 0xd9b67a26 || //ERC-1155 _interfaceId == 0x80ac58cd || //ERC-721 @@ -474,8 +509,8 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { } // // // // // // // // - // STANDARD - UTILS - // // // // // // // // + // STANDARD - UTILS + // // // // // // // // /** * @notice Mint an amount of a desired token * Currently no restrictions as to who is allowed to mint - so, it is public. @@ -485,14 +520,15 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _value Amount of the token to be minted * @param _data Additional data forwarded to onERC1155BatchReceived if _to is a contract */ - function mint(address _to, uint256 _tokenId, uint256 _value, bytes memory _data) - public - override - onlyFromVoucherKernel - { + function mint( + address _to, + uint256 _tokenId, + uint256 _value, + bytes memory _data + ) public override onlyFromVoucherKernel { _mint(_to, _tokenId, _value, _data); - } - + } + /** * @notice Internal function to mint an amount of a desired token * @dev ERC-1155 @@ -501,18 +537,27 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _value Amount of the token to be minted * @param _data Additional data forwarded to onERC1155BatchReceived if _to is a contract */ - function _mint(address _to, uint256 _tokenId, uint256 _value, bytes memory _data) - internal - { - require(_to != address(0), "UNSPECIFIED_ADDRESS"); //FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + function _mint( + address _to, + uint256 _tokenId, + uint256 _value, + bytes memory _data + ) internal { + require(_to != address(0), "UNSPECIFIED_ADDRESS"); //FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + balances[_tokenId][_to] = balances[_tokenId][_to].add(_value); emit TransferSingle(msg.sender, address(0), _to, _tokenId, _value); - _doSafeTransferAcceptanceCheck(msg.sender, address(0), _to, _tokenId, _value, _data); - } - - + _doSafeTransferAcceptanceCheck( + msg.sender, + address(0), + _to, + _tokenId, + _value, + _data + ); + } + /** * @notice Function to mint tokens. * @dev ERC-721 @@ -520,17 +565,16 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param tokenId The token id to mint. * @return A boolean that indicates if the operation was successful. */ - function mint(address to, uint256 tokenId) + function mint(address to, uint256 tokenId) public override onlyFromVoucherKernel - returns (bool) + returns (bool) { _mint(to, tokenId); return true; } - - + /** * @notice Internal function to mint a new token. * Reverts if the given token ID already exists. @@ -538,19 +582,19 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _to The address that will own the minted token * @param _tokenId uint256 ID of the token to be minted */ - function _mint(address _to, uint256 _tokenId) - internal - { - require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(owners721[_tokenId] == address(0), "ERC721: token already minted"); + function _mint(address _to, uint256 _tokenId) internal { + require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require( + owners721[_tokenId] == address(0), + "ERC721: token already minted" + ); owners721[_tokenId] = _to; balance721[_to]++; emit Transfer(address(0), _to, _tokenId); } - - + /** * @notice Batch minting of tokens * Currently no restrictions as to who is allowed to mint - so, it is public. @@ -560,15 +604,17 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _values Amounts of the tokens to be minted * @param _data Additional data forwarded to onERC1155BatchReceived if _to is a contract */ - function mintBatch(address _to, uint256[] memory _tokenIds, uint256[] memory _values, bytes memory _data) - public - onlyFromVoucherKernel - { + function mintBatch( + address _to, + uint256[] memory _tokenIds, + uint256[] memory _values, + bytes memory _data + ) public onlyFromVoucherKernel { //require approved minter - + _mintBatch(_to, _tokenIds, _values, _data); - } - + } + /** * @notice Internal function for batch minting of tokens\ * @dev ERC-1155 @@ -577,22 +623,33 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _values Amounts of the tokens to be minted * @param _data Additional data forwarded to onERC1155BatchReceived if _to is a contract */ - function _mintBatch(address _to, uint256[] memory _tokenIds, uint256[] memory _values, bytes memory _data) - internal - { - require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + function _mintBatch( + address _to, + uint256[] memory _tokenIds, + uint256[] memory _values, + bytes memory _data + ) internal { + require(_to != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) - for(uint i = 0; i < _tokenIds.length; i++) { - balances[_tokenIds[i]][_to] = _values[i].add(balances[_tokenIds[i]][_to]); + for (uint256 i = 0; i < _tokenIds.length; i++) { + balances[_tokenIds[i]][_to] = _values[i].add( + balances[_tokenIds[i]][_to] + ); } emit TransferBatch(msg.sender, address(0), _to, _tokenIds, _values); - _doSafeBatchTransferAcceptanceCheck(msg.sender, address(0), _to, _tokenIds, _values, _data); - } - - + _doSafeBatchTransferAcceptanceCheck( + msg.sender, + address(0), + _to, + _tokenIds, + _values, + _data + ); + } + /** * @notice Burn an amount of tokens with the given ID * @dev ERC-1155 @@ -600,14 +657,14 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId ID of the token * @param _value Amount of the token */ - function burn(address _account, uint256 _tokenId, uint256 _value) - public - override - onlyFromVoucherKernel - { + function burn( + address _account, + uint256 _tokenId, + uint256 _value + ) public override onlyFromVoucherKernel { _burn(_account, _tokenId, _value); } - + /** * @notice Burn an amount of tokens with the given ID * @dev ERC-1155 @@ -615,16 +672,18 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenId ID of the token * @param _value Amount of the token */ - function _burn(address _account, uint256 _tokenId, uint256 _value) internal { - require(_account != address(0), "UNSPECIFIED_ADDRESS"); //"UNSPECIFIED_ADDRESS" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + function _burn( + address _account, + uint256 _tokenId, + uint256 _value + ) internal { + require(_account != address(0), "UNSPECIFIED_ADDRESS"); //"UNSPECIFIED_ADDRESS" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) balances[_tokenId][_account] = balances[_tokenId][_account].sub(_value); emit TransferSingle(msg.sender, _account, address(0), _tokenId, _value); } - - - /* Burning ERC-721 is not allowed, as a voucher (being an ERC-721 token) has a final state and shouldn't be destructed. */ - + + /* Burning ERC-721 is not allowed, as a voucher (being an ERC-721 token) has a final state and shouldn't be destructed. */ /** * @notice Batch burn an amounts of tokens @@ -633,13 +692,14 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenIds IDs of the tokens * @param _values Amounts of the tokens */ - function burnBatch(address _account, uint256[] memory _tokenIds, uint256[] memory _values) - public - onlyFromVoucherKernel - { + function burnBatch( + address _account, + uint256[] memory _tokenIds, + uint256[] memory _values + ) public onlyFromVoucherKernel { _burnBatch(_account, _tokenIds, _values); - } - + } + /** * @notice Internal function to batch burn an amounts of tokens * @dev ERC-1155 @@ -647,70 +707,67 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @param _tokenIds IDs of the tokens * @param _values Amounts of the tokens */ - function _burnBatch(address _account, uint256[] memory _tokenIds, uint256[] memory _values) - internal - { + function _burnBatch( + address _account, + uint256[] memory _tokenIds, + uint256[] memory _values + ) internal { require(_account != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) require(_tokenIds.length == _values.length, "MISMATCHED_ARRAY_LENGTHS"); //hex"28" FISSION.code(FISSION.Category.Find, FISSION.Status.Duplicate_Conflict_Collision) - for(uint i = 0; i < _tokenIds.length; i++) { - balances[_tokenIds[i]][_account] = balances[_tokenIds[i]][_account].sub(_values[i]); + for (uint256 i = 0; i < _tokenIds.length; i++) { + balances[_tokenIds[i]][_account] = balances[_tokenIds[i]][_account] + .sub(_values[i]); } - emit TransferBatch(msg.sender, _account, address(0), _tokenIds, _values); + emit TransferBatch( + msg.sender, + _account, + address(0), + _tokenIds, + _values + ); } - // // // // // // // // - // METADATA EXTENSIONS - // // // // // // // // - + // METADATA EXTENSIONS + // // // // // // // // + /** * @notice Setting the URL prefix for tokens metadata * @param _newBase New prefix to be used */ - function _setMetadataBase(string memory _newBase) - public - onlyOwner - { + function _setMetadataBase(string memory _newBase) public onlyOwner { metadataBase = _newBase; } - - + /** * @notice A distinct Uniform Resource Identifier (URI) for a given token. * @dev ERC-1155 - * URIs are defined in RFC 3986. The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". + * URIs are defined in RFC 3986. The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". * @param _tokenId The ID of the token * @return Full URI string for metadata of the _tokenId - */ - function uri(uint256 _tokenId) - external view - returns (string memory) - { - return string(abi.encodePacked(metadataBase, _uint2str(_tokenId), ".json")); + */ + function uri(uint256 _tokenId) external view returns (string memory) { + return + string( + abi.encodePacked(metadataBase, _uint2str(_tokenId), ".json") + ); } - /** * @notice A descriptive name for a collection of NFTs in this contract * @dev ERC-721 - */ - function name() - external pure - returns (string memory _name) - { + */ + function name() external pure returns (string memory _name) { return "Boson Smart Voucher"; } /** * @notice An abbreviated name for NFTs in this contract * @dev ERC-721 - */ - function symbol() - external pure - returns (string memory _symbol) - { + */ + function symbol() external pure returns (string memory _symbol) { return "BSV"; } @@ -719,20 +776,19 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { * @dev ERC-721 * Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC 3986. The URI may point to a JSON file that conforms to the "ERC721 Metadata JSON Schema". * @param _tokenId ID of the token - */ - function tokenURI(uint256 _tokenId) - external view - returns (string memory) - { + */ + function tokenURI(uint256 _tokenId) external view returns (string memory) { require(owners721[_tokenId] != address(0), "INVALID_ID"); - return string(abi.encodePacked(metadataBase, _uint2str(_tokenId), ".json")); + return + string( + abi.encodePacked(metadataBase, _uint2str(_tokenId), ".json") + ); } - - + + // // // // // // // // + // UTILS // // // // // // // // - // UTILS - // // // // // // // // - + /** * @notice Set the address of the VoucherKernel contract * @param _voucherKernelAddress The address of the Voucher Kernel contract @@ -741,10 +797,10 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { external onlyOwner { - require(_voucherKernelAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + require(_voucherKernelAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + voucherKernelAddress = _voucherKernelAddress; - + emit LogVoucherKernelSet(_voucherKernelAddress, msg.sender); } @@ -758,40 +814,38 @@ contract ERC1155ERC721 is IERC1155, IERC721, IERC1155ERC721 { { bosonRouterAddress = _bosonRouterAddress; emit LogBosonRouterSet(_bosonRouterAddress, msg.sender); - } - function getBosonRouterAddress() public view returns (address){ + function getBosonRouterAddress() public view returns (address) { address(bosonRouterAddress); } - - + /** * @notice Convert UINT to string * Thank you, Oraclize (aka Provable)! * https://github.com/provable-things/ethereum-api/blob/master/provableAPI_0.5.sol * @param _i uint parameter */ - function _uint2str(uint256 _i) - internal pure + function _uint2str(uint256 _i) + internal + pure returns (string memory _uintAsString) { if (_i == 0) { return "0"; } - uint j = _i; - uint len; + uint256 j = _i; + uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); - uint k = len - 1; + uint256 k = len - 1; while (_i != 0) { - bstr[k--] = byte(uint8(48 + _i % 10)); + bstr[k--] = bytes1(uint8(48 + (_i % 10))); _i /= 10; } - return string(bstr); + return string(bstr); } - -} \ No newline at end of file +} diff --git a/contracts/ERC20WithPermit.sol b/contracts/ERC20WithPermit.sol index 3c3e9bf2..4c2e2b91 100644 --- a/contracts/ERC20WithPermit.sol +++ b/contracts/ERC20WithPermit.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -pragma solidity >=0.6.6; +pragma solidity >=0.6.6 <0.7.0; import "./IERC20WithPermit.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; @@ -9,14 +9,19 @@ contract ERC20WithPermit is IERC20WithPermit { string public override name; string public override symbol; + // solhint-disable-next-line const-name-snakecase uint8 public constant override decimals = 18; uint256 public override totalSupply; mapping(address => uint256) public override balanceOf; mapping(address => mapping(address => uint256)) public override allowance; - bytes32 public override DOMAIN_SEPARATOR; //prevents collision of identical structures. Formed in the initialization of the contract - bytes32 public override constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; //representation of keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + // prevents collision of identical structures. Formed in the initialization of the contract + // solhint-disable-next-line var-name-mixedcase + bytes32 public override DOMAIN_SEPARATOR; + // representation of keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); + bytes32 public constant override PERMIT_TYPEHASH = + 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint256) public override nonces; event Approval( @@ -122,22 +127,23 @@ contract ERC20WithPermit is IERC20WithPermit { ) external override { require(deadline >= block.timestamp, "ERC20WithPermit: EXPIRED"); - bytes32 digest = keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256( - abi.encode( - PERMIT_TYPEHASH, - owner, - spender, - value, - nonces[owner]++, - deadline + bytes32 digest = + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR, + keccak256( + abi.encode( + PERMIT_TYPEHASH, + owner, + spender, + value, + nonces[owner]++, + deadline + ) ) ) - ) - ); + ); address recoveredAddress = ecrecover(digest, v, r, s); require( diff --git a/contracts/FundLimitsOracle.sol b/contracts/FundLimitsOracle.sol index 3ec1124b..f052796d 100644 --- a/contracts/FundLimitsOracle.sol +++ b/contracts/FundLimitsOracle.sol @@ -4,21 +4,13 @@ pragma solidity >=0.6.6 <0.7.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "./IFundLimitsOracle.sol"; - contract FundLimitsOracle is Ownable, IFundLimitsOracle { - uint256 private ethLimit; - mapping (address => uint256) private tokenLimits; + mapping(address => uint256) private tokenLimits; - event LogETHLimitChanged( - uint256 _newLimit, - address _triggeredBy - ); + event LogETHLimitChanged(uint256 _newLimit, address _triggeredBy); - event LogTokenLimitChanged( - uint256 _newLimit, - address _triggeredBy - ); + event LogTokenLimitChanged(uint256 _newLimit, address _triggeredBy); modifier notZeroAddress(address tokenAddress) { require(tokenAddress != address(0), "INVALID_TOKEN_ADDRESS"); @@ -29,25 +21,21 @@ contract FundLimitsOracle is Ownable, IFundLimitsOracle { ethLimit = 1 ether; } - /** - * @notice Set new limit for ETH. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. - * @param _newLimit New limit which will be set. - */ - function setETHLimit(uint256 _newLimit) - external - override - onlyOwner - { + /** + * @notice Set new limit for ETH. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. + * @param _newLimit New limit which will be set. + */ + function setETHLimit(uint256 _newLimit) external override onlyOwner { ethLimit = _newLimit; emit LogETHLimitChanged(_newLimit, owner()); } - /** - * @notice Set new limit for a token. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. - * @param _tokenAddress Address of the token which will be updated. - * @param _newLimit New limit which will be set. It must comply to the decimals of the token, so the limit is set in the correct decimals. - */ - function setTokenLimit(address _tokenAddress, uint256 _newLimit) + /** + * @notice Set new limit for a token. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. + * @param _tokenAddress Address of the token which will be updated. + * @param _newLimit New limit which will be set. It must comply to the decimals of the token, so the limit is set in the correct decimals. + */ + function setTokenLimit(address _tokenAddress, uint256 _newLimit) external override onlyOwner @@ -58,22 +46,26 @@ contract FundLimitsOracle is Ownable, IFundLimitsOracle { } // // // // // // // // - // GETTERS - // // // // // // // // + // GETTERS + // // // // // // // // - /** - * @notice Get the maximum allowed ETH limit to set as price of voucher, buyer deposit or seller deposit. - */ - function getETHLimit() external override view returns(uint256) { + /** + * @notice Get the maximum allowed ETH limit to set as price of voucher, buyer deposit or seller deposit. + */ + function getETHLimit() external view override returns (uint256) { return ethLimit; } - /** - * @notice Get the maximum allowed token limit for the specified Token. - * @param _tokenAddress Address of the token which will be update. - */ - function getTokenLimit(address _tokenAddress) external override view returns(uint256) { + /** + * @notice Get the maximum allowed token limit for the specified Token. + * @param _tokenAddress Address of the token which will be update. + */ + function getTokenLimit(address _tokenAddress) + external + view + override + returns (uint256) + { return tokenLimits[_tokenAddress]; } - -} \ No newline at end of file +} diff --git a/contracts/IBosonRouter.sol b/contracts/IBosonRouter.sol index aeac93ad..13b771ad 100644 --- a/contracts/IBosonRouter.sol +++ b/contracts/IBosonRouter.sol @@ -3,7 +3,6 @@ pragma solidity >=0.6.6 <0.7.0; interface IBosonRouter { - //TODO Write comments function pause() external; @@ -23,11 +22,11 @@ interface IBosonRouter { uint256 _depositBu = metadata[4]; uint256 _quantity = metadata[5]; */ - function requestCreateOrder_ETH_ETH(uint256[] calldata metadata) + function requestCreateOrderETHETH(uint256[] calldata metadata) external payable; - function requestCreateOrder_TKN_TKN_WithPermit( + function requestCreateOrderTKNTKNWithPermit( address _tokenPriceAddress, address _tokenDepositAddress, uint256 _tokensSent, @@ -36,10 +35,9 @@ interface IBosonRouter { bytes32 r, bytes32 s, uint256[] calldata metadata - ) - external; + ) external; - function requestCreateOrder_ETH_TKN_WithPermit( + function requestCreateOrderETHTKNWithPermit( address _tokenDepositAddress, uint256 _tokensSent, uint256 deadline, @@ -47,119 +45,130 @@ interface IBosonRouter { bytes32 r, bytes32 s, uint256[] calldata metadata - ) - external; + ) external; - function requestCreateOrder_TKN_ETH( + function requestCreateOrderTKNETH( address _tokenPriceAddress, uint256[] calldata metadata - ) - external - payable; + ) external payable; /** - * @notice Consumer requests/buys a voucher by filling an order and receiving a Voucher Token in return - * @param _tokenIdSupply ID of the supply token - * @param _issuer Address of the issuer of the supply token + * @notice Consumer requests/buys a voucher by filling an order and receiving a Voucher Token in return + * @param _tokenIdSupply ID of the supply token + * @param _issuer Address of the issuer of the supply token */ - function requestVoucher_ETH_ETH(uint256 _tokenIdSupply, address _issuer) + function requestVoucherETHETH(uint256 _tokenIdSupply, address _issuer) external payable; - - function requestVoucher_TKN_TKN_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherTKNTKNWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensSent, uint256 deadline, - uint8 vPrice, bytes32 rPrice, bytes32 sPrice, // tokenPrice - uint8 vDeposit, bytes32 rDeposit, bytes32 sDeposit // tokenDeposits - ) - external; - - - function requestVoucher_TKN_TKN_Same_WithPermit( - uint256 _tokenIdSupply, + uint8 vPrice, + bytes32 rPrice, + bytes32 sPrice, // tokenPrice + uint8 vDeposit, + bytes32 rDeposit, + bytes32 sDeposit // tokenDeposits + ) external; + + function requestVoucherTKNTKNSameWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensSent, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external; + uint8 v, + bytes32 r, + bytes32 s + ) external; - function requestVoucher_ETH_TKN_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherETHTKNWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensDeposit, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external - payable; + uint8 v, + bytes32 r, + bytes32 s + ) external payable; - function requestVoucher_TKN_ETH_WithPermit( - uint256 _tokenIdSupply, + function requestVoucherTKNETHWithPermit( + uint256 _tokenIdSupply, address _issuer, uint256 _tokensPrice, uint256 deadline, - uint8 v, bytes32 r, bytes32 s - ) - external - payable; + uint8 v, + bytes32 r, + bytes32 s + ) external payable; /** - * @notice Redemption of the vouchers promise - * @param _tokenIdVoucher ID of the voucher - */ + * @notice Redemption of the vouchers promise + * @param _tokenIdVoucher ID of the voucher + */ function redeem(uint256 _tokenIdVoucher) external; /** - * @notice Refunding a voucher - * @param _tokenIdVoucher ID of the voucher - */ + * @notice Refunding a voucher + * @param _tokenIdVoucher ID of the voucher + */ function refund(uint256 _tokenIdVoucher) external; /** - * @notice Issue a complain for a voucher - * @param _tokenIdVoucher ID of the voucher - */ + * @notice Issue a complain for a voucher + * @param _tokenIdVoucher ID of the voucher + */ function complain(uint256 _tokenIdVoucher) external; /** - * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal - * @param _tokenIdVoucher ID of the voucher - */ + * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal + * @param _tokenIdVoucher ID of the voucher + */ function cancelOrFault(uint256 _tokenIdVoucher) external; /** - * @notice Hook which will be triggered when a _tokenIdVoucher will be transferred. Escrow funds should be allocated to the new owner. - * @param _from prev owner of the _tokenIdVoucher - * @param _to next owner of the _tokenIdVoucher - * @param _tokenIdVoucher _tokenIdVoucher that has been transferred - */ - function _onERC721Transfer(address _from, address _to, uint256 _tokenIdVoucher) external; + * @notice Hook which will be triggered when a _tokenIdVoucher will be transferred. Escrow funds should be allocated to the new owner. + * @param _from prev owner of the _tokenIdVoucher + * @param _to next owner of the _tokenIdVoucher + * @param _tokenIdVoucher _tokenIdVoucher that has been transferred + */ + function _onERC721Transfer( + address _from, + address _to, + uint256 _tokenIdVoucher + ) external; /** - * @notice Pre-validation when a transfer from the the Tokens contract is triggered. Only the whole supply is allowed for transfer, otherwise reverts. - * @param _from owner of the _tokenSupplyId - * @param _tokenSupplyId _tokenSupplyId which will be validated - * @param _value qty which is desired to be transferred - */ - function _beforeERC1155Transfer(address _from, uint256 _tokenSupplyId, uint256 _value) external view; + * @notice Pre-validation when a transfer from the the Tokens contract is triggered. Only the whole supply is allowed for transfer, otherwise reverts. + * @param _from owner of the _tokenSupplyId + * @param _tokenSupplyId _tokenSupplyId which will be validated + * @param _value qty which is desired to be transferred + */ + function _beforeERC1155Transfer( + address _from, + uint256 _tokenSupplyId, + uint256 _value + ) external view; /** - * @notice After the transfer happens the _tokenSupplyId should be updated in the promise. Escrow funds for the deposits (If in ETH) should be allocated to the new owner as well. - * @param _from prev owner of the _tokenSupplyId - * @param _to next owner of the _tokenSupplyId - * @param _tokenSupplyId _tokenSupplyId for transfer - * @param _value qty which has been transferred - */ - function _onERC1155Transfer(address _from, address _to, uint256 _tokenSupplyId, uint256 _value) external; + * @notice After the transfer happens the _tokenSupplyId should be updated in the promise. Escrow funds for the deposits (If in ETH) should be allocated to the new owner as well. + * @param _from prev owner of the _tokenSupplyId + * @param _to next owner of the _tokenSupplyId + * @param _tokenSupplyId _tokenSupplyId for transfer + * @param _value qty which has been transferred + */ + function _onERC1155Transfer( + address _from, + address _to, + uint256 _tokenSupplyId, + uint256 _value + ) external; /** - * @notice Set the address of the ERC1155ERC721 contract - * @param _tokensContractAddress The address of the ERC1155ERC721 contract - */ + * @notice Set the address of the ERC1155ERC721 contract + * @param _tokensContractAddress The address of the ERC1155ERC721 contract + */ function setTokenContractAddress(address _tokensContractAddress) external; - -} \ No newline at end of file +} diff --git a/contracts/ICashier.sol b/contracts/ICashier.sol index b826d964..758666b0 100644 --- a/contracts/ICashier.sol +++ b/contracts/ICashier.sol @@ -3,21 +3,19 @@ pragma solidity >=0.6.6 <0.7.0; interface ICashier { - /** - * @notice Pause the Cashier && the Voucher Kernel contracts in case of emergency. - * All functions related to creating new batch, requestVoucher or withdraw will be paused, hence cannot be executed. - * There is special function for withdrawing funds if contract is paused. - */ + * @notice Pause the Cashier && the Voucher Kernel contracts in case of emergency. + * All functions related to creating new batch, requestVoucher or withdraw will be paused, hence cannot be executed. + * There is special function for withdrawing funds if contract is paused. + */ function pause() external; - + /** - * @notice Unpause the Cashier && the Voucher Kernel contracts. - * All functions related to creating new batch, requestVoucher or withdraw will be unpaused. - */ + * @notice Unpause the Cashier && the Voucher Kernel contracts. + * All functions related to creating new batch, requestVoucher or withdraw will be unpaused. + */ function unpause() external; - /** * @notice Trigger withdrawals of what funds are releasable * The caller of this function triggers transfers to all involved entities (pool, issuer, token holder), also paying for gas. @@ -34,36 +32,34 @@ interface ICashier { */ function withdrawWhenPaused(uint256 _tokenIdVoucher) external; - /** - * @notice Seller triggers withdrawals of remaining deposits for a given supply, in case the contracts are paused. - * @param _tokenIdSupply an ID of a supply token (ERC-1155) which will be burned and deposits will be returned for - */ + * @notice Seller triggers withdrawals of remaining deposits for a given supply, in case the contracts are paused. + * @param _tokenIdSupply an ID of a supply token (ERC-1155) which will be burned and deposits will be returned for + */ function withdrawDeposits(uint256 _tokenIdSupply) external; - /** * @notice Trigger withdrawals of pooled funds - */ + */ function withdrawPool() external; /** - * @notice Get the amount in escrow of an address - * @param _account The address of an account to query - */ + * @notice Get the amount in escrow of an address + * @param _account The address of an account to query + * @return The balance in escrow + */ function getEscrowAmount(address _account) external view returns (uint256); /** - * @notice Update the amount in escrow of an address wit the new value, based on VoucherSet/Voucher interaction - * @param _account The address of an account to query - * @param _newAmount New amount to be set - */ + * @notice Update the amount in escrow of an address wit the new value, based on VoucherSet/Voucher interaction + * @param _account The address of an account to query + * @param _newAmount New amount to be set + */ function updateEscrowAmount(address _account, uint256 _newAmount) external; - /** + /** * @notice Set the address of the BR contract * @param _bosonRouterAddress The address of the Cashier contract */ function setBosonRouterAddress(address _bosonRouterAddress) external; - -} \ No newline at end of file +} diff --git a/contracts/IERC1155.sol b/contracts/IERC1155.sol index 2629dd4d..a717ca29 100644 --- a/contracts/IERC1155.sol +++ b/contracts/IERC1155.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -pragma solidity >=0.6.0 <0.7.0; +pragma solidity >=0.6.6 <0.7.0; /** @title ERC-1155 Multi Token Standard @dev See https://eips.ethereum.org/EIPS/eip-1155 Note: The ERC-165 identifier for this interface is 0xd9b67a26. */ -interface IERC1155 /* is IERC165 */ { +/* is IERC165 */ +interface IERC1155 { /** @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). @@ -18,7 +19,13 @@ interface IERC1155 /* is IERC165 */ { When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). */ - event TransferSingle(address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value); + event TransferSingle( + address indexed _operator, + address indexed _from, + address indexed _to, + uint256 _id, + uint256 _value + ); /** @dev Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). @@ -30,12 +37,22 @@ interface IERC1155 /* is IERC165 */ { When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). */ - event TransferBatch(address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values); + event TransferBatch( + address indexed _operator, + address indexed _from, + address indexed _to, + uint256[] _ids, + uint256[] _values + ); /** @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). */ - event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + event ApprovalForAll( + address indexed _owner, + address indexed _operator, + bool _approved + ); /** @dev MUST emit when the URI is updated for a token ID. @@ -58,7 +75,13 @@ interface IERC1155 /* is IERC165 */ { @param _value Transfer amount @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` */ - function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; + function safeTransferFrom( + address _from, + address _to, + uint256 _id, + uint256 _value, + bytes calldata _data + ) external; /** @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). @@ -76,7 +99,13 @@ interface IERC1155 /* is IERC165 */ { @param _values Transfer amounts per token type (order and length must match _ids array) @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` */ - function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external; + function safeBatchTransferFrom( + address _from, + address _to, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) external; /** @notice Get the balance of an account's tokens. @@ -84,7 +113,10 @@ interface IERC1155 /* is IERC165 */ { @param _id ID of the token @return The _owner's balance of the token type requested */ - function balanceOf(address _owner, uint256 _id) external view returns (uint256); + function balanceOf(address _owner, uint256 _id) + external + view + returns (uint256); /** @notice Get the balance of multiple account/token pairs @@ -92,7 +124,10 @@ interface IERC1155 /* is IERC165 */ { @param _ids ID of the tokens @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) */ - function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory); + function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) + external + view + returns (uint256[] memory); /** @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. @@ -108,5 +143,8 @@ interface IERC1155 /* is IERC165 */ { @param _operator Address of authorized operator @return True if the operator is approved, false if not */ - function isApprovedForAll(address _owner, address _operator) external view returns (bool); -} \ No newline at end of file + function isApprovedForAll(address _owner, address _operator) + external + view + returns (bool); +} diff --git a/contracts/IERC1155ERC721.sol b/contracts/IERC1155ERC721.sol index 3e18aa29..f86cb879 100644 --- a/contracts/IERC1155ERC721.sol +++ b/contracts/IERC1155ERC721.sol @@ -3,7 +3,6 @@ pragma solidity >=0.6.6 <0.7.0; interface IERC1155ERC721 { - /** * @notice Mint an amount of a desired token * Currently no restrictions as to who is allowed to mint - so, it is external. @@ -13,8 +12,13 @@ interface IERC1155ERC721 { * @param _value Amount of the token to be minted * @param _data Additional data forwarded to onERC1155BatchReceived if _to is a contract */ - function mint(address _to, uint256 _tokenId, uint256 _value, bytes calldata _data) external; - + function mint( + address _to, + uint256 _tokenId, + uint256 _value, + bytes calldata _data + ) external; + /** * @notice Burn an amount of tokens with the given ID * @dev ERC-1155 @@ -22,7 +26,11 @@ interface IERC1155ERC721 { * @param _tokenId ID of the token * @param _value Amount of the token */ - function burn(address _account, uint256 _tokenId, uint256 _value) external; + function burn( + address _account, + uint256 _tokenId, + uint256 _value + ) external; /** * @notice Function to mint tokens. @@ -32,5 +40,4 @@ interface IERC1155ERC721 { * @return A boolean that indicates if the operation was successful. */ function mint(address to, uint256 tokenId) external returns (bool); - -} \ No newline at end of file +} diff --git a/contracts/IERC1155TokenReceiver.sol b/contracts/IERC1155TokenReceiver.sol index 0c0b9bad..deec6d7f 100644 --- a/contracts/IERC1155TokenReceiver.sol +++ b/contracts/IERC1155TokenReceiver.sol @@ -19,7 +19,13 @@ interface ERC1155TokenReceiver { @param _data Additional data with no specified format @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` */ - function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4); + function onERC1155Received( + address _operator, + address _from, + uint256 _id, + uint256 _value, + bytes calldata _data + ) external returns (bytes4); /** @notice Handle the receipt of multiple ERC1155 token types. @@ -34,5 +40,11 @@ interface ERC1155TokenReceiver { @param _data Additional data with no specified format @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` */ - function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4); -} \ No newline at end of file + function onERC1155BatchReceived( + address _operator, + address _from, + uint256[] calldata _ids, + uint256[] calldata _values, + bytes calldata _data + ) external returns (bytes4); +} diff --git a/contracts/IERC20WithPermit.sol b/contracts/IERC20WithPermit.sol index 65fbe59d..41593d70 100644 --- a/contracts/IERC20WithPermit.sol +++ b/contracts/IERC20WithPermit.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-or-later -pragma solidity >=0.6.0 <0.7.0; +pragma solidity >=0.6.6 <0.7.0; interface IERC20WithPermit { event Approval( @@ -34,12 +34,14 @@ interface IERC20WithPermit { uint256 value ) external returns (bool); + // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); + // solhint-disable-next-line func-name-mixedcase function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint256); - + function permit( address owner, address spender, @@ -49,5 +51,4 @@ interface IERC20WithPermit { bytes32 r, bytes32 s ) external; - -} \ No newline at end of file +} diff --git a/contracts/IERC721.sol b/contracts/IERC721.sol index 74693924..c2c02500 100644 --- a/contracts/IERC721.sol +++ b/contracts/IERC721.sol @@ -14,17 +14,29 @@ abstract contract IERC721 is IERC165 { /// (`to` == 0). Exception: during contract creation, any number of NFTs /// may be created and assigned without emitting Transfer. At the time of /// any transfer, the approved address for that NFT (if any) is reset to none. - event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); + event Transfer( + address indexed _from, + address indexed _to, + uint256 indexed _tokenId + ); /// @dev This emits when the approved address for an NFT is changed or /// reaffirmed. The zero address indicates there is no approved address. /// When a Transfer event emits, this also indicates that the approved /// address for that NFT (if any) is reset to none. - event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); + event Approval( + address indexed _owner, + address indexed _approved, + uint256 indexed _tokenId + ); /// @dev This emits when an operator is enabled or disabled for an owner. /// The operator can manage all NFTs of the owner. - event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); + event ApprovalForAll( + address indexed _owner, + address indexed _operator, + bool _approved + ); /// @notice Count all NFTs assigned to an owner /// @dev NFTs assigned to the zero address are considered invalid, and this @@ -52,7 +64,12 @@ abstract contract IERC721 is IERC165 { /// @param _to The new owner /// @param _tokenId The NFT to transfer /// @param data Additional data with no specified format, sent in call to `_to` - function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory data) public virtual; + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId, + bytes memory data + ) public virtual; /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, @@ -60,7 +77,11 @@ abstract contract IERC721 is IERC165 { /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer - function safeTransferFrom(address _from, address _to, uint256 _tokenId) public virtual; + function safeTransferFrom( + address _from, + address _to, + uint256 _tokenId + ) public virtual; /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE @@ -72,7 +93,11 @@ abstract contract IERC721 is IERC165 { /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer - function transferFrom(address _from, address _to, uint256 _tokenId) public virtual; + function transferFrom( + address _from, + address _to, + uint256 _tokenId + ) public virtual; /// @notice Change or reaffirm the approved address for an NFT /// @dev The zero address indicates there is no approved address. @@ -88,17 +113,27 @@ abstract contract IERC721 is IERC165 { /// multiple operators per owner. /// @param _operator Address to add to the set of authorized operators /// @param _approved True if the operator is approved, false to revoke approval - function setApprovalForAll(address _operator, bool _approved) external virtual; + function setApprovalForAll(address _operator, bool _approved) + external + virtual; /// @notice Get the approved address for a single NFT /// @dev Throws if `_tokenId` is not a valid NFT. /// @param _tokenId The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none - function getApproved(uint256 _tokenId) public view virtual returns (address); + function getApproved(uint256 _tokenId) + public + view + virtual + returns (address); /// @notice Query if an address is an authorized operator for another address /// @param _owner The address that owns the NFTs /// @param _operator The address that acts on behalf of the owner /// @return True if `_operator` is an approved operator for `_owner`, false otherwise - function isApprovedForAll(address _owner, address _operator) public view virtual returns (bool); -} \ No newline at end of file + function isApprovedForAll(address _owner, address _operator) + public + view + virtual + returns (bool); +} diff --git a/contracts/IERC721TokenReceiver.sol b/contracts/IERC721TokenReceiver.sol index bb549cc2..0f4fe8b3 100644 --- a/contracts/IERC721TokenReceiver.sol +++ b/contracts/IERC721TokenReceiver.sol @@ -16,5 +16,10 @@ interface ERC721TokenReceiver { /// @param _data Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` /// unless throwing - function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns(bytes4); -} \ No newline at end of file + function onERC721Received( + address _operator, + address _from, + uint256 _tokenId, + bytes calldata _data + ) external returns (bytes4); +} diff --git a/contracts/IFundLimitsOracle.sol b/contracts/IFundLimitsOracle.sol index aed724d2..2c4fa628 100644 --- a/contracts/IFundLimitsOracle.sol +++ b/contracts/IFundLimitsOracle.sol @@ -2,30 +2,31 @@ pragma solidity >=0.6.6 <0.7.0; - interface IFundLimitsOracle { - - /** - * @notice Set new limit for a token. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. - * @param _tokenAddress Address of the token which will be updated. - * @param _newLimit New limit which will be set. It must comply to the decimals of the token, so the limit is set in the correct decimals. - */ + /** + * @notice Set new limit for a token. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. + * @param _tokenAddress Address of the token which will be updated. + * @param _newLimit New limit which will be set. It must comply to the decimals of the token, so the limit is set in the correct decimals. + */ function setTokenLimit(address _tokenAddress, uint256 _newLimit) external; - /** - * @notice Get the maximum allowed token limit for the specified Token. - * @param _tokenAddress Address of the token which will be update. - */ - function getTokenLimit(address _tokenAddress) external view returns(uint256); + /** + * @notice Get the maximum allowed token limit for the specified Token. + * @param _tokenAddress Address of the token which will be update. + */ + function getTokenLimit(address _tokenAddress) + external + view + returns (uint256); - /** - * @notice Set new limit for ETH. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. - * @param _newLimit New limit which will be set. - */ + /** + * @notice Set new limit for ETH. It's used while seller tries to create a voucher. The limit is determined by a voucher set. Voucher price * quantity, seller deposit * quantity, buyer deposit * qty must be below the limit. + * @param _newLimit New limit which will be set. + */ function setETHLimit(uint256 _newLimit) external; - /** - * @notice Get the maximum allowed ETH limit to set as price of voucher, buyer deposit or seller deposit. - */ - function getETHLimit() external view returns(uint256); -} \ No newline at end of file + /** + * @notice Get the maximum allowed ETH limit to set as price of voucher, buyer deposit or seller deposit. + */ + function getETHLimit() external view returns (uint256); +} diff --git a/contracts/IVoucherKernel.sol b/contracts/IVoucherKernel.sol index c068a0ee..7fc05b36 100644 --- a/contracts/IVoucherKernel.sol +++ b/contracts/IVoucherKernel.sol @@ -3,234 +3,303 @@ pragma solidity >=0.6.6 <0.7.0; interface IVoucherKernel { - /** - * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. - * Only Cashier contract is in control of this function. - */ + * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. + * Only Cashier contract is in control of this function. + */ function pause() external; /** - * @notice Unpause the process of interaction with voucherID's (ERC-721). - * Only Cashier contract is in control of this function. - */ + * @notice Unpause the process of interaction with voucherID's (ERC-721). + * Only Cashier contract is in control of this function. + */ function unpause() external; /** - * @notice Creating a new promise for goods or services. - * Can be reused, e.g. for making different batches of these (but not in prototype). - * @param _seller seller of the promise - * @param _validFrom Start of valid period - * @param _validTo End of valid period - * @param _price Price (payment amount) - * @param _depositSe Seller's deposit - * @param _depositBu Buyer's deposit - */ - function createTokenSupplyID(address _seller, uint256 _validFrom, uint256 _validTo, uint256 _price, uint256 _depositSe, uint256 _depositBu, uint256 _quantity) external returns (uint256); - - /** - * @notice Creates a Payment method struct recording the details on how the seller requires to receive Price and Deposits for a certain Voucher Set. - * @param _tokenIdSupply _tokenIdSupply of the voucher set this is related to - * @param _paymentMethod might be ETH_ETH, ETH_TKN, TKN_ETH or TKN_TKN - * @param _tokenPrice token address which will hold the funds for the price of the voucher - * @param _tokenDeposits token address which will hold the funds for the deposits of the voucher - */ - function createPaymentMethod(uint256 _tokenIdSupply, uint8 _paymentMethod, address _tokenPrice, address _tokenDeposits) external; + * @notice Creating a new promise for goods or services. + * Can be reused, e.g. for making different batches of these (but not in prototype). + * @param _seller seller of the promise + * @param _validFrom Start of valid period + * @param _validTo End of valid period + * @param _price Price (payment amount) + * @param _depositSe Seller's deposit + * @param _depositBu Buyer's deposit + */ + function createTokenSupplyID( + address _seller, + uint256 _validFrom, + uint256 _validTo, + uint256 _price, + uint256 _depositSe, + uint256 _depositBu, + uint256 _quantity + ) external returns (uint256); + + /** + * @notice Creates a Payment method struct recording the details on how the seller requires to receive Price and Deposits for a certain Voucher Set. + * @param _tokenIdSupply _tokenIdSupply of the voucher set this is related to + * @param _paymentMethod might be ETHETH, ETHTKN, TKNETH or TKNTKN + * @param _tokenPrice token address which will hold the funds for the price of the voucher + * @param _tokenDeposits token address which will hold the funds for the deposits of the voucher + */ + function createPaymentMethod( + uint256 _tokenIdSupply, + uint8 _paymentMethod, + address _tokenPrice, + address _tokenDeposits + ) external; /** - * @notice Mark voucher token that the payment was released - * @param _tokenIdVoucher ID of the voucher token - */ + * @notice Mark voucher token that the payment was released + * @param _tokenIdVoucher ID of the voucher token + */ function setPaymentReleased(uint256 _tokenIdVoucher) external; /** - * @notice Mark voucher token that the deposits were released - * @param _tokenIdVoucher ID of the voucher token - */ + * @notice Mark voucher token that the deposits were released + * @param _tokenIdVoucher ID of the voucher token + */ function setDepositsReleased(uint256 _tokenIdVoucher) external; - + /** - * @notice Extract a standard non-fungible tokens ERC-721 from a supply stored in ERC-1155 - * @dev Token ID is derived following the same principles for both ERC-1155 and ERC-721 - * @param _issuer The address of the token issuer - * @param _tokenIdSupply ID of the token type - * @param _qty qty that should be burned - */ - function burnSupplyOnPause(address _issuer, uint256 _tokenIdSupply, uint256 _qty) external; + * @notice Extract a standard non-fungible tokens ERC-721 from a supply stored in ERC-1155 + * @dev Token ID is derived following the same principles for both ERC-1155 and ERC-721 + * @param _issuer The address of the token issuer + * @param _tokenIdSupply ID of the token type + * @param _qty qty that should be burned + */ + function burnSupplyOnPause( + address _issuer, + uint256 _tokenIdSupply, + uint256 _qty + ) external; /** - * @notice Redemption of the vouchers promise - * @param _tokenIdVoucher ID of the voucher - * @param _msgSender owner of the voucher - */ + * @notice Redemption of the vouchers promise + * @param _tokenIdVoucher ID of the voucher + * @param _msgSender owner of the voucher + */ function redeem(uint256 _tokenIdVoucher, address _msgSender) external; /** - * @notice Refunding a voucher - * @param _tokenIdVoucher ID of the voucher - * @param _msgSender owner of the voucher - */ + * @notice Refunding a voucher + * @param _tokenIdVoucher ID of the voucher + * @param _msgSender owner of the voucher + */ function refund(uint256 _tokenIdVoucher, address _msgSender) external; /** - * @notice Issue a complain for a voucher - * @param _tokenIdVoucher ID of the voucher - * @param _msgSender owner of the voucher - */ + * @notice Issue a complain for a voucher + * @param _tokenIdVoucher ID of the voucher + * @param _msgSender owner of the voucher + */ function complain(uint256 _tokenIdVoucher, address _msgSender) external; /** - * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal - * @param _tokenIdVoucher ID of the voucher - * @param _msgSender owner of the voucher set (seller) - */ - function cancelOrFault(uint256 _tokenIdVoucher, address _msgSender) external; + * @notice Cancel/Fault transaction by the Seller, admitting to a fault or backing out of the deal + * @param _tokenIdVoucher ID of the voucher + * @param _msgSender owner of the voucher set (seller) + */ + function cancelOrFault(uint256 _tokenIdVoucher, address _msgSender) + external; /** - * @notice Fill Voucher Order, iff funds paid, then extract & mint NFT to the voucher holder - * @param _tokenIdSupply ID of the supply token (ERC-1155) - * @param _issuer Address of the token's issuer - * @param _holder Address of the recipient of the voucher (ERC-721) - */ - function fillOrder(uint256 _tokenIdSupply, address _issuer, address _holder) external; + * @notice Fill Voucher Order, iff funds paid, then extract & mint NFT to the voucher holder + * @param _tokenIdSupply ID of the supply token (ERC-1155) + * @param _issuer Address of the token's issuer + * @param _holder Address of the recipient of the voucher (ERC-721) + */ + function fillOrder( + uint256 _tokenIdSupply, + address _issuer, + address _holder + ) external; /** - * @notice Mark voucher token as expired - * @param _tokenIdVoucher ID of the voucher token - */ + * @notice Mark voucher token as expired + * @param _tokenIdVoucher ID of the voucher token + */ function triggerExpiration(uint256 _tokenIdVoucher) external; /** - * @notice Mark voucher token to the final status - * @param _tokenIdVoucher ID of the voucher token - */ + * @notice Mark voucher token to the final status + * @param _tokenIdVoucher ID of the voucher token + */ function triggerFinalizeVoucher(uint256 _tokenIdVoucher) external; /** - * @notice Set the address of the new holder of a _tokenIdSupply on transfer - * @param _tokenIdSupply _tokenIdSupply which will be transferred - * @param _newSeller new holder of the supply - */ - function setSupplyHolderOnTransfer(uint256 _tokenIdSupply, address _newSeller) external; + * @notice Set the address of the new holder of a _tokenIdSupply on transfer + * @param _tokenIdSupply _tokenIdSupply which will be transferred + * @param _newSeller new holder of the supply + */ + function setSupplyHolderOnTransfer( + uint256 _tokenIdSupply, + address _newSeller + ) external; /** - * @notice Set the general cancelOrFault period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. - * @param _cancelFaultPeriod the new value for cancelOrFault period (in number of seconds) - */ + * @notice Set the general cancelOrFault period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. + * @param _cancelFaultPeriod the new value for cancelOrFault period (in number of seconds) + */ function setCancelFaultPeriod(uint256 _cancelFaultPeriod) external; /** - * @notice Set the address of the Cashier contract - * @param _cashierAddress The address of the Cashier contract - */ + * @notice Set the address of the Cashier contract + * @param _cashierAddress The address of the Cashier contract + */ function setCashierAddress(address _cashierAddress) external; /** - * @notice Set the general complain period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. - * @param _complainPeriod the new value for complain period (in number of seconds) - */ + * @notice Set the general complain period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. + * @param _complainPeriod the new value for complain period (in number of seconds) + */ function setComplainPeriod(uint256 _complainPeriod) external; /** - * @notice Get the promise ID at specific index - * @param _idx Index in the array of promise keys - * @return Promise ID - */ + * @notice Get the promise ID at specific index + * @param _idx Index in the array of promise keys + * @return Promise ID + */ function getPromiseKey(uint256 _idx) external view returns (bytes32); /** - * @notice Get the address of the token where the price for the supply is held - * @param _tokenIdSupply ID of the voucher token - * @return Address of the token - */ - function getVoucherPriceToken(uint256 _tokenIdSupply) external view returns (address); + * @notice Get the address of the token where the price for the supply is held + * @param _tokenIdSupply ID of the voucher token + * @return Address of the token + */ + function getVoucherPriceToken(uint256 _tokenIdSupply) + external + view + returns (address); /** - * @notice Get the address of the token where the deposits for the supply are held - * @param _tokenIdSupply ID of the voucher token - * @return Address of the token - */ - function getVoucherDepositToken(uint256 _tokenIdSupply) external view returns (address); + * @notice Get the address of the token where the deposits for the supply are held + * @param _tokenIdSupply ID of the voucher token + * @return Address of the token + */ + function getVoucherDepositToken(uint256 _tokenIdSupply) + external + view + returns (address); /** - * @notice Get Buyer costs required to make an order for a supply token - * @param _tokenIdSupply ID of the supply token - * @return returns a tuple (Payment amount, Buyer's deposit) - */ - function getBuyerOrderCosts(uint256 _tokenIdSupply) external view returns (uint256, uint256); + * @notice Get Buyer costs required to make an order for a supply token + * @param _tokenIdSupply ID of the supply token + * @return returns a tuple (Payment amount, Buyer's deposit) + */ + function getBuyerOrderCosts(uint256 _tokenIdSupply) + external + view + returns (uint256, uint256); /** - * @notice Get Seller deposit - * @param _tokenIdSupply ID of the supply token - * @return returns sellers deposit - */ - function getSellerDeposit(uint256 _tokenIdSupply) external view returns (uint256); + * @notice Get Seller deposit + * @param _tokenIdSupply ID of the supply token + * @return returns sellers deposit + */ + function getSellerDeposit(uint256 _tokenIdSupply) + external + view + returns (uint256); /** - * @notice Get the promise ID from a voucher token - * @param _tokenIdVoucher ID of the voucher token - * @return ID of the promise - */ - function getIdSupplyFromVoucher(uint256 _tokenIdVoucher) external pure returns (uint256); + * @notice Get the promise ID from a voucher token + * @param _tokenIdVoucher ID of the voucher token + * @return ID of the promise + */ + function getIdSupplyFromVoucher(uint256 _tokenIdVoucher) + external + pure + returns (uint256); /** * @notice Get the promise ID from a voucher token * @param _tokenIdVoucher ID of the voucher token * @return ID of the promise */ - function getPromiseIdFromVoucherId(uint256 _tokenIdVoucher) external view returns (bytes32); + function getPromiseIdFromVoucherId(uint256 _tokenIdVoucher) + external + view + returns (bytes32); /** - * @notice Get the current supply of tokens of an account - * @param _account Address to query - * @return Balance + * @notice Get the current supply of tokens of an account + * @param _account Address to query + * @return Balance */ function getTotalSupply(address _account) external view returns (uint256); /** - * @notice Get all necessary funds for a supply token - * @param _tokenIdSupply ID of the supply token - * @return returns a tuple (Payment amount, Seller's deposit, Buyer's deposit) - */ - function getOrderCosts(uint256 _tokenIdSupply) external view returns (uint256, uint256, uint256); - - /** - * @notice Get the remaining quantity left in supply of tokens (e.g ERC-721 left in ERC-1155) of an account - * @param _tokenSupplyId Token supply ID - * @param _owner holder of the Token Supply - * @return remaining quantity - */ - function getRemQtyForSupply(uint _tokenSupplyId, address _owner) external view returns (uint256); - - /** - * @notice Get the payment method for a particular _tokenIdSupply - * @param _tokenIdSupply ID of the voucher supply token - * @return payment method - */ - function getVoucherPaymentMethod(uint256 _tokenIdSupply) external view returns (uint8); + * @notice Get all necessary funds for a supply token + * @param _tokenIdSupply ID of the supply token + * @return returns a tuple (Payment amount, Seller's deposit, Buyer's deposit) + */ + function getOrderCosts(uint256 _tokenIdSupply) + external + view + returns ( + uint256, + uint256, + uint256 + ); + + /** + * @notice Get the remaining quantity left in supply of tokens (e.g ERC-721 left in ERC-1155) of an account + * @param _tokenSupplyId Token supply ID + * @param _owner holder of the Token Supply + * @return remaining quantity + */ + function getRemQtyForSupply(uint256 _tokenSupplyId, address _owner) + external + view + returns (uint256); /** - * @notice Get the current status of a voucher - * @param _tokenIdVoucher ID of the voucher token - * @return Status of the voucher (via enum) - */ - function getVoucherStatus(uint256 _tokenIdVoucher) external view returns (uint8, bool, bool); + * @notice Get the payment method for a particular _tokenIdSupply + * @param _tokenIdSupply ID of the voucher supply token + * @return payment method + */ + function getVoucherPaymentMethod(uint256 _tokenIdSupply) + external + view + returns (uint8); /** - * @notice Get the holder of a supply - * @param _tokenIdSupply ID of a promise which is mapped to the corresponding Promise - * @return Address of the holder - */ - function getSupplyHolder(uint256 _tokenIdSupply) external view returns (address); + * @notice Get the current status of a voucher + * @param _tokenIdVoucher ID of the voucher token + * @return Status of the voucher (via enum) + */ + function getVoucherStatus(uint256 _tokenIdVoucher) + external + view + returns ( + uint8, + bool, + bool + ); + + /** + * @notice Get the holder of a supply + * @param _tokenIdSupply ID of a promise which is mapped to the corresponding Promise + * @return Address of the holder + */ + function getSupplyHolder(uint256 _tokenIdSupply) + external + view + returns (address); /** - * @notice Get the holder of a voucher - * @param _tokenIdVoucher ID of the voucher token - * @return Address of the holder - */ - function getVoucherHolder(uint256 _tokenIdVoucher) external view returns (address); - - - function isInValidityPeriod(uint256 _tokenIdVoucher) external view returns (bool); - -} \ No newline at end of file + * @notice Get the holder of a voucher + * @param _tokenIdVoucher ID of the voucher token + * @return Address of the holder + */ + function getVoucherHolder(uint256 _tokenIdVoucher) + external + view + returns (address); + + function isInValidityPeriod(uint256 _tokenIdVoucher) + external + view + returns (bool); +} diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 7e6dfe8c..9d794c83 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -3,23 +3,23 @@ pragma solidity >=0.6.6 <0.7.0; contract Migrations { - address public owner; - uint public last_completed_migration; + address public owner; + uint256 public lastCompletedMigration; - constructor() public { - owner = msg.sender; - } + constructor() public { + owner = msg.sender; + } - modifier restricted() { - if (msg.sender == owner) _; - } + modifier restricted() { + if (msg.sender == owner) _; + } - function setCompleted(uint completed) public restricted { - last_completed_migration = completed; - } + function setCompleted(uint256 completed) public restricted { + lastCompletedMigration = completed; + } - function upgrade(address new_address) public restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } + function upgrade(address newAddress) public restricted { + Migrations upgraded = Migrations(newAddress); + upgraded.setCompleted(lastCompletedMigration); + } } diff --git a/contracts/UsingHelpers.sol b/contracts/UsingHelpers.sol new file mode 100644 index 00000000..649d3103 --- /dev/null +++ b/contracts/UsingHelpers.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +pragma solidity >=0.6.6 <0.7.0; + +/** + * @title Utility contract to enable access to common structures + */ +contract UsingHelpers { + uint8 internal constant ONE = 1; + uint8 internal constant IDX_COMMIT = 7; + uint8 internal constant IDX_REDEEM = 6; + uint8 internal constant IDX_REFUND = 5; + uint8 internal constant IDX_EXPIRE = 4; + uint8 internal constant IDX_COMPLAIN = 3; + uint8 internal constant IDX_CANCEL_FAULT = 2; + uint8 internal constant IDX_FINAL = 1; + + /* Status of the voucher in 8 bits: + [7:COMMITTED] [6:REDEEMED] [5:REFUNDED] [4:EXPIRED] [3:COMPLAINED] [2:CANCELORFAULT] [1:FINAL] [1:/] + */ + + // Those are the payment methods we are using throughout the system. + // Depending on how to user choose to interact with it's funds we store the method, so we could distribute its tokens afterwise + uint8 internal constant ETHETH = 1; + uint8 internal constant ETHTKN = 2; + uint8 internal constant TKNETH = 3; + uint8 internal constant TKNTKN = 4; + + struct VoucherDetails { + uint256 tokenIdSupply; + uint256 tokenIdVoucher; + address payable issuer; + address payable holder; + uint256 price; + uint256 depositSe; + uint256 depositBu; + uint256 amount2pool; + uint256 amount2issuer; + uint256 amount2holder; + uint8 paymentMethod; + VoucherStatus currStatus; + } + + struct VoucherStatus { + uint8 status; + bool isPaymentReleased; + bool isDepositsReleased; + uint256 complainPeriodStart; + uint256 cancelFaultPeriodStart; + } + + function isStateCommitted(uint8 _status) internal pure returns (bool) { + return _status == setChange(0, IDX_COMMIT); + } + + function isStateRedemptionSigned(uint8 _status) + internal + pure + returns (bool) + { + return _status == setChange(setChange(0, IDX_COMMIT), IDX_REDEEM); + } + + function isStateRefunded(uint8 _status) internal pure returns (bool) { + return _status == setChange(setChange(0, IDX_COMMIT), IDX_REFUND); + } + + function isStateExpired(uint8 _status) internal pure returns (bool) { + return _status == setChange(setChange(0, IDX_COMMIT), IDX_EXPIRE); + } + + function isStatus(uint8 _status, uint8 _idx) internal pure returns (bool) { + return (_status >> _idx) & ONE == 1; + } + + function setChange(uint8 _status, uint8 _changeIdx) + internal + pure + returns (uint8) + { + return _status | (ONE << _changeIdx); + } +} diff --git a/contracts/VoucherKernel.sol b/contracts/VoucherKernel.sol index 99dd9ac2..0ea0c65f 100644 --- a/contracts/VoucherKernel.sol +++ b/contracts/VoucherKernel.sol @@ -12,41 +12,39 @@ import "./IERC721.sol"; import "./IERC1155ERC721.sol"; import "./IERC721TokenReceiver.sol"; import "./IVoucherKernel.sol"; -import "./usingHelpers.sol"; +import "./UsingHelpers.sol"; //preparing for ERC-1066, ERC-1444, EIP-838 /** * @title VoucherKernel contract is controlling the core business logic - * @dev Notes: - * - Since this is a demo app, it is not yet optimized. + * @dev Notes: + * - Since this is a demo app, it is not yet optimized. * In the next phase, the bulk raw data will be packed into a single bytes32 field and/or pushed off-chain. * - The usage of block.timestamp is honored since vouchers are defined with day-precision and the demo app is not covering all edge cases. * See: https://ethereum.stackexchange.com/questions/5924/how-do-ethereum-mining-nodes-maintain-a-time-consistent-with-the-network/5931#5931 -*/ -contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { + */ +contract VoucherKernel is IVoucherKernel, Ownable, Pausable, UsingHelpers { using Address for address; - using SafeMath for uint; + using SafeMath for uint256; //using Counters for Counters.Counter; //Counters.Counter private voucherTokenId; //unique IDs for voucher tokens - + //AssetRegistry assetRegistry; address public tokensContract; - + //promise for an asset could be reusable, but simplified here for brevitbytes32 struct Promise { bytes32 promiseId; - uint256 nonce; //the asset that is offered - address seller; //the seller who created the promise - + uint256 nonce; //the asset that is offered + address seller; //the seller who created the promise //we simplify the value for the demoapp, otherwise voucher details would be packed in one bytes32 field value uint256 validFrom; uint256 validTo; uint256 price; uint256 depositSe; uint256 depositBu; - - uint idx; + uint256 idx; } struct VoucherPaymentMethod { @@ -54,37 +52,37 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { address addressTokenPrice; address addressTokenDeposits; } - - address public bosonRouterAddress; //address of the Boson Router contract - address public cashierAddress; //address of the Cashier contract - - mapping(bytes32 => Promise) public promises; //promises to deliver goods or services + + address public bosonRouterAddress; //address of the Boson Router contract + address public cashierAddress; //address of the Cashier contract + + mapping(bytes32 => Promise) public promises; //promises to deliver goods or services mapping(address => uint256) public tokenNonces; //mapping between seller address and its own nonces. Every time seller creates supply ID it gets incremented. Used to avoid duplicate ID's - mapping (uint256 => VoucherPaymentMethod) public paymentDetails; // tokenSupplyId to VoucherPaymentMethod + mapping(uint256 => VoucherPaymentMethod) public paymentDetails; // tokenSupplyId to VoucherPaymentMethod bytes32[] public promiseKeys; - + mapping(address => uint256) public accountSupply; - mapping(uint256 => bytes32) public ordersPromise; //mapping between an order (supply token) and a promise - - mapping(uint256 => VoucherStatus) public vouchersStatus; //recording the vouchers evolution - mapping(uint256 => address) public voucherIssuers; //issuers of vouchers // TODO on refactoring this must be removed as if we are to transfer 1155, issuer should be fetched from the promise, not from the 721 - + mapping(uint256 => bytes32) public ordersPromise; //mapping between an order (supply token) and a promise + + mapping(uint256 => VoucherStatus) public vouchersStatus; //recording the vouchers evolution + mapping(uint256 => address) public voucherIssuers; //issuers of vouchers // TODO on refactoring this must be removed as if we are to transfer 1155, issuer should be fetched from the promise, not from the 721 + //standard reqs - mapping (uint256 => mapping(address => uint256)) private balances; //balance of token ids of an account - mapping (address => mapping(address => bool)) private operatorApprovals; //approval of accounts of an operator - + mapping(uint256 => mapping(address => uint256)) private balances; //balance of token ids of an account + mapping(address => mapping(address => bool)) private operatorApprovals; //approval of accounts of an operator + //ID reqs - mapping (uint256 => uint256) public typeCounters; //counter for ID of a particular type of NFT - uint256 public constant MASK_TYPE = uint256(uint128(~0)) << 128; //the type mask in the upper 128 bits -//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + mapping(uint256 => uint256) public typeCounters; //counter for ID of a particular type of NFT + uint256 public constant MASK_TYPE = uint256(uint128(~0)) << 128; //the type mask in the upper 128 bits + //1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + uint256 public constant MASK_NF_INDEX = uint128(~0); //the non-fungible index mask in the lower 128 + //0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - uint256 public constant MASK_NF_INDEX = uint128(~0); //the non-fungible index mask in the lower 128 -//0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 - uint256 public constant TYPE_NF_BIT = 1 << 255; //the first bit represents an NFT type -//1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - + //1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + uint256 public typeId; //base token type ... 127-bits cover 1.701411835*10^38 types (not differentiating between FTs and NFTs) /* Token IDs: Fungibles: 0, followed by 127-bit FT type ID, in the upper 128 bits, followed by 0 in lower 128-bits @@ -96,11 +94,10 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { Non-fungible vouchers: 1, followed by 127-bit NFT type ID, in the upper 128 bits, followed by a 1-based index of an NFT token ID. <1> */ - + uint256 public complainPeriod; //for demo purposes, this is fixed/set by owner uint256 public cancelFaultPeriod; //for demo purposes, this is fixed/set by owner - - + event LogPromiseCreated( bytes32 indexed _promiseId, uint256 indexed _nonce, @@ -110,148 +107,127 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { uint256 _idx ); - event LogVoucherDelivered( + event LogVoucherDelivered( uint256 indexed _tokenIdSupply, uint256 _tokenIdVoucher, address _issuer, address _holder, bytes32 _promiseId - ); - + ); + event LogVoucherRedeemed( uint256 _tokenIdVoucher, address _holder, bytes32 _promiseId ); - - event LogVoucherRefunded( - uint256 _tokenIdVoucher - ); - - event LogVoucherComplain( - uint256 _tokenIdVoucher - ); - - event LogVoucherFaultCancel( - uint256 _tokenIdVoucher - ); - - event LogExpirationTriggered( - uint256 _tokenIdVoucher, - address _triggeredBy - ); - - event LogFinalizeVoucher( - uint256 _tokenIdVoucher, - address _triggeredBy - ); - - event LogBosonRouterSet( - address _newBosonRouter, - address _triggeredBy - ); - event LogCashierSet( - address _newCashier, - address _triggeredBy - ); - + event LogVoucherRefunded(uint256 _tokenIdVoucher); + + event LogVoucherComplain(uint256 _tokenIdVoucher); + + event LogVoucherFaultCancel(uint256 _tokenIdVoucher); + + event LogExpirationTriggered(uint256 _tokenIdVoucher, address _triggeredBy); + + event LogFinalizeVoucher(uint256 _tokenIdVoucher, address _triggeredBy); + + event LogBosonRouterSet(address _newBosonRouter, address _triggeredBy); + + event LogCashierSet(address _newCashier, address _triggeredBy); + event LogComplainPeriodChanged( uint256 _newComplainPeriod, address _triggeredBy ); - + event LogCancelFaultPeriodChanged( uint256 _newCancelFaultPeriod, address _triggeredBy - ); - + ); + event LogFundsReleased( uint256 _tokenIdVoucher, - uint8 _type //0 .. payment, 1 .. deposits + uint8 _type //0 .. payment, 1 .. deposits ); - modifier onlyFromRouter() { - require(bosonRouterAddress != address(0), "UNSPECIFIED_BR"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(msg.sender == bosonRouterAddress, "UNAUTHORIZED_BR"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require(bosonRouterAddress != address(0), "UNSPECIFIED_BR"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(msg.sender == bosonRouterAddress, "UNAUTHORIZED_BR"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; } modifier onlyFromCashier() { - require(cashierAddress != address(0), "UNSPECIFIED_BR"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(msg.sender == cashierAddress, "UNAUTHORIZED_C"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require(cashierAddress != address(0), "UNSPECIFIED_BR"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(msg.sender == cashierAddress, "UNAUTHORIZED_C"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; } - + modifier onlyVoucherOwner(uint256 _tokenIdVoucher, address _sender) { //check authorization - require(IERC721(tokensContract).ownerOf(_tokenIdVoucher) == _sender, "UNAUTHORIZED_V"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require( + IERC721(tokensContract).ownerOf(_tokenIdVoucher) == _sender, + "UNAUTHORIZED_V" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) _; } - - constructor( - address _tokensContract - ) - public - { + + constructor(address _tokensContract) public { tokensContract = _tokensContract; - + complainPeriod = 7 * 1 days; cancelFaultPeriod = 7 * 1 days; } /** - * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. - * Only BR contract is in control of this function. - */ + * @notice Pause the process of interaction with voucherID's (ERC-721), in case of emergency. + * Only BR contract is in control of this function. + */ function pause() external override onlyFromRouter { _pause(); } /** - * @notice Unpause the process of interaction with voucherID's (ERC-721). - * Only BR contract is in control of this function. - */ + * @notice Unpause the process of interaction with voucherID's (ERC-721). + * Only BR contract is in control of this function. + */ function unpause() external override onlyFromRouter { _unpause(); - } - + } + /** - * @notice Creating a new promise for goods or services. - * Can be reused, e.g. for making different batches of these (but not in prototype). - * @param _seller seller of the promise - * @param _validFrom Start of valid period - * @param _validTo End of valid period - * @param _price Price (payment amount) - * @param _depositSe Seller's deposit - * @param _depositBu Buyer's deposit - */ + * @notice Creating a new promise for goods or services. + * Can be reused, e.g. for making different batches of these (but not in prototype). + * @param _seller seller of the promise + * @param _validFrom Start of valid period + * @param _validTo End of valid period + * @param _price Price (payment amount) + * @param _depositSe Seller's deposit + * @param _depositBu Buyer's deposit + */ function createTokenSupplyID( - address _seller, + address _seller, uint256 _validFrom, uint256 _validTo, uint256 _price, uint256 _depositSe, uint256 _depositBu, uint256 _quantity - ) - external - override - onlyFromRouter - returns (uint256) - { - - require(_validFrom <= _validTo, "INVALID_VALIDITY_FROM"); //hex"26" FISSION.code(FISSION.Category.Find, FISSION.Status.Above_Range_Overflow) - require(_validTo >= block.timestamp, "INVALID_VALIDITY_TO"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow) - + ) external override onlyFromRouter returns (uint256) { + require(_validFrom <= _validTo, "INVALID_VALIDITY_FROM"); //hex"26" FISSION.code(FISSION.Category.Find, FISSION.Status.Above_Range_Overflow) + require(_validTo >= block.timestamp, "INVALID_VALIDITY_TO"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow) + bytes32 key; - key = keccak256(abi.encodePacked(tokenNonces[_seller]++, _validFrom, _validTo)); - + key = keccak256( + abi.encodePacked(tokenNonces[_seller]++, _validFrom, _validTo) + ); + if (promiseKeys.length > 0) { - require(promiseKeys[promises[key].idx] != key, "PROMISE_ALREADY_EXISTS"); + require( + promiseKeys[promises[key].idx] != key, + "PROMISE_ALREADY_EXISTS" + ); } - + promises[key] = Promise({ promiseId: key, nonce: tokenNonces[_seller], @@ -263,11 +239,17 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { depositBu: _depositBu, idx: promiseKeys.length }); - + promiseKeys.push(key); - - emit LogPromiseCreated(key, tokenNonces[_seller], _seller, _validFrom, _validTo, //_price, _depositSe, _depositBu, _complainPeriod, _cancelFaultPeriod, - promiseKeys.length - 1); + + emit LogPromiseCreated( + key, + tokenNonces[_seller], + _seller, + _validFrom, + _validTo, //_price, _depositSe, _depositBu, _complainPeriod, _cancelFaultPeriod, + promiseKeys.length - 1 + ); return createOrder(_seller, key, _quantity); } @@ -275,7 +257,7 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { /** * @notice Creates a Payment method struct recording the details on how the seller requires to receive Price and Deposits for a certain Voucher Set. * @param _tokenIdSupply _tokenIdSupply of the voucher set this is related to - * @param _paymentMethod might be ETH_ETH, ETH_TKN, TKN_ETH or TKN_TKN + * @param _paymentMethod might be ETHETH, ETHTKN, TKNETH or TKNTKN * @param _tokenPrice token address which will hold the funds for the price of the voucher * @param _tokenDeposits token address which will hold the funds for the deposits of the voucher */ @@ -284,17 +266,11 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { uint8 _paymentMethod, address _tokenPrice, address _tokenDeposits - ) - external - override - onlyFromRouter - { - + ) external override onlyFromRouter { paymentDetails[_tokenIdSupply] = VoucherPaymentMethod({ paymentMethod: _paymentMethod, addressTokenPrice: _tokenPrice, addressTokenDeposits: _tokenDeposits - }); } @@ -305,69 +281,83 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @param _promiseId ID of a promise (simplified into asset for demo) * @param _quantity Quantity of assets on offer */ - function createOrder(address _seller, bytes32 _promiseId, uint256 _quantity) - private - returns (uint256) - { - require(_promiseId != bytes32(0), "UNSPECIFIED_PROMISE"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(promises[_promiseId].seller == _seller, "UNAUTHORIZED_CO"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + function createOrder( + address _seller, + bytes32 _promiseId, + uint256 _quantity + ) private returns (uint256) { + require(_promiseId != bytes32(0), "UNSPECIFIED_PROMISE"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require(promises[_promiseId].seller == _seller, "UNAUTHORIZED_CO"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) require(_quantity > 0, "INVALID_QUANTITY"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow) - + uint256 tokenIdSupply = generateTokenType(true); //create & assign a new non-fungible type - IERC1155ERC721(tokensContract).mint(_seller, tokenIdSupply, _quantity, ""); - + IERC1155ERC721(tokensContract).mint( + _seller, + tokenIdSupply, + _quantity, + "" + ); + ordersPromise[tokenIdSupply] = _promiseId; accountSupply[_seller] += _quantity; return tokenIdSupply; } - - + /** - * @notice Fill Voucher Order, iff funds paid, then extract & mint NFT to the voucher holder - * @param _tokenIdSupply ID of the supply token (ERC-1155) - * @param _issuer Address of the token's issuer - * @param _holder Address of the recipient of the voucher (ERC-721) - */ - function fillOrder(uint256 _tokenIdSupply, address _issuer, address _holder) - external - override - onlyFromRouter - - { + * @notice Fill Voucher Order, iff funds paid, then extract & mint NFT to the voucher holder + * @param _tokenIdSupply ID of the supply token (ERC-1155) + * @param _issuer Address of the token's issuer + * @param _holder Address of the recipient of the voucher (ERC-721) + */ + function fillOrder( + uint256 _tokenIdSupply, + address _issuer, + address _holder + ) external override onlyFromRouter { //checks checkOrderFillable(_tokenIdSupply, _issuer, _holder); //close order uint256 voucherTokenId = extract721(_issuer, _holder, _tokenIdSupply); - emit LogVoucherDelivered(_tokenIdSupply, voucherTokenId, _issuer, _holder, getPromiseIdFromVoucherId(voucherTokenId)); + emit LogVoucherDelivered( + _tokenIdSupply, + voucherTokenId, + _issuer, + _holder, + getPromiseIdFromVoucherId(voucherTokenId) + ); } - - + /** * @notice Check order is fillable * @dev Will throw if checks don't pass * @param _tokenIdSupply ID of the supply token - * @param _issuer Address of the token's issuer - * @param _holder Address of the recipient of the voucher (ERC-721) + * @param _issuer Address of the token's issuer + * @param _holder Address of the recipient of the voucher (ERC-721) */ - function checkOrderFillable(uint256 _tokenIdSupply, address _issuer, address _holder) - internal - view - { + function checkOrderFillable( + uint256 _tokenIdSupply, + address _issuer, + address _holder + ) internal view { require(_tokenIdSupply != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) if (_holder.isContract()) { - require(IERC165(_holder).supportsInterface(0x150b7a02), "UNSUPPORTED_ERC721_RECEIVED"); //hex"31" + require( + IERC165(_holder).supportsInterface(0x150b7a02), + "UNSUPPORTED_ERC721_RECEIVED" + ); //hex"31" //bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")) - } - - require(_holder != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - require(IERC1155(tokensContract).balanceOf(_issuer, _tokenIdSupply) > 0, "OFFER_EMPTY"); //hex"40" FISSION.code(FISSION.Category.Availability, FISSION.Status.Unavailable) - + } + + require(_holder != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + require( + IERC1155(tokensContract).balanceOf(_issuer, _tokenIdSupply) > 0, + "OFFER_EMPTY" + ); //hex"40" FISSION.code(FISSION.Category.Availability, FISSION.Status.Unavailable) } - /** * @notice Extract a standard non-fungible token ERC-721 from a supply stored in ERC-1155 @@ -377,31 +367,43 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @param _tokenIdSupply ID of the token type * @return ID of the voucher token */ - function extract721(address _issuer, address _to, uint256 _tokenIdSupply) - internal - returns (uint256) - { + function extract721( + address _issuer, + address _to, + uint256 _tokenIdSupply + ) internal returns (uint256) { if (_to.isContract()) { - require(ERC721TokenReceiver(_to).onERC721Received(_issuer, msg.sender, _tokenIdSupply, "") == ERC721TokenReceiver(_to).onERC721Received.selector, "UNSUPPORTED_ERC721_RECEIVED"); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) + require( + ERC721TokenReceiver(_to).onERC721Received( + _issuer, + msg.sender, + _tokenIdSupply, + "" + ) == ERC721TokenReceiver(_to).onERC721Received.selector, + "UNSUPPORTED_ERC721_RECEIVED" + ); //hex"10" FISSION.code(FISSION.Category.Permission, FISSION.Status.Disallowed_Stop) //bytes4(keccak256("onERC721Received(address,address,uint256,bytes)")) - } + } IERC1155ERC721(tokensContract).burn(_issuer, _tokenIdSupply, 1); // This is hardcoded as 1 on purpose accountSupply[_issuer]--; - - + //calculate tokenId - uint256 voucherTokenId = _tokenIdSupply | ++typeCounters[_tokenIdSupply]; - + uint256 voucherTokenId = + _tokenIdSupply | ++typeCounters[_tokenIdSupply]; + //set status - vouchersStatus[voucherTokenId].status = setChange(vouchersStatus[voucherTokenId].status, idxCommit); + vouchersStatus[voucherTokenId].status = setChange( + vouchersStatus[voucherTokenId].status, + IDX_COMMIT + ); vouchersStatus[voucherTokenId].isPaymentReleased = false; vouchersStatus[voucherTokenId].isDepositsReleased = false; - + //mint voucher NFT as ERC-721 IERC1155ERC721(tokensContract).mint(_to, voucherTokenId); voucherIssuers[voucherTokenId] = _issuer; //TODO THIS MIGHT NOT BE REQUIRED ANYMORE - + return voucherTokenId; } @@ -411,42 +413,39 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @param _issuer The address of the token issuer * @param _tokenIdSupply ID of the token type * @param _qty qty that should be burned - */ - function burnSupplyOnPause(address _issuer, uint256 _tokenIdSupply, uint256 _qty) - external - override - whenPaused - onlyFromCashier - { + */ + function burnSupplyOnPause( + address _issuer, + uint256 _tokenIdSupply, + uint256 _qty + ) external override whenPaused onlyFromCashier { IERC1155ERC721(tokensContract).burn(_issuer, _tokenIdSupply, _qty); accountSupply[_issuer] = accountSupply[_issuer].sub(_qty); } - - + /** * @notice Creating a new token type, serving as the base for tokenID generation for NFTs, and a de facto ID for FTs. * @param _isNonFungible Flag for generating NFT or FT * @return _tokenType Returns a newly generated token type - */ + */ function generateTokenType(bool _isNonFungible) internal returns (uint256 _tokenType) { typeId++; - + if (_isNonFungible) { - _tokenType = TYPE_NF_BIT | typeId << 128; //upper bit is 1, followed by sequence, leaving lower 128-bits as 0 + _tokenType = TYPE_NF_BIT | (typeId << 128); //upper bit is 1, followed by sequence, leaving lower 128-bits as 0 } else { _tokenType = typeId << 128; //upper bit is not set, followed by sequence, leaving lower 128-bits as 0 } - + //not needed: //assert(typeId= vouchersStatus[_tokenIdVoucher].complainPeriodStart + cancelFaultPeriod) { + } else if ( + block.timestamp >= + vouchersStatus[_tokenIdVoucher].complainPeriodStart + + cancelFaultPeriod + ) { //if COMPLAIN: then final after cof period mark = true; } - - } else if (isStatus(tStatus, idxCancelFault) && - block.timestamp >= vouchersStatus[_tokenIdVoucher].complainPeriodStart + complainPeriod - ) { + } else if ( + isStatus(tStatus, IDX_CANCEL_FAULT) && + block.timestamp >= + vouchersStatus[_tokenIdVoucher].complainPeriodStart + complainPeriod + ) { //if COF: then final after complain period mark = true; - - } else if (isStateRedemptionSigned(tStatus) || - isStateRefunded(tStatus)) { + } else if ( + isStateRedemptionSigned(tStatus) || isStateRefunded(tStatus) + ) { //if RDM/RFND NON_COMPLAIN: then final after complainPeriodStart + complainPeriod - if (block.timestamp >= vouchersStatus[_tokenIdVoucher].complainPeriodStart + complainPeriod) { + if ( + block.timestamp >= + vouchersStatus[_tokenIdVoucher].complainPeriodStart + + complainPeriod + ) { mark = true; } - } else if (isStateExpired(tStatus)) { //if EXP NON_COMPLAIN: then final after validTo + complainPeriod if (block.timestamp >= tPromise.validTo + complainPeriod) { mark = true; - } + } } - + if (mark) { - vouchersStatus[_tokenIdVoucher].status = setChange(tStatus, idxFinal); - emit LogFinalizeVoucher(_tokenIdVoucher, msg.sender); + vouchersStatus[_tokenIdVoucher].status = setChange( + tStatus, + IDX_FINAL + ); + emit LogFinalizeVoucher(_tokenIdVoucher, msg.sender); } // - } - - // // // // // // // // - // UTILS - // // // // // // // // + } + // // // // // // // // + // UTILS + // // // // // // // // /** * @notice Set the address of the new holder of a _tokenIdSupply on transfer * @param _tokenIdSupply _tokenIdSupply which will be transferred * @param _newSeller new holder of the supply - */ - function setSupplyHolderOnTransfer(uint256 _tokenIdSupply, address _newSeller) - external override onlyFromRouter - { + */ + function setSupplyHolderOnTransfer( + uint256 _tokenIdSupply, + address _newSeller + ) external override onlyFromRouter { bytes32 promiseKey = ordersPromise[_tokenIdSupply]; promises[promiseKey].seller = _newSeller; } @@ -755,14 +853,14 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { external onlyOwner { - require(_bosonRouterAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + require(_bosonRouterAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + bosonRouterAddress = _bosonRouterAddress; - + emit LogBosonRouterSet(_bosonRouterAddress, msg.sender); } - /** + /** * @notice Set the address of the Cashier contract * @param _cashierAddress The address of the BR contract */ @@ -771,14 +869,13 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { override onlyOwner { - require(_cashierAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + require(_cashierAddress != address(0), "UNSPECIFIED_ADDRESS"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + cashierAddress = _cashierAddress; - + emit LogCashierSet(_cashierAddress, msg.sender); } - - + /** * @notice Set the general complain period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. * @param _complainPeriod the new value for complain period (in number of seconds) @@ -789,11 +886,10 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { onlyOwner { complainPeriod = _complainPeriod; - + emit LogComplainPeriodChanged(_complainPeriod, msg.sender); } - - + /** * @notice Set the general cancelOrFault period, should be used sparingly as it has significant consequences. Here done simply for demo purposes. * @param _cancelFaultPeriod the new value for cancelOrFault period (in number of seconds) @@ -804,15 +900,14 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { onlyOwner { cancelFaultPeriod = _cancelFaultPeriod; - + emit LogCancelFaultPeriodChanged(_cancelFaultPeriod, msg.sender); - } - - + } + // // // // // // // // - // GETTERS - // // // // // // // // - + // GETTERS + // // // // // // // // + /** * @notice Get the promise ID at specific index * @param _idx Index in the array of promise keys @@ -826,8 +921,7 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { { return promiseKeys[_idx]; } - - + /** * @notice Get the supply token ID from a voucher token * @param _tokenIdVoucher ID of the voucher token @@ -841,8 +935,7 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { { return _tokenIdVoucher & MASK_TYPE; } - - + /** * @notice Get the promise ID from a voucher token * @param _tokenIdVoucher ID of the voucher token @@ -854,13 +947,12 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { override returns (bytes32) { - require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) - + require(_tokenIdVoucher != 0, "UNSPECIFIED_ID"); //hex"20" FISSION.code(FISSION.Category.Find, FISSION.Status.NotFound_Unequal_OutOfRange) + uint256 tokenIdSupply = getIdSupplyFromVoucher(_tokenIdVoucher); return promises[ordersPromise[tokenIdSupply]].promiseId; } - - + /** * @notice Get the current supply of tokens of an account * @param _account Address to query @@ -882,8 +974,8 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @param _owner holder of the Token Supply * @return remaining quantity */ - function getRemQtyForSupply(uint _tokenSupplyId, address _owner) - external + function getRemQtyForSupply(uint256 _tokenSupplyId, address _owner) + external view override returns (uint256) @@ -891,18 +983,27 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { return IERC1155(tokensContract).balanceOf(_owner, _tokenSupplyId); } - /** * @notice Get all necessary funds for a supply token * @param _tokenIdSupply ID of the supply token * @return returns a tuple (Payment amount, Seller's deposit, Buyer's deposit) */ function getOrderCosts(uint256 _tokenIdSupply) - public view override - returns (uint256, uint256, uint256) + public + view + override + returns ( + uint256, + uint256, + uint256 + ) { bytes32 promiseKey = ordersPromise[_tokenIdSupply]; - return (promises[promiseKey].price, promises[promiseKey].depositSe, promises[promiseKey].depositBu); + return ( + promises[promiseKey].price, + promises[promiseKey].depositSe, + promises[promiseKey].depositBu + ); } /** @@ -911,7 +1012,9 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @return returns a tuple (Payment amount, Buyer's deposit) */ function getBuyerOrderCosts(uint256 _tokenIdSupply) - public view override + public + view + override returns (uint256, uint256) { bytes32 promiseKey = ordersPromise[_tokenIdSupply]; @@ -919,55 +1022,70 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { } /** - * @notice Get Seller deposit + * @notice Get Seller deposit * @param _tokenIdSupply ID of the supply token * @return returns sellers deposit - */ + */ function getSellerDeposit(uint256 _tokenIdSupply) - public view override + public + view + override returns (uint256) { bytes32 promiseKey = ordersPromise[_tokenIdSupply]; return promises[promiseKey].depositSe; } - + /** * @notice Get the current status of a voucher * @param _tokenIdVoucher ID of the voucher token * @return Status of the voucher (via enum) */ function getVoucherStatus(uint256 _tokenIdVoucher) - public view override - returns (uint8, bool, bool) + public + view + override + returns ( + uint8, + bool, + bool + ) { - return (vouchersStatus[_tokenIdVoucher].status, vouchersStatus[_tokenIdVoucher].isPaymentReleased, vouchersStatus[_tokenIdVoucher].isDepositsReleased); + return ( + vouchersStatus[_tokenIdVoucher].status, + vouchersStatus[_tokenIdVoucher].isPaymentReleased, + vouchersStatus[_tokenIdVoucher].isDepositsReleased + ); } - + /** * @notice Get the holder of a voucher * @param _tokenIdVoucher ID of the voucher token * @return Address of the holder - */ + */ function getVoucherHolder(uint256 _tokenIdVoucher) - public view override + public + view + override returns (address) { return IERC721(tokensContract).ownerOf(_tokenIdVoucher); } /** - * @notice Get the holder of a supply - * @param _tokenIdSupply ID of a promise which is mapped to the corresponding Promise - * @return Address of the holder - */ + * @notice Get the holder of a supply + * @param _tokenIdSupply ID of a promise which is mapped to the corresponding Promise + * @return Address of the holder + */ function getSupplyHolder(uint256 _tokenIdSupply) - public view override + public + view + override returns (address) { bytes32 promiseKey = ordersPromise[_tokenIdSupply]; return promises[promiseKey].seller; } - /** * @notice Get the address of the token where the price for the supply is held @@ -975,7 +1093,9 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @return Address of the token */ function getVoucherPriceToken(uint256 _tokenIdSupply) - public view override + public + view + override returns (address) { return paymentDetails[_tokenIdSupply].addressTokenPrice; @@ -987,7 +1107,9 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @return Address of the token */ function getVoucherDepositToken(uint256 _tokenIdSupply) - public view override + public + view + override returns (address) { return paymentDetails[_tokenIdSupply].addressTokenDeposits; @@ -999,14 +1121,16 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { * @return payment method */ function getVoucherPaymentMethod(uint256 _tokenIdSupply) - public view override + public + view + override returns (uint8) { return paymentDetails[_tokenIdSupply].paymentMethod; } - - /** - * + + /** + * */ function isInValidityPeriod(uint256 _tokenIdVoucher) public @@ -1015,10 +1139,11 @@ contract VoucherKernel is IVoucherKernel, Ownable, Pausable, usingHelpers { returns (bool) { //check validity period - Promise memory tPromise = promises[getPromiseIdFromVoucherId(_tokenIdVoucher)]; + Promise memory tPromise = + promises[getPromiseIdFromVoucherId(_tokenIdVoucher)]; require(tPromise.validFrom <= block.timestamp, "INVALID_VALIDITY_FROM"); //hex"26" FISSION.code(FISSION.Category.Find, FISSION.Status.Above_Range_Overflow) - require(tPromise.validTo >= block.timestamp, "INVALID_VALIDITY_TO"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow) - + require(tPromise.validTo >= block.timestamp, "INVALID_VALIDITY_TO"); //hex"24" FISSION.code(FISSION.Category.Find, FISSION.Status.BelowRange_Underflow) + return true; } -} \ No newline at end of file +} diff --git a/contracts/usingHelpers.sol b/contracts/usingHelpers.sol index 1c56c56e..649d3103 100644 --- a/contracts/usingHelpers.sol +++ b/contracts/usingHelpers.sol @@ -5,34 +5,26 @@ pragma solidity >=0.6.6 <0.7.0; /** * @title Utility contract to enable access to common structures */ -contract usingHelpers { +contract UsingHelpers { uint8 internal constant ONE = 1; - uint8 internal constant idxCommit = 7; - uint8 internal constant idxRedeem = 6; - uint8 internal constant idxRefund = 5; - uint8 internal constant idxExpire = 4; - uint8 internal constant idxComplain = 3; - uint8 internal constant idxCancelFault = 2; - uint8 internal constant idxFinal = 1; - + uint8 internal constant IDX_COMMIT = 7; + uint8 internal constant IDX_REDEEM = 6; + uint8 internal constant IDX_REFUND = 5; + uint8 internal constant IDX_EXPIRE = 4; + uint8 internal constant IDX_COMPLAIN = 3; + uint8 internal constant IDX_CANCEL_FAULT = 2; + uint8 internal constant IDX_FINAL = 1; + /* Status of the voucher in 8 bits: [7:COMMITTED] [6:REDEEMED] [5:REFUNDED] [4:EXPIRED] [3:COMPLAINED] [2:CANCELORFAULT] [1:FINAL] [1:/] */ - // Those are the payment methods we are using throughout the system. - // Depending on how to user choose to interact with it's funds we store the method, so we could distribute its tokens afterwise - uint8 internal constant ETH_ETH = 1; - uint8 internal constant ETH_TKN = 2; - uint8 internal constant TKN_ETH = 3; - uint8 internal constant TKN_TKN = 4; - - struct VoucherStatus { - uint8 status; - bool isPaymentReleased; - bool isDepositsReleased; - uint256 complainPeriodStart; - uint256 cancelFaultPeriodStart; - } + // Those are the payment methods we are using throughout the system. + // Depending on how to user choose to interact with it's funds we store the method, so we could distribute its tokens afterwise + uint8 internal constant ETHETH = 1; + uint8 internal constant ETHTKN = 2; + uint8 internal constant TKNETH = 3; + uint8 internal constant TKNTKN = 4; struct VoucherDetails { uint256 tokenIdSupply; @@ -45,55 +37,47 @@ contract usingHelpers { uint256 amount2pool; uint256 amount2issuer; uint256 amount2holder; - uint8 paymentMethod; + uint8 paymentMethod; VoucherStatus currStatus; } - - - function isStateCommitted(uint8 _status) - internal pure - returns (bool) - { - return _status == setChange(0, idxCommit); + + struct VoucherStatus { + uint8 status; + bool isPaymentReleased; + bool isDepositsReleased; + uint256 complainPeriodStart; + uint256 cancelFaultPeriodStart; + } + + function isStateCommitted(uint8 _status) internal pure returns (bool) { + return _status == setChange(0, IDX_COMMIT); } - - + function isStateRedemptionSigned(uint8 _status) - internal pure + internal + pure returns (bool) { - return _status == setChange(setChange(0, idxCommit), idxRedeem); - } - - - function isStateRefunded(uint8 _status) - internal pure - returns (bool) - { - return _status == setChange(setChange(0, idxCommit), idxRefund); - } - + return _status == setChange(setChange(0, IDX_COMMIT), IDX_REDEEM); + } - function isStateExpired(uint8 _status) - internal pure - returns (bool) - { - return _status == setChange(setChange(0, idxCommit), idxExpire); - } - - - function isStatus(uint8 _status, uint8 _idx) - internal pure - returns (bool) - { - return _status >> _idx & ONE == 1; + function isStateRefunded(uint8 _status) internal pure returns (bool) { + return _status == setChange(setChange(0, IDX_COMMIT), IDX_REFUND); + } + + function isStateExpired(uint8 _status) internal pure returns (bool) { + return _status == setChange(setChange(0, IDX_COMMIT), IDX_EXPIRE); } - - - function setChange(uint8 _status, uint8 _changeIdx) - internal pure - returns (uint8) + + function isStatus(uint8 _status, uint8 _idx) internal pure returns (bool) { + return (_status >> _idx) & ONE == 1; + } + + function setChange(uint8 _status, uint8 _changeIdx) + internal + pure + returns (uint8) { - return _status | ONE << _changeIdx; - } + return _status | (ONE << _changeIdx); + } } diff --git a/doc_contracts.md b/doc_contracts.md deleted file mode 100644 index ac2b2c7f..00000000 --- a/doc_contracts.md +++ /dev/null @@ -1,40 +0,0 @@ -# Smart contracts description -This is a brief description of the smart contracts used in Boson Protocol. They are based on two NFT standards, [ERC-1155](https://eips.ethereum.org/EIPS/eip-1155) and [ERC-721](https://eips.ethereum.org/EIPS/eip-721). - -Main contracts: -* BosonToken: ERC-20 contract for the native Boson Protocol token -* Cashier: funds-related functions -* ERC1155ERC721: token factory -* VoucherKernel: main business logic -* usingHelpers: common utils as structures - -Supported currencies are currently ETH and BSN tokens therefore functions dealing with funds have appendices such as ETH_ETH or ETH_TKN to denote the currencies used in that particular function (e.g. `function requestCreateOrder_ETH_ETH(uint256[] calldata metadata)`). - - -## Transactions flow -The journey through the NFT lifecycle is presented on a simplified diagram below. - -![Simplified exchange mechanism](assets/boson_exchange_diagram_simplified.png) - - -Voucher's status is defined in 7 bits that are set depending on the path in its lifecycle (defined in [usingHelpers.sol](https://github.com/bosonprotocol/bsn-core-prototype/blob/master/contracts/usingHelpers.sol#L29)): -7:COMMITTED -6:REDEEMED
 -5:REFUNDED -4:EXPIRED 
 -3:COMPLAINED
 -2:CANCELORFAULT
 -1:FINAL - - -### Happy path -The process starts with Seller making an offer - minting a VoucherSet, which is represented as ERC-1155 token: `Cashier.requestCreateOrder()`. The Seller sets the expiration period of the whole VoucherSet. - -Then the Buyer purchases the Voucher, i.e. is committing to redeem it at some point later - this means an ERC-721 token is extracted from a VoucherSet: `Cashier.requestVoucher()`. - -The Buyer redeems the voucher, thus releasing the payment amount to the Seller: `VoucherKernel.redeem()`. - -After the two wait periods pass (the period within which Buyer can complain and the period within which Seller can admit cancel/fault), the Seller's deposit can be returned to the Seller and Buyer's deposit can be returned to the Buyer. - -A scheduled process is running in the backend that flags the vouchers when redemption was made and when wait periods expire. Anybody could be executing these functions, marked as external, the backend is currently running them for convenience: `VoucherKernel.triggerExpiration()`, `VoucherKernel.triggerFinalizeVoucher()`, `Cashier.withdraw()`. - diff --git a/docs/assets/banner.png b/docs/assets/banner.png new file mode 100644 index 00000000..2a3ef41e Binary files /dev/null and b/docs/assets/banner.png differ diff --git a/docs/assets/banner.psd b/docs/assets/banner.psd new file mode 100644 index 00000000..37f6af8e Binary files /dev/null and b/docs/assets/banner.psd differ diff --git a/assets/boson_exchange_diagram_simplified.png b/docs/assets/exchange-diagram-simplified.png similarity index 100% rename from assets/boson_exchange_diagram_simplified.png rename to docs/assets/exchange-diagram-simplified.png diff --git a/docs/contracts/deployment.md b/docs/contracts/deployment.md new file mode 100644 index 00000000..a479c61f --- /dev/null +++ b/docs/contracts/deployment.md @@ -0,0 +1,26 @@ +# Smart Contracts - Deployment + +## Initialization + +[Migrations script](./migrations/2_deploy_contracts.js) for Truffle also does +this initialization: + +- ERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true') +- ERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address) +- VoucherKernel.setBosonRouterAddress(bosonRouter.address) + +## Deployment addresses + +Contracts are deployed on Kovan testnet at addresses: + +ERC1155ERC721: 0xF3aA8eB3812303F6c86c136557bC23E48d634B58 +VoucherKernel: 0x1806312211bd1521430C953683038d6263580feE +Cashier: 0xaaf749c8e6e37b51410F1810ADcAEED18d0C166F + +The frontend is currently pointing to Kovan deployment. + +Contract are also deployed on Ropsten testnet at addresses: + +ERC1155ERC721: 0xe7028d66222aD1AfEB0098956347A6284443bd16 +VoucherKernel: 0xa93f95bf0039CE30957b77A6638e2e273598D576 +Cashier: 0x014b8baF57bA77FaE23075aa93c2B768eeb440bD diff --git a/docs/contracts/overview.md b/docs/contracts/overview.md new file mode 100644 index 00000000..38e94c18 --- /dev/null +++ b/docs/contracts/overview.md @@ -0,0 +1,61 @@ +# Smart Contracts - Overview + +This is a brief description of the smart contracts used in Boson Protocol. They +are based on two NFT standards, +[ERC-1155](https://eips.ethereum.org/EIPS/eip-1155) and +[ERC-721](https://eips.ethereum.org/EIPS/eip-721). + +Main contracts: +* BosonRouter: creation of VoucherSets and Vouchers +* BosonToken: ERC-20 contract for the native Boson Protocol token +* Cashier: escrow management +* ERC1155ERC721: token factory +* VoucherKernel: main business logic +* UsingHelpers: common utils as structures + +Supported currencies are currently ETH and BSN tokens therefore functions +dealing with funds have appendices such as ETHETH or ETHTKN to denote the +currencies used in that particular function (e.g. +`function requestCreateOrderETHETH(uint256[] calldata metadata)`). + +## Transactions flow + +The journey through the NFT lifecycle is presented on a simplified diagram +below. + +![Simplified exchange mechanism](docs/assets/exchange-diagram-simplified.png) + +Voucher's status is defined in 7 bits that are set depending on the path in its +lifecycle (defined in +[UsingHelpers.sol](https://github.com/bosonprotocol/bsn-core-prototype/blob/master/contracts/UsingHelpers.sol#L29)): + +7:COMMITTED +6:REDEEMED +5:REFUNDED +4:EXPIRED +3:COMPLAINED +2:CANCELORFAULT +1:FINAL + +### Happy path + +The process starts with Seller making an offer - minting a VoucherSet, which is +represented as ERC-1155 token: `BosonRouter.requestCreateOrder()`. The Seller sets +the expiration period of the whole VoucherSet. + +Then the Buyer purchases the Voucher, i.e. is committing to redeem it at some +point later - this means an ERC-721 token is extracted from a VoucherSet: +`BosonRouter.requestVoucher()`. + +The Buyer redeems the voucher, thus releasing the payment amount to the Seller: +`VoucherKernel.redeem()`. + +After the two wait periods pass (the period within which Buyer can complain and +the period within which Seller can admit cancel/fault), the Seller's deposit +can be returned to the Seller and Buyer's deposit can be returned to the Buyer. + +A scheduled process is running in the backend that flags the vouchers when +redemption was made and when wait periods expire. Anybody could be executing +these functions, marked as external, the backend is currently running them for +convenience: `VoucherKernel.triggerExpiration()`, +`VoucherKernel.triggerFinalizeVoucher()`, `Cashier.withdraw()`. diff --git a/docs/setup/linux.md b/docs/setup/linux.md new file mode 100644 index 00000000..3724e342 --- /dev/null +++ b/docs/setup/linux.md @@ -0,0 +1,84 @@ +# Machine Setup - Linux + +## Requirements + +In order for the build to run correctly, a few tools will need to be installed +on your development machine: + +* git +* direnv +* Node (10.23.0) +* NPM (> 6) +* Ruby (2.7.2) +* Bundler (> 2) + +## Installation + +Installing the required tools is dependent on your distribution. In this guide, +we assume a Debian based distribution. + +### git & direnv + +To install git: + +```shell script +apt-get install git +``` + +To install direnv: + +```shell script +apt-get install direnv +echo "$(direnv hook bash)" >> ~/.bashrc +exec $SHELL + +direnv allow +``` + +Note: if you use zsh instead of bash, change `~/.bashrc` above to `~/.zshrc` +and use `direnv hook zsh`. + +### Node & NPM + +To install Node & NPM: + +```shell script +apt-get update +apt-get install curl +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash +mkdir ~/.nvm +echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.bashrc +echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> ~/.bashrc +echo '[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"' >> ~/.bashrc +exec $SHELL +nvm install 10.23.0 +nvm use 10.23.0 +``` + +Note: if you use zsh instead of bash, change `~/.bashrc` above to `~/.zshrc`. + +### Ruby & Bundler + +To install Ruby and bundler: + +```shell script +apt-get update +apt-get install \ + git curl libssl-dev libreadline-dev zlib1g-dev \ + autoconf bison build-essential libyaml-dev \ + libreadline-dev libncurses5-dev libffi-dev libgdbm-dev +curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-installer | bash +echo 'export PATH="$PATH:~/.rbenv/bin"' >> ~/.bashrc +echo 'eval "$(rbenv init - bash)"' >> ~/.bashrc +exec $SHELL +rbenv install 2.7.2 +rbenv rehash +rbenv local 2.7.2 +gem install bundler +``` + +Note: if you use zsh instead of bash, change `~/.bashrc` above to `~/.zshrc` +and use `rbenv init - zsh`. + + +Note: if you use Fedora, see installation instructions at [Installing Ruby and Rails with rbenv](https://developer.fedoraproject.org/start/sw/web-app/rails.html). diff --git a/docs/setup/osx.md b/docs/setup/osx.md new file mode 100644 index 00000000..f2b4adbf --- /dev/null +++ b/docs/setup/osx.md @@ -0,0 +1,79 @@ +# Machine Setup - OS X + +## Requirements + +In order for the build to run correctly, a few tools will need to be installed +on your development machine: + +* git +* direnv +* Node (10.23.0) +* NPM (> 6) +* Ruby (2.7.2) +* Bundler (> 2) + +## Installation + +Installing the required tools is best managed by [homebrew](http://brew.sh). + +To install homebrew: + +``` +ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +``` + +### git & direnv + +To install git: + +```shell script +brew install git +``` + +To install direnv: + +```shell script +brew install direnv +echo "$(direnv hook zsh)" >> ~/.zshrc +exec $SHELL + +direnv allow +``` + +Note: if you use bash instead of zsh, change `~/.zshrc` above to `~/.bashrc` +and use `direnv hook bash`. + +### Node & NPM + +To install Node & NPM: + +```shell script +brew install nvm +mkdir ~/.nvm +echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc +echo '[ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh"' >> ~/.zshrc +echo '[ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && . "/usr/local/opt/nvm/etc/bash_completion.d/nvm"' >> ~/.zshrc +exec $SHELL +nvm install 10.23.0 +nvm use 10.23.0 +``` + +Note: if you use bash instead of zsh, change `~/.zshrc` above to `~/.bashrc` + +### Ruby & Bundler + +To install Ruby and bundler: + +```shell script +brew install rbenv +brew install ruby-build +echo 'eval "$(rbenv init - zsh)"' >> ~/.zshrc +exec $SHELL +rbenv install 2.7.2 +rbenv rehash +rbenv local 2.7.2 +gem install bundler +``` + +Note: if you use bash instead of zsh, change `~/.zshrc` above to `~/.bashrc` +and use `rbenv init - bash`. diff --git a/go b/go new file mode 100755 index 00000000..a42c485a --- /dev/null +++ b/go @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +[ -n "$GO_DEBUG" ] && set -x +set -e + +project_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +verbose="no" +offline="no" +skip_checks="no" + +missing_dependency="no" + +[ -n "$GO_DEBUG" ] && verbose="yes" +[ -n "$GO_SKIP_CHECKS" ] && skip_checks="yes" +[ -n "$GO_OFFLINE" ] && offline="yes" + + +if [[ "$skip_checks" = "no" ]]; then + echo "Checking for system dependencies." + ruby_version="$(cat "$project_dir"/.ruby-version)" + if ! type ruby >/dev/null 2>&1 || ! ruby -v | grep -q "$ruby_version"; then + echo "This codebase requires Ruby $ruby_version." + missing_dependency="yes" + fi + + if ! type bundler >/dev/null 2>&1; then + echo "This codebase requires Bundler." + missing_dependency="yes" + fi + + if [[ "$missing_dependency" = "yes" ]]; then + echo "Please install missing dependencies to continue." + exit 1 + fi + + echo "All system dependencies present. Continuing." +fi + +if [[ "$offline" = "no" ]]; then + echo "Installing bundler." + if [[ "$verbose" = "yes" ]]; then + gem install --no-document bundler + else + gem install --no-document bundler > /dev/null + fi + + echo "Installing ruby dependencies." + if [[ "$verbose" = "yes" ]]; then + bundle install + else + bundle install > /dev/null + fi +fi + +echo "Starting rake." +if [[ "$verbose" = "yes" ]]; then + time bundle exec rake --verbose "$@" +else + time bundle exec rake "$@" +fi diff --git a/lib/ganache.rb b/lib/ganache.rb new file mode 100644 index 00000000..d53cce0a --- /dev/null +++ b/lib/ganache.rb @@ -0,0 +1,131 @@ +require 'childprocess' +require 'random-port' +require 'fileutils' + +module Ganache + def self.builder + Builder.new + end + + def self.on_available_port(options = {}, &block) + RandomPort::Pool.new.acquire do |port| + begin + instance = Builder.new(options.merge(port: port)).build + instance.start + block.call(instance) + ensure + instance.stop + end + end + end + + class Instance + attr_reader( + :binary, + :port, + :account_keys_directory, + :pidfile_directory, + :allow_unlimited_contract_size) + + def initialize(options) + @binary = options[:binary] + @port = options[:port] + @account_keys_directory = options[:account_keys_directory] + @pidfile_directory = options[:pidfile_directory] + @allow_unlimited_contract_size = options[:allow_unlimited_contract_size] + + @started = false + end + + def started? + @started + end + + def pidfile + "#{@pidfile_directory}/ganache-#{@port}.pid" + end + + def account_keys_file + "#{@account_keys_directory}/accounts-#{@port}.json" + end + + def start + FileUtils.mkdir_p(@pidfile_directory) + FileUtils.mkdir_p(@account_keys_directory) + + command = [@binary, '--port', @port.to_s] + if @allow_unlimited_contract_size + command = command.concat(['--allowUnlimitedContractSize']) + end + if @account_keys_directory + command = command.concat(['--acctKeys', account_keys_file]) + end + + process = ChildProcess.build(*command) + # process.io.inherit! + process.leader = true + process.detach = true + process.start + + File.open(pidfile, "w") { |pidfile| pidfile.write(process.pid) } + + @started = true + end + + def stop + pid = File.read(pidfile).to_i + + Process.kill('INT', pid) + File.unlink(pidfile) + File.unlink(account_keys_file) + + @started = false + end + end + + class Builder + def initialize(options = {}) + @binary = options[:binary] || './node_modules/.bin/ganache-cli' + @port = options[:port] || 8545 + @pidfile_directory = options[:pidfile_directory] || 'run/pid' + @account_keys_directory = + options[:account_keys_directory] || 'build/ganache' + @allow_unlimited_contract_size = + options[:allow_unlimited_contract_size] || false + end + + def clone(options) + Builder.new(to_h.merge(options)) + end + + def on_port(port) + clone(port: port) + end + + def allowing_unlimited_contract_size + clone(allow_unlimited_contract_size: true) + end + + def saving_account_keys_to(directory) + clone(account_keys_directory: directory) + end + + def saving_pidfile_to(directory) + clone(pidfile_directory: directory) + end + + def build + Instance.new(to_h) + end + + def to_h + { + binary: @binary, + port: @port, + pidfile_directory: @pidfile_directory, + account_keys_directory: @account_keys_directory, + allow_unlimited_contract_size: @allow_unlimited_contract_size + } + end + end +end diff --git a/migrations/2_deploy_contracts.js b/migrations/2_deploy_contracts.js index e6ca164a..3ad293c2 100644 --- a/migrations/2_deploy_contracts.js +++ b/migrations/2_deploy_contracts.js @@ -9,51 +9,47 @@ const FundLimitsOracle = artifacts.require('FundLimitsOracle'); const BosonTokenPrice = artifacts.require("BosonTokenPrice") const BosonTokenDeposit = artifacts.require("BosonTokenDeposit") - module.exports = function(deployer, network, accounts) { console.log("network: ", network); console.log("accounts: ", accounts); - + deployer.deploy(FundLimitsOracle).then(function() { return deployer.deploy(ERC1155ERC721).then(function() { return deployer.deploy(VoucherKernel, ERC1155ERC721.address).then(function() { - return deployer.deploy(Cashier, VoucherKernel.address).then(function () { + return deployer.deploy(Cashier, VoucherKernel.address).then(function() { return deployer.deploy(BosonRouter, VoucherKernel.address, ERC1155ERC721.address, FundLimitsOracle.address, Cashier.address).then(function() { return deployer.deploy(BosonTokenPrice, "BosonTokenPrice", "BPRC").then(function () { return deployer.deploy(BosonTokenDeposit, "BosonTokenDeposit", "BDEP").then(function() { - - console.log("$ Setting initial values ..."); - - ERC1155ERC721.deployed().then(instance => { instance.setApprovalForAll(VoucherKernel.address, 'true').then(tx => - console.log("\n$ ERC1155ERC721", tx.logs[0].event, "approved VoucherKernel:", tx.logs[0].args._approved))}); - ERC1155ERC721.deployed().then(instance => { instance.setVoucherKernelAddress(VoucherKernel.address).then(tx => - console.log("\n$ ERC1155ERC721", tx.logs[0].event, "at:", tx.logs[0].args._newVoucherKernel))}); - - ERC1155ERC721.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => + console.log("$ Setting initial values ..."); + ERC1155ERC721.deployed().then(instance => { instance.setApprovalForAll(VoucherKernel.address, 'true').then(tx => + console.log("\n$ ERC1155ERC721", tx.logs[0].event, "approved VoucherKernel:", tx.logs[0].args._approved))}); + ERC1155ERC721.deployed().then(instance => { instance.setVoucherKernelAddress(VoucherKernel.address).then(tx => + console.log("\n$ ERC1155ERC721", tx.logs[0].event, "at:", tx.logs[0].args._newVoucherKernel))}); + ERC1155ERC721.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => console.log("\n$ ERC1155ERC721", tx.logs[0].event, "at:", tx.logs[0].args._newBosonRouter))}); - VoucherKernel.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => - console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newBosonRouter))}); + VoucherKernel.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => + console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newBosonRouter))}); + + VoucherKernel.deployed().then(instance => { instance.setCashierAddress(Cashier.address).then(tx => + console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newCashier))}); - VoucherKernel.deployed().then(instance => { instance.setCashierAddress(Cashier.address).then(tx => - console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newCashier))}); + Cashier.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => + console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newBosonRouter))}); - Cashier.deployed().then(instance => { instance.setBosonRouterAddress(BosonRouter.address).then(tx => - console.log("\n$ VoucherKernel", tx.logs[0].event, "at:", tx.logs[0].args._newBosonRouter))}); - - console.log("FundLimitsOracle Contract Address: ", FundLimitsOracle.address); + console.log("FundLimitsOracle Contract Address: ", FundLimitsOracle.address); console.log("ERC1155ERC721 Contract Address: ", ERC1155ERC721.address); console.log("VoucherKernel Contract Address: ", VoucherKernel.address); console.log("Cashier Contract Address: ", Cashier.address); - console.log("Boson Router Contract Address: ", BosonRouter.address); + console.log("Boson Router Contract Address: ", BosonRouter.address); console.log("Boson Token Price Contract Address: ", BosonTokenPrice.address); console.log("Boson Token Deposit Contract Address: ", BosonTokenDeposit.address); - }); - }); + }) + }) }) }); }) }) - }) + }); }; diff --git a/package-lock.json b/package-lock.json index f7ba900f..343d8fe3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,11 +4,18 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, "@babel/helper-module-imports": { "version": "7.12.5", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", - "dev": true, "requires": { "@babel/types": "^7.12.5" } @@ -16,20 +23,78 @@ "@babel/helper-plugin-utils": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==" }, "@babel/helper-validator-identifier": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", - "dev": true + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } }, "@babel/plugin-transform-runtime": { "version": "7.12.10", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.10.tgz", "integrity": "sha512-xOrUfzPxw7+WDm9igMgQCbO3cJKymX7dFdsgRr1eu9n3KjjyU4pptIXbXPseQDquw+W+RuJEJMHKHNsPNNm3CA==", - "dev": true, "requires": { "@babel/helper-module-imports": "^7.12.5", "@babel/helper-plugin-utils": "^7.10.4", @@ -39,8 +104,7 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" } } }, @@ -48,7 +112,6 @@ "version": "7.12.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } @@ -57,13 +120,63 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.11.tgz", "integrity": "sha512-ukA9SQtKThINm++CX1CwmliMrE54J6nIYB5XTwL5f/CLFW9owfls+YSU8tVW15RQ2w+a3fSbPjC6HdQNtWZkiA==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, + "@eslint/eslintrc": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", + "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "lodash": "^4.17.20", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + } + } + }, "@ethersproject/abi": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.9.tgz", @@ -444,7 +557,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, "requires": { "@nodelib/fs.stat": "2.0.3", "run-parallel": "^1.1.9" @@ -453,14 +565,12 @@ "@nodelib/fs.stat": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==" }, "@nodelib/fs.walk": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", - "dev": true, "requires": { "@nodelib/fs.scandir": "2.1.3", "fastq": "^1.6.0" @@ -479,8 +589,7 @@ "@solidity-parser/parser": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.8.2.tgz", - "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==", - "dev": true + "integrity": "sha512-8LySx3qrNXPgB5JiULfG10O3V7QTxI/TLzSw5hFQhXWSkVxZBAv4rZQ0sYgLEbc8g3L2lmnujj1hKul38Eu5NQ==" }, "@szmarczak/http-timer": { "version": "1.1.2", @@ -493,14 +602,12 @@ "@truffle/error": { "version": "0.0.11", "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.11.tgz", - "integrity": "sha512-ju6TucjlJkfYMmdraYY/IBJaFb+Sa+huhYtOoyOJ+G29KcgytUVnDzKGwC7Kgk6IsxQMm62Mc1E0GZzFbGGipw==", - "dev": true + "integrity": "sha512-ju6TucjlJkfYMmdraYY/IBJaFb+Sa+huhYtOoyOJ+G29KcgytUVnDzKGwC7Kgk6IsxQMm62Mc1E0GZzFbGGipw==" }, "@truffle/hdwallet-provider": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@truffle/hdwallet-provider/-/hdwallet-provider-1.2.0.tgz", "integrity": "sha512-EPatDbyRuGbB/MLt9ZBokmtjyLjaNpuHfUIWuv4mQMrH1Nu82H5AAZYLh4Z1BZliDZpqB03a0yUMmK/4R0BN9g==", - "dev": true, "requires": { "@trufflesuite/web3-provider-engine": "15.0.13-1", "@types/web3": "^1.0.20", @@ -518,7 +625,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -535,7 +641,6 @@ "version": "0.4.18", "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.18.tgz", "integrity": "sha512-P9JVSYD/CX3V+NgTWu+Bf71sLh8pMwrCpbiYRB93pRw/1H3ZTvt5iDC2MVvVxCs8FkSiy4OZzQK/DJ8+hXAmYw==", - "dev": true, "requires": { "bn.js": "^4.11.8", "ethers": "^4.0.32", @@ -547,7 +652,6 @@ "version": "5.0.0-beta.153", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", - "dev": true, "requires": { "@ethersproject/address": ">=5.0.0-beta.128", "@ethersproject/bignumber": ">=5.0.0-beta.130", @@ -564,7 +668,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, "requires": { "ethereumjs-common": "^1.5.0", "ethereumjs-util": "^6.0.0" @@ -574,7 +677,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -589,7 +691,6 @@ "version": "4.0.48", "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.48.tgz", "integrity": "sha512-sZD5K8H28dOrcidzx9f8KYh8083n5BexIO3+SbE4jK83L85FxtpXZBCQdXb8gkg+7sBqomcLhhkU7UHL+F7I2g==", - "dev": true, "requires": { "aes-js": "3.0.0", "bn.js": "^4.4.0", @@ -605,14 +706,12 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.0" @@ -621,32 +720,27 @@ "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "scrypt-js": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true + "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==" }, "setimmediate": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=", - "dev": true + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" }, "swarm-js": { "version": "0.1.40", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", - "dev": true, "requires": { "bluebird": "^3.5.0", "buffer": "^5.0.5", @@ -665,7 +759,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, "requires": { "decompress-response": "^3.2.0", "duplexer3": "^0.1.4", @@ -686,8 +779,7 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" } } }, @@ -695,7 +787,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, "requires": { "prepend-http": "^1.0.1" } @@ -703,14 +794,12 @@ "uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=", - "dev": true + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" }, "web3": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.9.tgz", "integrity": "sha512-Mo5aBRm0JrcNpN/g4VOrDzudymfOnHRC3s2VarhYxRA8aWgF5rnhQ0ziySaugpic1gksbXPe105pUWyRqw8HUA==", - "dev": true, "requires": { "web3-bzz": "1.2.9", "web3-core": "1.2.9", @@ -725,7 +814,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.9.tgz", "integrity": "sha512-ogVQr9jHodu9HobARtvUSmWG22cv2EUQzlPeejGWZ7j5h20HX40EDuWyomGY5VclIj5DdLY76Tmq88RTf/6nxA==", - "dev": true, "requires": { "@types/node": "^10.12.18", "got": "9.6.0", @@ -737,7 +825,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.9.tgz", "integrity": "sha512-fSYv21IP658Ty2wAuU9iqmW7V+75DOYMVZsDH/c14jcF/1VXnedOcxzxSj3vArsCvXZNe6XC5/wAuGZyQwR9RA==", - "dev": true, "requires": { "@types/bn.js": "^4.11.4", "@types/node": "^12.6.1", @@ -751,8 +838,7 @@ "@types/node": { "version": "12.19.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", - "dev": true + "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==" } } }, @@ -760,7 +846,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.9.tgz", "integrity": "sha512-t0WAG3orLCE3lqi77ZoSRNFok3VQWZXTniZigDQjyOJYMAX7BU3F3js8HKbjVnAxlX3tiKoDxI0KBk9F3AxYuw==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-eth-iban": "1.2.9", @@ -771,7 +856,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.9.tgz", "integrity": "sha512-bjsIoqP3gs7A/gP8+QeLUCyOKJ8bopteCSNbCX36Pxk6TYfYWNuC6hP+2GzUuqdP3xaZNe+XEElQFUNpR3oyAg==", - "dev": true, "requires": { "@ethersproject/transactions": "^5.0.0-beta.135", "underscore": "1.9.1", @@ -785,7 +869,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.9.tgz", "integrity": "sha512-0eAUA2zjgXTleSrnc1wdoKQPPIHU6KHf4fAscu4W9kKrR+mqP1KsjYrxY9wUyjNnXxfQ+5M29ipvbiaK8OqdOw==", - "dev": true, "requires": { "eventemitter3": "3.1.2" } @@ -794,7 +877,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.9.tgz", "integrity": "sha512-1PwKV2m46ALUnIN5VPPgjOj8yMLJhhqZYvYJE34hTN5SErOkwhzx5zScvo5MN7v7KyQGFnpVCZKKGCiEnDmtFA==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.9", @@ -807,7 +889,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.9.tgz", "integrity": "sha512-Y48TvXPSPxEM33OmXjGVDMzTd0j8X0t2+sDw66haeBS8eYnrEzasWuBZZXDq0zNUsqyxItgBGDn+cszkgEnFqg==", - "dev": true, "requires": { "eventemitter3": "3.1.2", "underscore": "1.9.1", @@ -818,7 +899,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.9.tgz", "integrity": "sha512-sIKO4iE9FEBa/CYUd6GdPd7GXt/wISqxUd8PlIld6+hvMJj02lgO7Z7p5T9mZIJcIZJGvZX81ogx8oJ9yif+Ag==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-core": "1.2.9", @@ -839,7 +919,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.9.tgz", "integrity": "sha512-3YwUYbh/DMfDbhMWEebAdjSd5bj3ZQieOjLzWFHU23CaLEqT34sUix1lba+hgUH/EN6A7bKAuKOhR3p0OvTn7Q==", - "dev": true, "requires": { "@ethersproject/abi": "5.0.0-beta.153", "underscore": "1.9.1", @@ -850,7 +929,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.9.tgz", "integrity": "sha512-jkbDCZoA1qv53mFcRHCinoCsgg8WH+M0YUO1awxmqWXRmCRws1wW0TsuSQ14UThih5Dxolgl+e+aGWxG58LMwg==", - "dev": true, "requires": { "crypto-browserify": "3.12.0", "eth-lib": "^0.2.8", @@ -869,7 +947,6 @@ "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -879,14 +956,12 @@ "scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "dev": true + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" } } }, @@ -894,7 +969,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.9.tgz", "integrity": "sha512-PYMvJf7EG/HyssUZa+pXrc8IB06K/YFfWYyW4R7ed3sab+9wWUys1TlWxBCBuiBXOokSAyM6H6P6/cKEx8FT8Q==", - "dev": true, "requires": { "@types/bn.js": "^4.11.4", "underscore": "1.9.1", @@ -911,7 +985,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.9.tgz", "integrity": "sha512-kG4+ZRgZ8I1WYyOBGI8QVRHfUSbbJjvJAGA1AF/NOW7JXQ+x7gBGeJw6taDWJhSshMoEKWcsgvsiuoG4870YxQ==", - "dev": true, "requires": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", @@ -928,7 +1001,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.9.tgz", "integrity": "sha512-RtdVvJE0pyg9dHLy0GzDiqgnLnssSzfz/JYguhC1wsj9+Gnq1M6Diy3NixACWUAp6ty/zafyOaZnNQ+JuH9TjQ==", - "dev": true, "requires": { "bn.js": "4.11.8", "web3-utils": "1.2.9" @@ -937,8 +1009,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" } } }, @@ -946,7 +1017,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.9.tgz", "integrity": "sha512-cFiNrktxZ1C/rIdJFzQTvFn3/0zcsR3a+Jf8Y3KxeQDHszQtosjLWptP7bsUmDwEh4hzh0Cy3KpOxlYBWB8bJQ==", - "dev": true, "requires": { "@types/node": "^12.6.1", "web3-core": "1.2.9", @@ -959,8 +1029,7 @@ "@types/node": { "version": "12.19.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", - "dev": true + "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==" } } }, @@ -968,7 +1037,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.9.tgz", "integrity": "sha512-d2mTn8jPlg+SI2hTj2b32Qan6DmtU9ap/IUlJTeQbZQSkTLf0u9suW8Vjwyr4poJYXTurdSshE7OZsPNn30/ZA==", - "dev": true, "requires": { "web3-core": "1.2.9", "web3-core-method": "1.2.9", @@ -979,7 +1047,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.9.tgz", "integrity": "sha512-F956tCIj60Ttr0UvEHWFIhx+be3He8msoPzyA44/kfzzYoMAsCFRn5cf0zQG6al0znE75g6HlWVSN6s3yAh51A==", - "dev": true, "requires": { "web3-core-helpers": "1.2.9", "xhr2-cookies": "1.1.0" @@ -989,7 +1056,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.9.tgz", "integrity": "sha512-NQ8QnBleoHA2qTJlqoWu7EJAD/FR5uimf7Ielzk4Z2z+m+6UAuJdJMSuQNj+Umhz9L/Ys6vpS1vHx9NizFl+aQ==", - "dev": true, "requires": { "oboe": "2.1.4", "underscore": "1.9.1", @@ -1000,7 +1066,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.9.tgz", "integrity": "sha512-6+UpvINeI//dglZoAKStUXqxDOXJy6Iitv2z3dbgInG4zb8tkYl/VBDL80UjUg3ZvzWG0g7EKY2nRPEpON2TFA==", - "dev": true, "requires": { "eventemitter3": "^4.0.0", "underscore": "1.9.1", @@ -1011,8 +1076,7 @@ "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" } } }, @@ -1020,7 +1084,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.9.tgz", "integrity": "sha512-PWa8b/EaxaMinFaxy6cV0i0EOi2M7a/ST+9k9nhyhCjVa2vzXuNoBNo2IUOmeZ0WP2UQB8ByJ2+p4htlJaDOjA==", - "dev": true, "requires": { "web3-core": "1.2.9", "web3-core-method": "1.2.9", @@ -1032,7 +1095,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.9.tgz", "integrity": "sha512-9hcpuis3n/LxFzEVjwnVgvJzTirS2S9/MiNAa7l4WOEoywY+BSNwnRX4MuHnjkh9NY25B6QOjuNG6FNnSjTw1w==", - "dev": true, "requires": { "bn.js": "4.11.8", "eth-lib": "0.2.7", @@ -1047,14 +1109,12 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "eth-lib": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -1069,7 +1129,6 @@ "version": "0.2.25", "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.25.tgz", "integrity": "sha512-BohKgT2357c2dYCH2IQwldQ4EJkfsWUClpb3j+kR8ng02vbsyAPe0HMH463I+h+tiDKvL757dBltXpe0DBJusg==", - "dev": true, "requires": { "@truffle/error": "^0.0.11", "@truffle/interface-adapter": "^0.4.18", @@ -1080,7 +1139,6 @@ "version": "5.0.0-beta.153", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz", "integrity": "sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==", - "dev": true, "requires": { "@ethersproject/address": ">=5.0.0-beta.128", "@ethersproject/bignumber": ">=5.0.0-beta.130", @@ -1096,14 +1154,12 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", - "dev": true + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "ethereumjs-tx": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, "requires": { "ethereumjs-common": "^1.5.0", "ethereumjs-util": "^6.0.0" @@ -1113,7 +1169,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -1127,26 +1182,22 @@ "get-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", - "dev": true + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" }, "prepend-http": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "swarm-js": { "version": "0.1.40", "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.40.tgz", "integrity": "sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA==", - "dev": true, "requires": { "bluebird": "^3.5.0", "buffer": "^5.0.5", @@ -1165,7 +1216,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", - "dev": true, "requires": { "decompress-response": "^3.2.0", "duplexer3": "^0.1.4", @@ -1189,7 +1239,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, "requires": { "prepend-http": "^1.0.1" } @@ -1197,14 +1246,12 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "web3": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.9.tgz", "integrity": "sha512-Mo5aBRm0JrcNpN/g4VOrDzudymfOnHRC3s2VarhYxRA8aWgF5rnhQ0ziySaugpic1gksbXPe105pUWyRqw8HUA==", - "dev": true, "requires": { "web3-bzz": "1.2.9", "web3-core": "1.2.9", @@ -1219,7 +1266,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.9.tgz", "integrity": "sha512-ogVQr9jHodu9HobARtvUSmWG22cv2EUQzlPeejGWZ7j5h20HX40EDuWyomGY5VclIj5DdLY76Tmq88RTf/6nxA==", - "dev": true, "requires": { "@types/node": "^10.12.18", "got": "9.6.0", @@ -1231,7 +1277,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.9.tgz", "integrity": "sha512-fSYv21IP658Ty2wAuU9iqmW7V+75DOYMVZsDH/c14jcF/1VXnedOcxzxSj3vArsCvXZNe6XC5/wAuGZyQwR9RA==", - "dev": true, "requires": { "@types/bn.js": "^4.11.4", "@types/node": "^12.6.1", @@ -1245,8 +1290,7 @@ "@types/node": { "version": "12.19.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", - "dev": true + "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==" } } }, @@ -1254,7 +1298,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.9.tgz", "integrity": "sha512-t0WAG3orLCE3lqi77ZoSRNFok3VQWZXTniZigDQjyOJYMAX7BU3F3js8HKbjVnAxlX3tiKoDxI0KBk9F3AxYuw==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-eth-iban": "1.2.9", @@ -1265,7 +1308,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.9.tgz", "integrity": "sha512-bjsIoqP3gs7A/gP8+QeLUCyOKJ8bopteCSNbCX36Pxk6TYfYWNuC6hP+2GzUuqdP3xaZNe+XEElQFUNpR3oyAg==", - "dev": true, "requires": { "@ethersproject/transactions": "^5.0.0-beta.135", "underscore": "1.9.1", @@ -1279,7 +1321,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.9.tgz", "integrity": "sha512-0eAUA2zjgXTleSrnc1wdoKQPPIHU6KHf4fAscu4W9kKrR+mqP1KsjYrxY9wUyjNnXxfQ+5M29ipvbiaK8OqdOw==", - "dev": true, "requires": { "eventemitter3": "3.1.2" } @@ -1288,7 +1329,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.9.tgz", "integrity": "sha512-1PwKV2m46ALUnIN5VPPgjOj8yMLJhhqZYvYJE34hTN5SErOkwhzx5zScvo5MN7v7KyQGFnpVCZKKGCiEnDmtFA==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.9", @@ -1301,7 +1341,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.9.tgz", "integrity": "sha512-Y48TvXPSPxEM33OmXjGVDMzTd0j8X0t2+sDw66haeBS8eYnrEzasWuBZZXDq0zNUsqyxItgBGDn+cszkgEnFqg==", - "dev": true, "requires": { "eventemitter3": "3.1.2", "underscore": "1.9.1", @@ -1312,7 +1351,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.9.tgz", "integrity": "sha512-sIKO4iE9FEBa/CYUd6GdPd7GXt/wISqxUd8PlIld6+hvMJj02lgO7Z7p5T9mZIJcIZJGvZX81ogx8oJ9yif+Ag==", - "dev": true, "requires": { "underscore": "1.9.1", "web3-core": "1.2.9", @@ -1333,7 +1371,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.9.tgz", "integrity": "sha512-3YwUYbh/DMfDbhMWEebAdjSd5bj3ZQieOjLzWFHU23CaLEqT34sUix1lba+hgUH/EN6A7bKAuKOhR3p0OvTn7Q==", - "dev": true, "requires": { "@ethersproject/abi": "5.0.0-beta.153", "underscore": "1.9.1", @@ -1344,7 +1381,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.9.tgz", "integrity": "sha512-jkbDCZoA1qv53mFcRHCinoCsgg8WH+M0YUO1awxmqWXRmCRws1wW0TsuSQ14UThih5Dxolgl+e+aGWxG58LMwg==", - "dev": true, "requires": { "crypto-browserify": "3.12.0", "eth-lib": "^0.2.8", @@ -1363,7 +1399,6 @@ "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -1376,7 +1411,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.9.tgz", "integrity": "sha512-PYMvJf7EG/HyssUZa+pXrc8IB06K/YFfWYyW4R7ed3sab+9wWUys1TlWxBCBuiBXOokSAyM6H6P6/cKEx8FT8Q==", - "dev": true, "requires": { "@types/bn.js": "^4.11.4", "underscore": "1.9.1", @@ -1393,7 +1427,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.9.tgz", "integrity": "sha512-kG4+ZRgZ8I1WYyOBGI8QVRHfUSbbJjvJAGA1AF/NOW7JXQ+x7gBGeJw6taDWJhSshMoEKWcsgvsiuoG4870YxQ==", - "dev": true, "requires": { "content-hash": "^2.5.2", "eth-ens-namehash": "2.0.8", @@ -1410,7 +1443,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.9.tgz", "integrity": "sha512-RtdVvJE0pyg9dHLy0GzDiqgnLnssSzfz/JYguhC1wsj9+Gnq1M6Diy3NixACWUAp6ty/zafyOaZnNQ+JuH9TjQ==", - "dev": true, "requires": { "bn.js": "4.11.8", "web3-utils": "1.2.9" @@ -1420,7 +1452,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.9.tgz", "integrity": "sha512-cFiNrktxZ1C/rIdJFzQTvFn3/0zcsR3a+Jf8Y3KxeQDHszQtosjLWptP7bsUmDwEh4hzh0Cy3KpOxlYBWB8bJQ==", - "dev": true, "requires": { "@types/node": "^12.6.1", "web3-core": "1.2.9", @@ -1433,8 +1464,7 @@ "@types/node": { "version": "12.19.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", - "dev": true + "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==" } } }, @@ -1442,7 +1472,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.9.tgz", "integrity": "sha512-d2mTn8jPlg+SI2hTj2b32Qan6DmtU9ap/IUlJTeQbZQSkTLf0u9suW8Vjwyr4poJYXTurdSshE7OZsPNn30/ZA==", - "dev": true, "requires": { "web3-core": "1.2.9", "web3-core-method": "1.2.9", @@ -1453,7 +1482,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.9.tgz", "integrity": "sha512-F956tCIj60Ttr0UvEHWFIhx+be3He8msoPzyA44/kfzzYoMAsCFRn5cf0zQG6al0znE75g6HlWVSN6s3yAh51A==", - "dev": true, "requires": { "web3-core-helpers": "1.2.9", "xhr2-cookies": "1.1.0" @@ -1463,7 +1491,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.9.tgz", "integrity": "sha512-NQ8QnBleoHA2qTJlqoWu7EJAD/FR5uimf7Ielzk4Z2z+m+6UAuJdJMSuQNj+Umhz9L/Ys6vpS1vHx9NizFl+aQ==", - "dev": true, "requires": { "oboe": "2.1.4", "underscore": "1.9.1", @@ -1474,7 +1501,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.9.tgz", "integrity": "sha512-6+UpvINeI//dglZoAKStUXqxDOXJy6Iitv2z3dbgInG4zb8tkYl/VBDL80UjUg3ZvzWG0g7EKY2nRPEpON2TFA==", - "dev": true, "requires": { "eventemitter3": "^4.0.0", "underscore": "1.9.1", @@ -1485,8 +1511,7 @@ "eventemitter3": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" } } }, @@ -1494,7 +1519,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.9.tgz", "integrity": "sha512-PWa8b/EaxaMinFaxy6cV0i0EOi2M7a/ST+9k9nhyhCjVa2vzXuNoBNo2IUOmeZ0WP2UQB8ByJ2+p4htlJaDOjA==", - "dev": true, "requires": { "web3-core": "1.2.9", "web3-core-method": "1.2.9", @@ -1506,7 +1530,6 @@ "version": "1.2.9", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.9.tgz", "integrity": "sha512-9hcpuis3n/LxFzEVjwnVgvJzTirS2S9/MiNAa7l4WOEoywY+BSNwnRX4MuHnjkh9NY25B6QOjuNG6FNnSjTw1w==", - "dev": true, "requires": { "bn.js": "4.11.8", "eth-lib": "0.2.7", @@ -1522,7 +1545,6 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", - "dev": true, "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -1537,7 +1559,6 @@ "version": "4.1.2-1", "resolved": "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.2-1.tgz", "integrity": "sha512-/MChvC5dw2ck9NU1cZmdovCz2VKbOeIyR4tcxDvA5sT+NaL0rA2/R5U0yI7zsbo1zD+pgqav77rQHTzpUdDNJQ==", - "dev": true, "requires": { "@trufflesuite/eth-json-rpc-middleware": "^4.4.2-0", "await-semaphore": "^0.1.3", @@ -1551,7 +1572,6 @@ "version": "4.0.3-0", "resolved": "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.3-0.tgz", "integrity": "sha512-xaUanOmo0YLqRsL0SfXpFienhdw5bpQ1WEXxMTRi57az4lwpZBv4tFUDvcerdwJrxX9wQqNmgUgd1BrR01dumw==", - "dev": true, "requires": { "@trufflesuite/eth-json-rpc-middleware": "^4.4.2-1", "cross-fetch": "^2.1.1", @@ -1563,7 +1583,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz", "integrity": "sha512-WT5shJ5KfNqHi9jOZD+ID8I1kuYWNrigtZat7GOQkvwo99f8SzAVaEcWhJUv656WiZOAg3P1RiJQANtUmDmbIg==", - "dev": true, "requires": { "fast-safe-stringify": "^2.0.6" } @@ -1574,7 +1593,6 @@ "version": "4.4.2-1", "resolved": "https://registry.npmjs.org/@trufflesuite/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.4.2-1.tgz", "integrity": "sha512-iEy9H8ja7/8aYES5HfrepGBKU9n/Y4OabBJEklVd/zIBlhCCBAWBqkIZgXt11nBXO/rYAeKwYuE3puH3ByYnLA==", - "dev": true, "requires": { "@trufflesuite/eth-sig-util": "^1.4.2", "btoa": "^1.2.1", @@ -1596,7 +1614,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz", "integrity": "sha512-WT5shJ5KfNqHi9jOZD+ID8I1kuYWNrigtZat7GOQkvwo99f8SzAVaEcWhJUv656WiZOAg3P1RiJQANtUmDmbIg==", - "dev": true, "requires": { "fast-safe-stringify": "^2.0.6" } @@ -1605,7 +1622,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -1619,8 +1635,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, @@ -1628,7 +1643,6 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/@trufflesuite/eth-sig-util/-/eth-sig-util-1.4.2.tgz", "integrity": "sha512-+GyfN6b0LNW77hbQlH3ufZ/1eCON7mMrGym6tdYf7xiNw9Vv3jBO72bmmos1EId2NgBvPMhmYYm6DSLQFTmzrA==", - "dev": true, "requires": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^5.1.1" @@ -1638,7 +1652,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -1655,7 +1668,6 @@ "version": "15.0.13-1", "resolved": "https://registry.npmjs.org/@trufflesuite/web3-provider-engine/-/web3-provider-engine-15.0.13-1.tgz", "integrity": "sha512-6u3x/iIN5fyj8pib5QTUDmIOUiwAGhaqdSTXdqCu6v9zo2BEwdCqgEJd1uXDh3DBmPRDfiZ/ge8oUPy7LerpHg==", - "dev": true, "requires": { "@trufflesuite/eth-json-rpc-filters": "^4.1.2-1", "@trufflesuite/eth-json-rpc-infura": "^4.0.3-0", @@ -1685,7 +1697,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -1700,7 +1711,6 @@ "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, "requires": { "async-limiter": "~1.0.0" } @@ -1711,7 +1721,6 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dev": true, "requires": { "@types/node": "*" } @@ -1720,7 +1729,6 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, "requires": { "@types/minimatch": "*", "@types/node": "*" @@ -1729,8 +1737,7 @@ "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" }, "@types/node": { "version": "10.17.49", @@ -1741,7 +1748,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "dev": true, "requires": { "@types/node": "*" } @@ -1750,7 +1756,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", - "dev": true, "requires": { "@types/node": "*" } @@ -1759,7 +1764,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/web3/-/web3-1.2.2.tgz", "integrity": "sha512-eFiYJKggNrOl0nsD+9cMh2MLk4zVBfXfGnVeRFbpiZzBE20eet4KLA3fXcjSuHaBn0RnQzwLAGdgzgzdet4C0A==", - "dev": true, "requires": { "web3": "*" } @@ -1767,20 +1771,17 @@ "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==" }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=" }, "abstract-leveldown": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", - "dev": true, "requires": { "xtend": "~4.0.0" } @@ -1794,11 +1795,20 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" + }, "address": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", - "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", - "dev": true + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==" }, "aes-js": { "version": "3.0.0", @@ -1820,30 +1830,36 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, "optional": true }, "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } }, + "antlr4": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.7.1.tgz", + "integrity": "sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ==" + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -1853,7 +1869,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1862,14 +1877,12 @@ "app-module-path": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=", - "dev": true + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=" }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -1882,8 +1895,7 @@ "array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" }, "asn1": { "version": "0.2.4", @@ -1914,11 +1926,20 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "ast-parents": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", + "integrity": "sha1-UI/Q8F0MSHddnszaLhdEIyYejdM=" + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, "requires": { "lodash": "^4.17.14" } @@ -1927,7 +1948,6 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dev": true, "requires": { "async": "^2.4.0" } @@ -1945,8 +1965,7 @@ "await-semaphore": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/await-semaphore/-/await-semaphore-0.1.3.tgz", - "integrity": "sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q==", - "dev": true + "integrity": "sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q==" }, "aws-sign2": { "version": "0.7.0", @@ -1959,19 +1978,17 @@ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "dev": true, + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", + "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", "requires": { - "follow-redirects": "1.5.10" + "follow-redirects": "^1.10.0" } }, "backoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", - "dev": true, "requires": { "precond": "0.2" } @@ -1979,14 +1996,12 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "base-x": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", - "dev": true, "requires": { "safe-buffer": "^5.0.1" } @@ -2012,14 +2027,12 @@ "bignumber.js": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", - "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", - "dev": true + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" }, "binary-extensions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==" }, "bindings": { "version": "1.5.0", @@ -2041,8 +2054,7 @@ "blakejs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", - "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=", - "dev": true + "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" }, "bluebird": { "version": "3.7.2", @@ -2075,7 +2087,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2085,7 +2096,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -2098,8 +2108,7 @@ "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" }, "browserify-aes": { "version": "1.2.0", @@ -2188,7 +2197,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", - "dev": true, "requires": { "base-x": "^3.0.2" } @@ -2197,7 +2205,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "dev": true, "requires": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -2207,8 +2214,7 @@ "btoa": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", - "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", - "dev": true + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" }, "buffer": { "version": "5.7.1", @@ -2246,8 +2252,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "buffer-to-arraybuffer": { "version": "0.0.5", @@ -2301,11 +2306,31 @@ } } }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "requires": { + "caller-callsite": "^2.0.0" + } + }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caseless": { "version": "0.12.0", @@ -2316,7 +2341,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", @@ -2330,23 +2354,25 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" }, "checkpoint-store": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", - "dev": true, "requires": { "functional-red-black-tree": "^1.0.1" } @@ -2355,7 +2381,6 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", - "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", @@ -2376,7 +2401,6 @@ "version": "0.7.5", "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", - "dev": true, "requires": { "buffer": "^5.5.0", "class-is": "^1.1.0", @@ -2389,7 +2413,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", - "dev": true, "requires": { "buffer": "^5.6.0", "varint": "^5.0.0" @@ -2409,20 +2432,25 @@ "circular": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/circular/-/circular-1.0.5.tgz", - "integrity": "sha1-fad6+Yu96c5LWzWM1Va13e0tMUk=", - "dev": true + "integrity": "sha1-fad6+Yu96c5LWzWM1Va13e0tMUk=" }, "class-is": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", - "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", - "dev": true + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } }, "cli-logger": { "version": "0.5.40", "resolved": "https://registry.npmjs.org/cli-logger/-/cli-logger-0.5.40.tgz", "integrity": "sha1-CX8OEbByx8aYomxH9YiinCC0iws=", - "dev": true, "requires": { "circular": "^1.0.5", "cli-util": "~1.1.27" @@ -2431,23 +2459,25 @@ "cli-regexp": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/cli-regexp/-/cli-regexp-0.1.2.tgz", - "integrity": "sha1-a82TsJ+y7RAl0woRVdWZeVSlNRI=", - "dev": true + "integrity": "sha1-a82TsJ+y7RAl0woRVdWZeVSlNRI=" }, "cli-util": { "version": "1.1.27", "resolved": "https://registry.npmjs.org/cli-util/-/cli-util-1.1.27.tgz", "integrity": "sha1-QtaeNqBAoyH8nPhRwVE8rcUJMFQ=", - "dev": true, "requires": { "cli-regexp": "~0.1.0" } }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -2457,14 +2487,12 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -2475,7 +2503,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -2485,8 +2512,7 @@ "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" }, "clone-response": { "version": "1.0.2", @@ -2500,7 +2526,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -2508,8 +2533,7 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "combined-stream": { "version": "1.0.8", @@ -2527,8 +2551,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "content-disposition": { "version": "0.5.3", @@ -2549,7 +2572,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", - "dev": true, "requires": { "cids": "^0.7.1", "multicodec": "^0.5.5", @@ -2590,6 +2612,17 @@ "vary": "^1" } }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, "create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -2628,7 +2661,6 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.3.tgz", "integrity": "sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw==", - "dev": true, "requires": { "node-fetch": "2.1.2", "whatwg-fetch": "2.0.4" @@ -2637,11 +2669,20 @@ "node-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true + "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=" } } }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -2680,8 +2721,7 @@ "death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=", - "dev": true + "integrity": "sha1-AaqcQB7dknUFFEcLgmY5DGbGcxg=" }, "debug": { "version": "2.6.9", @@ -2694,8 +2734,7 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, "decode-uri-component": { "version": "0.2.0", @@ -2795,7 +2834,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, "requires": { "type-detect": "^4.0.0" } @@ -2803,8 +2841,7 @@ "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, "defer-to-connect": { "version": "1.1.3", @@ -2815,7 +2852,6 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", - "dev": true, "requires": { "abstract-leveldown": "~2.6.0" } @@ -2823,8 +2859,7 @@ "delay": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", - "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==", - "dev": true + "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==" }, "delayed-stream": { "version": "1.0.0", @@ -2854,7 +2889,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", - "dev": true, "requires": { "address": "^1.0.1", "debug": "^2.6.0" @@ -2863,8 +2897,7 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, "diffie-hellman": { "version": "5.0.3", @@ -2880,11 +2913,23 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, "requires": { "path-type": "^4.0.0" } }, + "dir-to-object": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-to-object/-/dir-to-object-2.0.0.tgz", + "integrity": "sha512-sXs0JKIhymON7T1UZuO2Ud6VTNAx/VTBXIl4+3mjb2RgfOpt+hectX0x04YqPOPdkeOAKoJuKqwqnXXURNPNEA==" + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "requires": { + "esutils": "^2.0.2" + } + }, "dom-walk": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", @@ -2893,8 +2938,7 @@ "dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", - "dev": true + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" }, "duplexer3": { "version": "0.1.4", @@ -2932,8 +2976,7 @@ "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" }, "encodeurl": { "version": "1.0.2", @@ -2944,7 +2987,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, "requires": { "iconv-lite": "^0.6.2" }, @@ -2953,7 +2995,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3.0.0" } @@ -2968,15 +3009,30 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "requires": { + "ansi-colors": "^4.1.1" + } + }, "errno": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, "requires": { "prr": "~1.0.1" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es5-ext": { "version": "0.10.53", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", @@ -3014,14 +3070,12 @@ "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, "requires": { "esprima": "^2.7.1", "estraverse": "^1.9.1", @@ -3033,14 +3087,12 @@ "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, "optional": true, "requires": { "amdefine": ">=0.0.4" @@ -3048,23 +3100,247 @@ } } }, + "eslint": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.18.0.tgz", + "integrity": "sha512-fbgTiE8BfUJZuBeq2Yi7J3RB3WGUQ9PNuNbmgi6jt9Iv8qrkxfy19Ds3OpL1Pm7zg3BtTVhvcUZbIRQ0wmSjAQ==", + "requires": { + "@babel/code-frame": "^7.0.0", + "@eslint/eslintrc": "^0.3.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.20", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + } + } + }, + "eslint-config-prettier": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", + "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==" + }, + "eslint-plugin-truffle": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-truffle/-/eslint-plugin-truffle-0.3.1.tgz", + "integrity": "sha512-mjDM1gD96UknBUSEufgdx5m1x3jkWL3Xn/npSZhOVoTbKk/nkBL7dCcH7xsO6GyAjmjvzdev5o5IA4lKWf9b4g==" + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + } + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==" + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true + "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", @@ -3075,7 +3351,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz", "integrity": "sha512-A8tG4Z4iNg4mw5tP1Vung9N9IjgMNqpiMoJ/FouSFwNCGHv2X0mmOYwtQOJzki6XN7r7Tyo01S29p7b224I4jw==", - "dev": true, "requires": { "@babel/plugin-transform-runtime": "^7.5.5", "@babel/runtime": "^7.5.5", @@ -3088,8 +3363,7 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" } } }, @@ -3106,7 +3380,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.2.tgz", "integrity": "sha512-uBCRM2w2ewusRHGxN8JhcuOb2RN3ueAOYH/0BhqdFmQkZx5lj5+fLKTz0mIVOzd4FG5/kUksCzCD7eTEim6gaA==", - "dev": true, "requires": { "fast-safe-stringify": "^2.0.6" } @@ -3145,7 +3418,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", - "dev": true, "requires": { "json-rpc-random-id": "^1.0.0", "xtend": "^4.0.1" @@ -3155,7 +3427,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/eth-rpc-errors/-/eth-rpc-errors-3.0.0.tgz", "integrity": "sha512-iPPNHPrLwUlR9xCSYm7HHQjWBasor3+KZfRvwEWxMz3ca0yqnlBeJrnyphkGIXZ4J7AMAaOLmwy4AWhnxOiLxg==", - "dev": true, "requires": { "fast-safe-stringify": "^2.0.6" } @@ -3164,7 +3435,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.7.tgz", "integrity": "sha512-cDcJJSJ9GMAcURiAWO3DxIEhTL/uWqlQnvgKpuYQzYPrt/izuGU+1ntQmHt0IRq6ADoSYHFnB+aCEFIldjhkMQ==", - "dev": true, "requires": { "js-sha3": "^0.8.0" }, @@ -3172,22 +3442,19 @@ "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" } } }, "ethereum-common": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", - "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==", - "dev": true + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" }, "ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, "requires": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -3209,14 +3476,12 @@ "ethereum-protocol": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ethereum-protocol/-/ethereum-protocol-1.0.1.tgz", - "integrity": "sha512-3KLX1mHuEsBW0dKG+c6EOJS1NBNqdCICvZW9sInmZTt5aY0oxmHVggYRE0lJu1tcnMD1K+AKHdLi6U43Awm1Vg==", - "dev": true + "integrity": "sha512-3KLX1mHuEsBW0dKG+c6EOJS1NBNqdCICvZW9sInmZTt5aY0oxmHVggYRE0lJu1tcnMD1K+AKHdLi6U43Awm1Vg==" }, "ethereumjs-abi": { "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", - "dev": true, "requires": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -3226,7 +3491,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -3243,7 +3507,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", - "dev": true, "requires": { "ethereumjs-util": "^5.0.0", "rlp": "^2.0.0", @@ -3254,7 +3517,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -3271,7 +3533,6 @@ "version": "1.7.1", "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", - "dev": true, "requires": { "async": "^2.0.1", "ethereum-common": "0.2.0", @@ -3284,7 +3545,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -3300,14 +3560,12 @@ "ethereumjs-common": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz", - "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==", - "dev": true + "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA==" }, "ethereumjs-tx": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", - "dev": true, "requires": { "ethereum-common": "^0.0.18", "ethereumjs-util": "^5.0.0" @@ -3316,14 +3574,12 @@ "ethereum-common": { "version": "0.0.18", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=", - "dev": true + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" }, "ethereumjs-util": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -3340,7 +3596,6 @@ "version": "7.0.7", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.7.tgz", "integrity": "sha512-vU5rtZBlZsgkTw3o6PDKyB8li2EgLavnAbsKcfsH2YhHH1Le+PP8vEiMnAnvgc1B6uMoaM5GDCrVztBw0Q5K9g==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^5.1.2", @@ -3353,8 +3608,7 @@ "bn.js": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==" } } }, @@ -3362,7 +3616,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz", "integrity": "sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw==", - "dev": true, "requires": { "async": "^2.1.2", "async-eventemitter": "^0.2.2", @@ -3381,7 +3634,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", - "dev": true, "requires": { "async": "^2.0.1", "ethereumjs-common": "^1.5.0", @@ -3394,7 +3646,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -3411,7 +3662,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", - "dev": true, "requires": { "ethereumjs-common": "^1.5.0", "ethereumjs-util": "^6.0.0" @@ -3421,7 +3671,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -3438,7 +3687,6 @@ "version": "0.6.5", "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz", "integrity": "sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA==", - "dev": true, "requires": { "aes-js": "^3.1.1", "bs58check": "^2.1.2", @@ -3454,14 +3702,12 @@ "aes-js": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", - "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==", - "dev": true + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" }, "ethereumjs-util": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -3476,7 +3722,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-1.2.1.tgz", "integrity": "sha1-oyJfpLJST4AnAHYeKFW987LZIWM=", - "dev": true, "requires": { "pbkdf2": "^3.0.3" } @@ -3539,7 +3784,6 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dev": true, "requires": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -3553,8 +3797,7 @@ "events": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==" }, "evp_bytestokey": { "version": "1.0.3", @@ -3629,6 +3872,16 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -3638,7 +3891,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", - "dev": true, "requires": { "checkpoint-store": "^1.1.0" } @@ -3648,11 +3900,15 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==" + }, "fast-glob": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", - "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -3670,20 +3926,17 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" }, "fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", - "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", - "dev": true + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, "fastq": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", - "dev": true, "requires": { "reusify": "^1.0.4" } @@ -3700,11 +3953,33 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", - "dev": true, "requires": { "node-fetch": "~1.7.1" } }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + } + } + }, + "file-entry-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", + "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-type": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", @@ -3719,7 +3994,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -3742,7 +4016,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, "requires": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -3751,29 +4024,27 @@ "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "flatted": "^3.1.0", + "rimraf": "^3.0.2" } }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + }, + "follow-redirects": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz", + "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg==" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3825,27 +4096,23 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, "optional": true }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "ganache-cli": { "version": "6.12.1", "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.12.1.tgz", "integrity": "sha512-zoefZLQpQyEJH9jgtVYgM+ENFLAC9iwys07IDCsju2Ieq9KSTLH89RxSP4bhizXKV/h/+qaWpfyCBGWnBfqgIQ==", - "dev": true, "requires": { "ethereumjs-util": "6.2.1", "source-map-support": "0.5.12", @@ -3855,20 +4122,17 @@ "@types/bn.js": { "version": "4.11.6", "bundled": true, - "dev": true, "requires": { "@types/node": "*" } }, "@types/node": { "version": "14.11.2", - "bundled": true, - "dev": true + "bundled": true }, "@types/pbkdf2": { "version": "3.1.0", "bundled": true, - "dev": true, "requires": { "@types/node": "*" } @@ -3876,20 +4140,17 @@ "@types/secp256k1": { "version": "4.0.1", "bundled": true, - "dev": true, "requires": { "@types/node": "*" } }, "ansi-regex": { "version": "4.1.0", - "bundled": true, - "dev": true + "bundled": true }, "ansi-styles": { "version": "3.2.1", "bundled": true, - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -3897,30 +4158,25 @@ "base-x": { "version": "3.0.8", "bundled": true, - "dev": true, "requires": { "safe-buffer": "^5.0.1" } }, "blakejs": { "version": "1.1.0", - "bundled": true, - "dev": true + "bundled": true }, "bn.js": { "version": "4.11.9", - "bundled": true, - "dev": true + "bundled": true }, "brorand": { "version": "1.1.0", - "bundled": true, - "dev": true + "bundled": true }, "browserify-aes": { "version": "1.2.0", "bundled": true, - "dev": true, "requires": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -3933,7 +4189,6 @@ "bs58": { "version": "4.0.1", "bundled": true, - "dev": true, "requires": { "base-x": "^3.0.2" } @@ -3941,7 +4196,6 @@ "bs58check": { "version": "2.1.2", "bundled": true, - "dev": true, "requires": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -3950,23 +4204,19 @@ }, "buffer-from": { "version": "1.1.1", - "bundled": true, - "dev": true + "bundled": true }, "buffer-xor": { "version": "1.0.3", - "bundled": true, - "dev": true + "bundled": true }, "camelcase": { "version": "5.3.1", - "bundled": true, - "dev": true + "bundled": true }, "cipher-base": { "version": "1.0.4", "bundled": true, - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -3975,7 +4225,6 @@ "cliui": { "version": "5.0.0", "bundled": true, - "dev": true, "requires": { "string-width": "^3.1.0", "strip-ansi": "^5.2.0", @@ -3985,20 +4234,17 @@ "color-convert": { "version": "1.9.3", "bundled": true, - "dev": true, "requires": { "color-name": "1.1.3" } }, "color-name": { "version": "1.1.3", - "bundled": true, - "dev": true + "bundled": true }, "create-hash": { "version": "1.2.0", "bundled": true, - "dev": true, "requires": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -4010,7 +4256,6 @@ "create-hmac": { "version": "1.1.7", "bundled": true, - "dev": true, "requires": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -4023,7 +4268,6 @@ "cross-spawn": { "version": "6.0.5", "bundled": true, - "dev": true, "requires": { "nice-try": "^1.0.4", "path-key": "^2.0.1", @@ -4034,13 +4278,11 @@ }, "decamelize": { "version": "1.2.0", - "bundled": true, - "dev": true + "bundled": true }, "elliptic": { "version": "6.5.3", "bundled": true, - "dev": true, "requires": { "bn.js": "^4.4.0", "brorand": "^1.0.1", @@ -4053,13 +4295,11 @@ }, "emoji-regex": { "version": "7.0.3", - "bundled": true, - "dev": true + "bundled": true }, "end-of-stream": { "version": "1.4.4", "bundled": true, - "dev": true, "requires": { "once": "^1.4.0" } @@ -4067,7 +4307,6 @@ "ethereum-cryptography": { "version": "0.1.3", "bundled": true, - "dev": true, "requires": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -4089,7 +4328,6 @@ "ethereumjs-util": { "version": "6.2.1", "bundled": true, - "dev": true, "requires": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -4103,7 +4341,6 @@ "ethjs-util": { "version": "0.1.6", "bundled": true, - "dev": true, "requires": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -4112,7 +4349,6 @@ "evp_bytestokey": { "version": "1.0.3", "bundled": true, - "dev": true, "requires": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -4121,7 +4357,6 @@ "execa": { "version": "1.0.0", "bundled": true, - "dev": true, "requires": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", @@ -4135,20 +4370,17 @@ "find-up": { "version": "3.0.0", "bundled": true, - "dev": true, "requires": { "locate-path": "^3.0.0" } }, "get-caller-file": { "version": "2.0.5", - "bundled": true, - "dev": true + "bundled": true }, "get-stream": { "version": "4.1.0", "bundled": true, - "dev": true, "requires": { "pump": "^3.0.0" } @@ -4156,7 +4388,6 @@ "hash-base": { "version": "3.1.0", "bundled": true, - "dev": true, "requires": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -4166,7 +4397,6 @@ "hash.js": { "version": "1.1.7", "bundled": true, - "dev": true, "requires": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -4175,7 +4405,6 @@ "hmac-drbg": { "version": "1.0.1", "bundled": true, - "dev": true, "requires": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -4184,38 +4413,31 @@ }, "inherits": { "version": "2.0.4", - "bundled": true, - "dev": true + "bundled": true }, "invert-kv": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "is-hex-prefixed": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "is-stream": { "version": "1.1.0", - "bundled": true, - "dev": true + "bundled": true }, "isexe": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "keccak": { "version": "3.0.1", "bundled": true, - "dev": true, "requires": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0" @@ -4224,7 +4446,6 @@ "lcid": { "version": "2.0.0", "bundled": true, - "dev": true, "requires": { "invert-kv": "^2.0.0" } @@ -4232,7 +4453,6 @@ "locate-path": { "version": "3.0.0", "bundled": true, - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4241,7 +4461,6 @@ "map-age-cleaner": { "version": "0.1.3", "bundled": true, - "dev": true, "requires": { "p-defer": "^1.0.0" } @@ -4249,7 +4468,6 @@ "md5.js": { "version": "1.3.5", "bundled": true, - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -4259,7 +4477,6 @@ "mem": { "version": "4.3.0", "bundled": true, - "dev": true, "requires": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^2.0.0", @@ -4268,38 +4485,31 @@ }, "mimic-fn": { "version": "2.1.0", - "bundled": true, - "dev": true + "bundled": true }, "minimalistic-assert": { "version": "1.0.1", - "bundled": true, - "dev": true + "bundled": true }, "minimalistic-crypto-utils": { "version": "1.0.1", - "bundled": true, - "dev": true + "bundled": true }, "nice-try": { "version": "1.0.5", - "bundled": true, - "dev": true + "bundled": true }, "node-addon-api": { "version": "2.0.2", - "bundled": true, - "dev": true + "bundled": true }, "node-gyp-build": { "version": "4.2.3", - "bundled": true, - "dev": true + "bundled": true }, "npm-run-path": { "version": "2.0.2", "bundled": true, - "dev": true, "requires": { "path-key": "^2.0.0" } @@ -4307,7 +4517,6 @@ "once": { "version": "1.4.0", "bundled": true, - "dev": true, "requires": { "wrappy": "1" } @@ -4315,7 +4524,6 @@ "os-locale": { "version": "3.1.0", "bundled": true, - "dev": true, "requires": { "execa": "^1.0.0", "lcid": "^2.0.0", @@ -4324,23 +4532,19 @@ }, "p-defer": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "p-finally": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "p-is-promise": { "version": "2.1.0", - "bundled": true, - "dev": true + "bundled": true }, "p-limit": { "version": "2.3.0", "bundled": true, - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4348,30 +4552,25 @@ "p-locate": { "version": "3.0.0", "bundled": true, - "dev": true, "requires": { "p-limit": "^2.0.0" } }, "p-try": { "version": "2.2.0", - "bundled": true, - "dev": true + "bundled": true }, "path-exists": { "version": "3.0.0", - "bundled": true, - "dev": true + "bundled": true }, "path-key": { "version": "2.0.1", - "bundled": true, - "dev": true + "bundled": true }, "pbkdf2": { "version": "3.1.1", "bundled": true, - "dev": true, "requires": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -4383,7 +4582,6 @@ "pump": { "version": "3.0.0", "bundled": true, - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -4392,7 +4590,6 @@ "randombytes": { "version": "2.1.0", "bundled": true, - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -4400,7 +4597,6 @@ "readable-stream": { "version": "3.6.0", "bundled": true, - "dev": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -4409,18 +4605,15 @@ }, "require-directory": { "version": "2.1.1", - "bundled": true, - "dev": true + "bundled": true }, "require-main-filename": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "ripemd160": { "version": "2.0.2", "bundled": true, - "dev": true, "requires": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -4429,25 +4622,21 @@ "rlp": { "version": "2.2.6", "bundled": true, - "dev": true, "requires": { "bn.js": "^4.11.1" } }, "safe-buffer": { "version": "5.2.1", - "bundled": true, - "dev": true + "bundled": true }, "scrypt-js": { "version": "3.0.1", - "bundled": true, - "dev": true + "bundled": true }, "secp256k1": { "version": "4.0.2", "bundled": true, - "dev": true, "requires": { "elliptic": "^6.5.2", "node-addon-api": "^2.0.0", @@ -4456,23 +4645,19 @@ }, "semver": { "version": "5.7.1", - "bundled": true, - "dev": true + "bundled": true }, "set-blocking": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "setimmediate": { "version": "1.0.5", - "bundled": true, - "dev": true + "bundled": true }, "sha.js": { "version": "2.4.11", "bundled": true, - "dev": true, "requires": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -4481,30 +4666,25 @@ "shebang-command": { "version": "1.2.0", "bundled": true, - "dev": true, "requires": { "shebang-regex": "^1.0.0" } }, "shebang-regex": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "signal-exit": { "version": "3.0.3", - "bundled": true, - "dev": true + "bundled": true }, "source-map": { "version": "0.6.1", - "bundled": true, - "dev": true + "bundled": true }, "source-map-support": { "version": "0.5.12", "bundled": true, - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4513,7 +4693,6 @@ "string-width": { "version": "3.1.0", "bundled": true, - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -4523,7 +4702,6 @@ "string_decoder": { "version": "1.3.0", "bundled": true, - "dev": true, "requires": { "safe-buffer": "~5.2.0" } @@ -4531,46 +4709,39 @@ "strip-ansi": { "version": "5.2.0", "bundled": true, - "dev": true, "requires": { "ansi-regex": "^4.1.0" } }, "strip-eof": { "version": "1.0.0", - "bundled": true, - "dev": true + "bundled": true }, "strip-hex-prefix": { "version": "1.0.0", "bundled": true, - "dev": true, "requires": { "is-hex-prefixed": "1.0.0" } }, "util-deprecate": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true }, "which": { "version": "1.3.1", "bundled": true, - "dev": true, "requires": { "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", - "bundled": true, - "dev": true + "bundled": true }, "wrap-ansi": { "version": "5.1.0", "bundled": true, - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -4579,18 +4750,15 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "dev": true + "bundled": true }, "y18n": { "version": "4.0.0", - "bundled": true, - "dev": true + "bundled": true }, "yargs": { "version": "13.2.4", "bundled": true, - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -4608,7 +4776,6 @@ "yargs-parser": { "version": "13.1.2", "bundled": true, - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -4619,14 +4786,12 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" }, "get-stream": { "version": "4.1.0", @@ -4648,7 +4813,6 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, "requires": { "chalk": "^2.4.2", "node-emoji": "^1.10.0" @@ -4658,7 +4822,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -4667,7 +4830,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4678,7 +4840,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -4686,26 +4847,22 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -4716,7 +4873,6 @@ "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4730,7 +4886,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -4748,7 +4903,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, "requires": { "global-prefix": "^3.0.0" } @@ -4757,7 +4911,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, "requires": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -4768,18 +4921,24 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "requires": { "isexe": "^2.0.0" } } } }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "requires": { + "type-fest": "^0.8.1" + } + }, "globby": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, "requires": { "@types/glob": "^7.1.1", "array-union": "^2.1.0", @@ -4817,14 +4976,12 @@ "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==" }, "handlebars": { "version": "4.7.6", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "dev": true, "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -4850,8 +5007,7 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbol-support-x": { "version": "1.4.2", @@ -4900,8 +5056,7 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" }, "hmac-drbg": { "version": "1.0.1", @@ -4983,20 +5138,31 @@ "ignore": { "version": "5.1.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, "immediate": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", - "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", - "dev": true + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==" + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -5010,46 +5176,134 @@ "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } }, "interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=" + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", - "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=", - "dev": true + "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=" }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-function": { "version": "1.0.2", @@ -5060,7 +5314,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -5078,8 +5331,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-object": { "version": "1.0.2", @@ -5114,8 +5366,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -5136,11 +5387,15 @@ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -5156,11 +5411,15 @@ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + }, "json-rpc-engine": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-5.4.0.tgz", "integrity": "sha512-rAffKbPoNDjuRnXkecTjnsE3xLLrb00rEkdgalINhaYVYIxDwWtvYBr9UFbhTvPB1B2qUOLoFd/cV6f4Q7mh7g==", - "dev": true, "requires": { "eth-rpc-errors": "^3.0.0", "safe-event-emitter": "^1.0.1" @@ -5169,8 +5428,7 @@ "json-rpc-random-id": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", - "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=", - "dev": true + "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=" }, "json-schema": { "version": "0.2.3", @@ -5186,11 +5444,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, "requires": { "jsonify": "~0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -5207,14 +5469,12 @@ "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" }, "jsonschema": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.0.tgz", - "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==", - "dev": true + "integrity": "sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==" }, "jsprim": { "version": "1.4.1", @@ -5231,7 +5491,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.1.tgz", "integrity": "sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA==", - "dev": true, "requires": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0" @@ -5248,20 +5507,17 @@ "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "level-codec": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", - "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==", - "dev": true + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" }, "level-errors": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", - "dev": true, "requires": { "errno": "~0.1.1" } @@ -5270,7 +5526,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", - "dev": true, "requires": { "inherits": "^2.0.1", "level-errors": "^1.0.3", @@ -5281,14 +5536,12 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "readable-stream": { "version": "1.1.14", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -5299,8 +5552,7 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" } } }, @@ -5308,7 +5560,6 @@ "version": "0.0.0", "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", - "dev": true, "requires": { "readable-stream": "~1.0.15", "xtend": "~2.1.1" @@ -5317,14 +5568,12 @@ "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, "readable-stream": { "version": "1.0.34", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -5335,14 +5584,12 @@ "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "xtend": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, "requires": { "object-keys": "~0.4.0" } @@ -5353,7 +5600,6 @@ "version": "1.3.9", "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", - "dev": true, "requires": { "deferred-leveldown": "~1.2.1", "level-codec": "~7.0.0", @@ -5367,8 +5613,7 @@ "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" } } }, @@ -5376,7 +5621,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -5386,7 +5630,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, "requires": { "p-locate": "^5.0.0" } @@ -5394,14 +5637,12 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lodash.flatmap": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz", - "integrity": "sha1-74y/QI9uSCaGYzRTBcaswLd4cC4=", - "dev": true + "integrity": "sha1-74y/QI9uSCaGYzRTBcaswLd4cC4=" }, "lodash.isequal": { "version": "4.5.0", @@ -5411,14 +5652,12 @@ "lodash.toarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", - "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", - "dev": true + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, "requires": { "chalk": "^4.0.0" } @@ -5432,7 +5671,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" }, @@ -5440,16 +5678,14 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "ltgt": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" }, "make-dir": { "version": "1.3.0", @@ -5485,7 +5721,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", - "dev": true, "requires": { "abstract-leveldown": "~2.7.1", "functional-red-black-tree": "^1.0.1", @@ -5499,7 +5734,6 @@ "version": "2.7.2", "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", - "dev": true, "requires": { "xtend": "~4.0.0" } @@ -5507,8 +5741,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" } } }, @@ -5520,14 +5753,12 @@ "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, "merkle-patricia-tree": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz", "integrity": "sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g==", - "dev": true, "requires": { "async": "^1.4.2", "ethereumjs-util": "^5.0.0", @@ -5542,14 +5773,12 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "ethereumjs-util": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz", "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==", - "dev": true, "requires": { "bn.js": "^4.11.0", "create-hash": "^1.1.2", @@ -5571,7 +5800,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, "requires": { "braces": "^3.0.1", "picomatch": "^2.0.5" @@ -5604,6 +5832,11 @@ "mime-db": "1.44.0" } }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, "mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -5631,7 +5864,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5675,7 +5907,6 @@ "version": "8.2.1", "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", - "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", @@ -5708,7 +5939,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -5716,8 +5946,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" } } }, @@ -5735,7 +5964,6 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", - "dev": true, "requires": { "base-x": "^3.0.8", "buffer": "^5.5.0" @@ -5745,7 +5973,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", - "dev": true, "requires": { "varint": "^5.0.0" } @@ -5754,7 +5981,6 @@ "version": "0.4.21", "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", - "dev": true, "requires": { "buffer": "^5.5.0", "multibase": "^0.7.0", @@ -5765,7 +5991,6 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", - "dev": true, "requires": { "base-x": "^3.0.8", "buffer": "^5.5.0" @@ -5773,6 +5998,11 @@ } } }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, "nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", @@ -5786,8 +6016,12 @@ "nanoid": { "version": "3.1.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", - "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", - "dev": true + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "negotiator": { "version": "0.6.2", @@ -5797,25 +6031,27 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, "node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", - "dev": true + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, "node-emoji": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz", "integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==", - "dev": true, "requires": { "lodash.toarray": "^4.4.0" } @@ -5824,7 +6060,6 @@ "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "dev": true, "requires": { "encoding": "^0.1.11", "is-stream": "^1.0.1" @@ -5839,7 +6074,6 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1" } @@ -5847,8 +6081,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-url": { "version": "4.5.0", @@ -5884,8 +6117,7 @@ "object-keys": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" }, "oboe": { "version": "2.1.4", @@ -5911,11 +6143,18 @@ "wrappy": "1" } }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, "optionator": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -5928,8 +6167,12 @@ "original-require": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/original-require/-/original-require-1.0.1.tgz", - "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=", - "dev": true + "integrity": "sha1-DxMEcVhM0zURxew4yNWSE/msXiA=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "p-cancelable": { "version": "1.1.0", @@ -5945,7 +6188,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, "requires": { "yocto-queue": "^0.1.0" } @@ -5954,7 +6196,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, "requires": { "p-limit": "^3.0.2" } @@ -5970,8 +6211,22 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + } + } }, "parse-asn1": { "version": "5.1.6", @@ -5990,6 +6245,15 @@ "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5998,14 +6262,22 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-to-regexp": { "version": "0.1.7", @@ -6015,14 +6287,12 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pathval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", - "dev": true + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" }, "pbkdf2": { "version": "3.1.1", @@ -6049,8 +6319,7 @@ "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" }, "pify": { "version": "2.3.0", @@ -6073,20 +6342,93 @@ "precond": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", - "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=", - "dev": true + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" }, + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==" + }, + "prettier-plugin-solidity": { + "version": "1.0.0-beta.3", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.3.tgz", + "integrity": "sha512-iLbf5ZqwSUqi/BQuRGh+fHy0y3VLX9WayI7qB3wqakSUHItbiKsUKyXbTeho4pfTJVr0D3M4c8BNuEr2OMAOVg==", + "requires": { + "@solidity-parser/parser": "^0.11.0", + "dir-to-object": "^2.0.0", + "emoji-regex": "^9.0.0", + "escape-string-regexp": "^4.0.0", + "prettier": "^2.0.5", + "semver": "^7.3.2", + "solidity-comments-extractor": "^0.0.4", + "string-width": "^4.2.0" + }, + "dependencies": { + "@solidity-parser/parser": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.11.1.tgz", + "integrity": "sha512-H8BSBoKE8EubJa0ONqecA2TviT3TnHeC4NpgnAHSUiuhZoQBfPB4L2P9bs8R6AoTW10Endvh3vc+fomVMIDIYQ==" + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.0.tgz", + "integrity": "sha512-DNc3KFPK18bPdElMJnf/Pkv5TXhxFU3YFDEuGLDRtPmV4rkmCjBkCSEp22u6rBHdSN9Vlp/GK7k98prmE1Jgug==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -6097,11 +6439,15 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, "promise-to-callback": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", - "dev": true, "requires": { "is-fn": "^1.0.0", "set-immediate-shim": "^1.0.1" @@ -6119,8 +6465,7 @@ "prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" }, "psl": { "version": "1.8.0", @@ -6172,8 +6517,7 @@ "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "randombytes": { "version": "2.1.0", @@ -6238,7 +6582,6 @@ "version": "3.5.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -6247,7 +6590,6 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, "requires": { "resolve": "^1.1.6" } @@ -6256,7 +6598,6 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dev": true, "requires": { "minimatch": "3.0.4" } @@ -6264,8 +6605,12 @@ "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==" }, "request": { "version": "2.88.2", @@ -6304,20 +6649,27 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "responselike": { "version": "1.0.2", @@ -6327,11 +6679,27 @@ "lowercase-keys": "^1.0.0" } }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } }, "ripemd160": { "version": "2.0.2", @@ -6346,22 +6714,32 @@ "version": "2.2.6", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.6.tgz", "integrity": "sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg==", - "dev": true, "requires": { "bn.js": "^4.11.1" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, "run-parallel": { "version": "1.1.10", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", - "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", - "dev": true + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==" }, "rustbn.js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==", - "dev": true + "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "requires": { + "tslib": "^1.9.0" + } }, "safe-buffer": { "version": "5.2.1", @@ -6372,7 +6750,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz", "integrity": "sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg==", - "dev": true, "requires": { "events": "^3.0.0" } @@ -6386,7 +6763,6 @@ "version": "0.4.5", "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.5.tgz", "integrity": "sha512-7wR5EZFLsC4w0wSm9BUuCgW+OGKAU7PNlW5L0qwVPbh+Q1sfVn2fyzfMXYCm6rkNA5ipaCOt94nApcguQwF5Gg==", - "dev": true, "requires": { "abbrev": "1.0.x", "async": "1.x", @@ -6407,20 +6783,17 @@ "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, "esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, "requires": { "inflight": "^1.0.4", "inherits": "2", @@ -6432,14 +6805,12 @@ "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" }, "mkdirp": { "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, "requires": { "minimist": "^1.2.5" } @@ -6448,7 +6819,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, "requires": { "has-flag": "^1.0.0" } @@ -6457,7 +6827,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -6478,7 +6847,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.2.tgz", "integrity": "sha512-UDar4sKvWAksIlfX3xIaQReADn+WFnHvbVujpcbr+9Sf/69odMwy2MUsz5CKLQgX9nsIyrjuxL2imVyoNHa3fg==", - "dev": true, "requires": { "elliptic": "^6.5.2", "node-addon-api": "^2.0.0", @@ -6496,8 +6864,7 @@ "semaphore": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", - "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==", - "dev": true + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" }, "semver": { "version": "6.2.0", @@ -6535,7 +6902,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, "requires": { "randombytes": "^2.1.0" } @@ -6566,14 +6932,12 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "set-immediate-shim": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" }, "setimmediate": { "version": "1.0.5", @@ -6594,17 +6958,34 @@ "safe-buffer": "^5.0.1" } }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, "shelljs": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", - "dev": true, "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" } }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, "simple-concat": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", @@ -6623,14 +7004,397 @@ "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + } + } + }, + "solhint": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-3.3.2.tgz", + "integrity": "sha512-8tHCkIAk1axLLG6Qu2WIH3GgNABonj9eAWejJbov3o3ujkZQRNHeHU1cC4/Dmjsh3Om7UzFFeADUHu2i7ZJeiw==", + "requires": { + "@solidity-parser/parser": "^0.8.2", + "ajv": "^6.6.1", + "antlr4": "4.7.1", + "ast-parents": "0.0.1", + "chalk": "^2.4.2", + "commander": "2.18.0", + "cosmiconfig": "^5.0.7", + "eslint": "^5.6.0", + "fast-diff": "^1.1.2", + "glob": "^7.1.3", + "ignore": "^4.0.6", + "js-yaml": "^3.12.0", + "lodash": "^4.17.11", + "prettier": "^1.14.3", + "semver": "^6.3.0" + }, + "dependencies": { + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==" + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "commander": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.18.0.tgz", + "integrity": "sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ==" + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==" + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "optional": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==" + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "solidity-comments-extractor": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.4.tgz", + "integrity": "sha512-58glBODwXIKMaQ7rfcJOrWtFQMMOK28tJ0/LcB5Xhu7WtAxk4UX2fpgKPuaL41XjMp/y0gAa1MTLqk018wuSzA==" }, "solidity-coverage": { "version": "0.7.13", "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.7.13.tgz", "integrity": "sha512-06r0R+/j8lgl5/Z57VwxWNFZId0ZavcQU45W2gCfsBmEt/1Y6Xgm96oMSa6JBIvwrPR8H4T3icxTLiUVsMFNeg==", - "dev": true, "requires": { "@solidity-parser/parser": "^0.8.1", "@truffle/provider": "^0.2.24", @@ -6657,7 +7421,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -6666,7 +7429,6 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -6677,7 +7439,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -6685,20 +7446,17 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", - "dev": true, "requires": { "bn.js": "^4.11.6", "elliptic": "^6.4.0", @@ -6709,7 +7467,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -6719,20 +7476,17 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" }, "semver": { "version": "7.3.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -6741,7 +7495,6 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -6750,7 +7503,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.0.tgz", "integrity": "sha512-2mS5axFCbkhicmoDRuJeuo0TVGQDgC2sPi/5dblfVC+PMtX0efrb8Xlttv/eGkq7X4E83Pds34FH98TP2WOUZA==", - "dev": true, "requires": { "bn.js": "^4.11.9", "eth-lib": "0.2.8", @@ -6767,14 +7519,12 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6783,8 +7533,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", @@ -6816,7 +7565,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -6841,7 +7589,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "^3.0.0" } @@ -6865,14 +7612,12 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -6942,6 +7687,68 @@ } } }, + "table": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", + "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", + "requires": { + "ajv": "^7.0.2", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "dependencies": { + "ajv": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz", + "integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "tar": { "version": "4.4.13", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", @@ -6980,6 +7787,11 @@ "xtend": "^4.0.0" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -6990,6 +7802,14 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -6998,8 +7818,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-readable-stream": { "version": "1.0.0", @@ -7010,7 +7829,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -7033,7 +7851,6 @@ "version": "5.1.10", "resolved": "https://registry.npmjs.org/truffle/-/truffle-5.1.10.tgz", "integrity": "sha512-7dkBjNwabpNUp2LTSsXWUk5TMOfomX9F0mPLDEZgAgmfH3qWG5rBEUn/jw5t0LQfVx8NCG+GIN9FxqiUIEWrYQ==", - "dev": true, "requires": { "app-module-path": "^2.2.0", "mocha": "5.2.0", @@ -7043,14 +7860,12 @@ "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -7058,20 +7873,17 @@ "diff": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -7084,26 +7896,22 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "minimist": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" }, "mkdirp": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, "requires": { "minimist": "0.0.8" } @@ -7112,7 +7920,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, "requires": { "browser-stdout": "1.3.1", "commander": "2.15.1", @@ -7131,7 +7938,6 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, "requires": { "has-flag": "^3.0.0" } @@ -7147,29 +7953,48 @@ "lodash.isequal": "^4.5.0" } }, - "truffle-hdwallet-provider": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/truffle-hdwallet-provider/-/truffle-hdwallet-provider-1.0.17.tgz", - "integrity": "sha512-s6DvSP83jiIAc6TUcpr7Uqnja1+sLGJ8og3X7n41vfyC4OCaKmBtXL5HOHf+SsU3iblOvnbFDgmN6Y1VBL/fsg==", - "requires": { - "any-promise": "^1.3.0", - "bindings": "^1.3.1", - "web3": "1.2.1", - "websocket": "^1.0.28" - } - }, "truffle-plugin-verify": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/truffle-plugin-verify/-/truffle-plugin-verify-0.5.2.tgz", "integrity": "sha512-2D1GdfdfltvXRf/VYgFep+uouBtdFWi/O2xA1/khqEg9pREmtNXEYzDjozpOInJ1jzoyn30oFUyb1rouD0dlqw==", - "dev": true, "requires": { "axios": "0.19.2", "cli-logger": "0.5.40", "delay": "4.3.0", "querystring": "0.2.0" + }, + "dependencies": { + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + } } }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -7192,7 +8017,6 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, "requires": { "prelude-ls": "~1.1.2" } @@ -7200,8 +8024,12 @@ "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" }, "type-is": { "version": "1.6.18", @@ -7224,7 +8052,6 @@ "version": "3.12.2", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.2.tgz", "integrity": "sha512-rWYleAvfJPjduYCt+ELvzybNah/zIkRteGXIBO8X0lteRZPGladF61hFi8tU7qKTsF7u6DUQCtT9k00VlFOgkg==", - "dev": true, "optional": true }, "ultron": { @@ -7310,11 +8137,15 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==" + }, "varint": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", - "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", - "dev": true + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==" }, "vary": { "version": "1.1.2", @@ -7632,7 +8463,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#ef5ea2f41daf4a2113b80c9223df884b4d56c400" + "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" }, "dependencies": { "websocket": { @@ -7706,14 +8537,12 @@ "whatwg-fetch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", - "dev": true + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -7721,14 +8550,12 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2" } @@ -7736,26 +8563,22 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "workerpool": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", - "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", - "dev": true + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==" }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, "requires": { "ansi-styles": "^3.2.0", "string-width": "^3.0.0", @@ -7765,14 +8588,12 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -7781,7 +8602,6 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, "requires": { "color-name": "1.1.3" } @@ -7789,14 +8609,12 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -7807,7 +8625,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -7819,6 +8636,24 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "requires": { + "mkdirp": "^0.5.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "ws": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz", @@ -7878,8 +8713,7 @@ "y18n": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" }, "yaeti": { "version": "0.0.6", @@ -7895,7 +8729,6 @@ "version": "13.3.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, "requires": { "cliui": "^5.0.0", "find-up": "^3.0.0", @@ -7912,14 +8745,12 @@ "ansi-regex": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, "requires": { "locate-path": "^3.0.0" } @@ -7928,7 +8759,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -7938,7 +8768,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "requires": { "p-try": "^2.0.0" } @@ -7947,7 +8776,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, "requires": { "p-limit": "^2.0.0" } @@ -7955,14 +8783,12 @@ "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, "requires": { "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", @@ -7973,7 +8799,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, "requires": { "ansi-regex": "^4.1.0" } @@ -7984,7 +8809,6 @@ "version": "13.1.2", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -7994,7 +8818,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, "requires": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -8005,20 +8828,17 @@ "camelcase": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "dev": true + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" }, "decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" }, "is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" } } }, @@ -8034,8 +8854,7 @@ "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/package.json b/package.json index 54487dfb..3ba84afc 100644 --- a/package.json +++ b/package.json @@ -7,10 +7,19 @@ "test": "test" }, "scripts": { - "test": "truffle test", - "coverage": "node --max-old-space-size=4096 ./node_modules/.bin/truffle run coverage --network coverage", - "migrate-dev": "truffle migrate --network=rinkeby", - "verify-dev": "truffle run verify FundLimitsOracle ERC1155ERC721 VoucherKernel Cashier BosonRouter BosonTokenPrice BosonTokenDeposit --network rinkeby" + "contracts:compile": "truffle compile --all", + "contracts:lint": "solhint contracts/**/*.sol -w 32", + "contracts:lint-fix": "solhint contracts/**/*.sol -w 32 --fix", + "contracts:format": "prettier --list-different contracts/**/*.sol", + "contracts:format-fix": "prettier --write contracts/**/*.sol", + "contracts:migrate:dev": "truffle migrate --network=rinkeby", + "contracts:verify:dev": "truffle run verify FundLimitsOracle ERC1155ERC721 VoucherKernel Cashier BosonRouter BosonTokenPrice BosonTokenDeposit --network rinkeby", + "tests:lint": "eslint test/**/*.js testHelpers/**/*.js testUserInteractions/**/*.js", + "tests:lint-fix": "eslint --fix test/**/*.js testHelpers/**/*.js testUserInteractions/**/*.js", + "tests:format": "prettier --list-different test/**/*.js testHelpers/**/*.js testUserInteractions/**/*.js", + "tests:format-fix": "prettier --write test/**/*.js testHelpers/**/*.js testUserInteractions/**/*.js", + "tests:unit": "truffle test --network test", + "tests:coverage": "node --max-old-space-size=4096 ./node_modules/.bin/truffle run coverage --network coverage" }, "repository": { "type": "git", @@ -24,18 +33,22 @@ "homepage": "https://github.com/bosonprotocol/bsn-core-prototype#readme", "dependencies": { "@openzeppelin/contracts": "^3.2.0", - "ethers": "5.0.4", - "truffle-assertions": "^0.9.2", - "truffle-hdwallet-provider": "^1.0.17" - }, - "devDependencies": { "@truffle/hdwallet-provider": "^1.2.0", + "axios": "^0.20.0", "chai": "^4.2.0", "dotenv": "^8.2.0", + "eslint": "^7.18.0", + "eslint-plugin-truffle": "^0.3.1", + "eslint-config-prettier": "^7.2.0", "ethereumjs-util": "^7.0.7", + "ethers": "5.0.4", "mocha": "^8.2.1", + "prettier": "^2.2.1", + "prettier-plugin-solidity": "^1.0.0-beta.3", + "solhint": "^3.3.2", "solidity-coverage": "^0.7.12", "truffle": "5.1.10", + "truffle-assertions": "^0.9.2", "truffle-plugin-verify": "^0.5.2" } } diff --git a/test/1_test_fullpath.js b/test/1_test_fullpath.js index ef304bdb..9368e4e0 100644 --- a/test/1_test_fullpath.js +++ b/test/1_test_fullpath.js @@ -1,461 +1,708 @@ -const helpers = require("../testHelpers/constants"); -const timemachine = require('../testHelpers/timemachine'); const truffleAssert = require('truffle-assertions'); -//later consider using https://github.com/OpenZeppelin/openzeppelin-test-helpers +// later consider using +// https://github.com/OpenZeppelin/openzeppelin-test-helpers -const ERC1155ERC721 = artifacts.require("ERC1155ERC721"); -const VoucherKernel = artifacts.require("VoucherKernel"); -const Cashier = artifacts.require("Cashier"); -const BosonRouter = artifacts.require("BosonRouter") -const FundLimitsOracle = artifacts.require('FundLimitsOracle'); +const constants = require('../testHelpers/constants'); +const timemachine = require('../testHelpers/timemachine'); +const Utils = require('../testHelpers/utils'); +const Users = require('../testHelpers/users'); -const config = require('../testHelpers/config.json') +const ERC1155ERC721 = artifacts.require('ERC1155ERC721'); +const VoucherKernel = artifacts.require('VoucherKernel'); +const Cashier = artifacts.require('Cashier'); +const BosonRouter = artifacts.require('BosonRouter'); +const FundLimitsOracle = artifacts.require('FundLimitsOracle'); -const Utils = require('../testHelpers/utils') let snapshot; -contract("Voucher tests", async accounts => { - let Seller = config.accounts.seller.address - let Buyer = config.accounts.buyer.address - let Attacker = config.accounts.attacker.address - - let contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractFundLimitsOracle; - let promiseKey1, promiseKey2; - let order1payment, order1depositSe, order1depositBu; - let ordersCount; - let tokenSupplyKey1, tokenSupplyKey2, tokenVoucherKey1, tokenVoucherKey2; - - - - before('setup contracts for tests', async () => { - snapshot = await timemachine.takeSnapshot(); - - const timestamp = await Utils.getCurrTimestamp() - helpers.PROMISE_VALID_FROM = timestamp - helpers.PROMISE_VALID_TO = timestamp + 2 * helpers.SECONDS_IN_DAY; - - contractFundLimitsOracle = await FundLimitsOracle.new() - contractERC1155ERC721 = await ERC1155ERC721.new(); - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address); - contractCashier = await Cashier.new(contractVoucherKernel.address); - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true'); - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address); - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address); - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setComplainPeriod(60); //60 seconds - await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds - - console.log("Seller: " + Seller); - console.log("Buyer: " + Buyer); - console.log("Attacker: " + Attacker + "\n"); - }) - - - describe('Direct minting', function() { - - it("must fail: unauthorized minting ERC-1155", async () => { - await truffleAssert.reverts(contractERC1155ERC721.mint(Attacker, 666, 1, []), - truffleAssert.ErrorType.REVERT - ); - }); - - it("must fail: unauthorized minting ERC-721", async () => { - await truffleAssert.reverts(contractERC1155ERC721.mint(Attacker, 666), - truffleAssert.ErrorType.REVERT - ); - }); - }) - - -//in the prototype, the creation of a promise is merged into creating an order - // describe('Promises (aka offers)', function() { - - // it("adding one new promise", async () => { - // // console.log("helpers.PROMISE_VALID_FROM: ", helpers.PROMISE_VALID_FROM, ", helpers.PROMISE_VALID_TO: ", helpers.PROMISE_VALID_TO); - // await contractVoucherKernel.createTokenSupplyID(helpers.ASSET_TITLE, helpers.ASSET_PIN1, helpers.ASSET_QR1, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.PROMISE_CHALLENGE_PERIOD, helpers.PROMISE_CANCELORFAULT_PERIOD); - - // promiseKey1 = await contractVoucherKernel.promiseKeys.call(0); - - // assert.notEqual(promiseKey1, helpers.ZERO_ADDRESS, "promise not added"); - // }); - - // it("adding second new promise", async () => { - // await contractVoucherKernel.createTokenSupplyID(helpers.ASSET_TITLE2, helpers.ASSET_PIN2, helpers.ASSET_QR2, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE2, helpers.PROMISE_DEPOSITSE2, helpers.PROMISE_DEPOSITBU2, helpers.PROMISE_CHALLENGE_PERIOD, helpers.PROMISE_CANCELORFAULT_PERIOD); - - // promiseKey2 = await contractVoucherKernel.promiseKeys.call(1); - - // assert.notEqual(promiseKey2, helpers.ZERO_ADDRESS, "second promise not added"); - // }); - - // it("must fail: adding new promise with invalid validity", async () => { - // await truffleAssert.reverts(contractVoucherKernel.createTokenSupplyID(helpers.ASSET_TITLE, helpers.ASSET_PIN1, helpers.ASSET_QR1, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_FROM - 1, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.PROMISE_CHALLENGE_PERIOD, helpers.PROMISE_CANCELORFAULT_PERIOD), - // truffleAssert.ErrorType.REVERT - // ); - // }); - - // }) - - - describe('Orders (aka supply tokens - ERC1155)', function() { - - it("adding one new order / promise", async () => { - - let txOrder = await contractBosonRouter.requestCreateOrder_ETH_ETH([helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.ORDER_QUANTITY1], {from: Seller, to: contractCashier.address, value: helpers.PROMISE_DEPOSITSE1}); - - //would need truffle-events as the event emitted is from a nested contract, so truffle-assert doesn't detect it - // truffleAssert.eventEmitted(txOrder, 'LogOrderCreated', (ev) => { - // tokenSupplyKey = ev._tokenIdSupply; - // return ev._seller === Seller; - // }, "order1 not created successfully"); - - // //instead, we check that the escrow increased for the seller - // let escrowAmount = await contractBosonRouter.getEscrowAmount.call(Seller); - // assert.isAbove(escrowAmount.toNumber(), 0, "seller's escrowed deposit should be more than zero"); - - //move events from VoucherKernel to Cashier: - truffleAssert.eventEmitted(txOrder, 'LogOrderCreated', (ev) => { - tokenSupplyKey1 = ev._tokenIdSupply; - return ev._seller === Seller; - }, "order1 not created successfully"); - - }); - - it("adding second order", async () => { - - let txOrder = await contractBosonRouter.requestCreateOrder_ETH_ETH([helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE2, helpers.PROMISE_DEPOSITSE2, helpers.PROMISE_DEPOSITBU2, helpers.ORDER_QUANTITY2], {from: Seller, to: contractCashier.address, value: helpers.PROMISE_DEPOSITSE2}); - - truffleAssert.eventEmitted(txOrder, 'LogOrderCreated', (ev) => { - tokenSupplyKey2 = ev._tokenIdSupply; - return ev._seller === Seller; - }, "order2 not created successfully"); - - }); - - - it("fill one order (aka buy a voucher)", async () => { - - let txFillOrder = await contractBosonRouter.requestVoucher_ETH_ETH(tokenSupplyKey1, Seller, {from: Buyer, to: contractBosonRouter.address, value: helpers.PROMISE_PRICE1 + helpers.PROMISE_DEPOSITBU1}); - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - return ev._issuer === Seller; - }, "order1 not created successfully"); - - let filtered = internalTx.logs.filter(e => e.event == 'LogVoucherDelivered')[0] - tokenVoucherKey1 = filtered.returnValues['_tokenIdVoucher'] - }); - - - it("fill second order (aka buy a voucher)", async () => { - - let txFillOrder = await contractBosonRouter.requestVoucher_ETH_ETH(tokenSupplyKey2, Seller, {from: Buyer, to: contractBosonRouter.address, value: helpers.PROMISE_PRICE2 + helpers.PROMISE_DEPOSITBU2}); - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey2 = ev._tokenIdVoucher; - return ev._tokenIdSupply.toString() === tokenSupplyKey2.toString(); - }, "order1 not filled successfully"); - }); - - //in prototype, everyone can create an order - // it("must fail: unauthorized adding of new order", async () => { - - // await truffleAssert.reverts(contractBosonRouter.requestCreateOrder_ETH_ETH(promiseKey1, helpers.ORDER_QUANTITY1, {from: Attacker, to: contractBosonRouter.address, value: helpers.PROMISE_DEPOSITSE1}), - // truffleAssert.ErrorType.REVERT - // ); - - // }); - - - it("must fail: adding new order with incorrect value sent", async () => { - - await truffleAssert.reverts(contractBosonRouter.requestCreateOrder_ETH_ETH([helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.ORDER_QUANTITY1], {from: Seller, to: contractBosonRouter.address, value: 0}), - truffleAssert.ErrorType.REVERT - ); - - }); - - it("must fail: fill an order with incorrect value", async () => { - - await truffleAssert.reverts(contractBosonRouter.requestVoucher_ETH_ETH(tokenSupplyKey1, Seller, {from: Buyer, to: contractBosonRouter.address, value: 0}), - truffleAssert.ErrorType.REVERT - ); - - }); - - }) - - describe('Voucher tokens', function() { - - it("redeeming one voucher", async () => { - let txRedeem = await contractBosonRouter.redeem(tokenVoucherKey1, {from: Buyer}); - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txRedeem.tx)) - - - truffleAssert.eventEmitted(internalTx, 'LogVoucherRedeemed', (ev) => { - return ev._tokenIdVoucher.toString() === tokenVoucherKey1.toString(); - }, "voucher not redeemed successfully"); - }); - - - it("mark non-redeemed voucher as expired", async () => { - let statusBefore = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey2); //[1000.0000] = hex"80" = 128 = COMMITTED - assert.equal(web3.utils.toHex(statusBefore[0]), web3.utils.numberToHex(128), "initial voucher status not as expected (COMMITTED)"); - - await timemachine.advanceTimeSeconds(helpers.SECONDS_IN_DAY*365); //fast-forward for a year - await contractVoucherKernel.triggerExpiration(tokenVoucherKey2); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey2); //[1001.0000] = hex"90" = 144 = EXPIRED - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(144), "end voucher status not as expected (EXPIRED)"); - }); - - - it("mark voucher as finalized", async () => { - let txFinalize = await contractVoucherKernel.triggerFinalizeVoucher(tokenVoucherKey1, {from: Buyer}); - - truffleAssert.eventEmitted(txFinalize, 'LogFinalizeVoucher', (ev) => { - return ev._tokenIdVoucher.toString() === tokenVoucherKey1.toString(); - }, "voucher not finalized successfully"); - }); - - - it("must fail: unauthorized redemption", async () => { - await truffleAssert.reverts(contractBosonRouter.redeem(tokenVoucherKey1, {from: Attacker}), - truffleAssert.ErrorType.REVERT - ); - }); - - }) - - - describe('Withdrawals', function() { - - it("withdraw the escrowed payment from one redeemed voucher", async () => { - let escrowedBefore = await contractCashier.getEscrowAmount.call(Buyer); - - await contractCashier.withdraw(tokenVoucherKey1); - - let escrowedAfter = await contractCashier.getEscrowAmount.call(Buyer); - - assert.isBelow(escrowedAfter.toNumber(), escrowedBefore.toNumber(), "escrowed amount not decreased"); - }); - - - // it("must fail: unauthorized withdrawal of escrowed pool", async () => { - // await truffleAssert.reverts(contractCashier.withdrawPool({from: Attacker}), - // truffleAssert.ErrorType.REVERT - // ); - // }); - - }) - - - - after(async () => { - await timemachine.revertToSnapShot(snapshot.id) - }) - +contract('Voucher tests', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractFundLimitsOracle; + let tokenSupplyKey1, tokenSupplyKey2, tokenVoucherKey1, tokenVoucherKey2; + + before('setup contracts for tests', async () => { + const sixtySeconds = 60; + + snapshot = await timemachine.takeSnapshot(); + + const timestamp = await Utils.getCurrTimestamp(); + constants.PROMISE_VALID_FROM = timestamp; + constants.PROMISE_VALID_TO = timestamp + 2 * constants.SECONDS_IN_DAY; + + contractFundLimitsOracle = await FundLimitsOracle.new(); + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + + await contractVoucherKernel.setComplainPeriod(sixtySeconds); + await contractVoucherKernel.setCancelFaultPeriod(sixtySeconds); + + console.log('Seller: ' + users.seller.address); + console.log('Buyer: ' + users.buyer.address); + console.log('Attacker: ' + users.attacker.address); + console.log(); + }); + + describe('Direct minting', function () { + it('must fail: unauthorized minting ERC-1155', async () => { + await truffleAssert.reverts( + contractERC1155ERC721.mint(users.attacker.address, 666, 1, []), + truffleAssert.ErrorType.REVERT + ); + }); + + it('must fail: unauthorized minting ERC-721', async () => { + await truffleAssert.reverts( + contractERC1155ERC721.mint(users.attacker.address, 666), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Orders (aka supply tokens - ERC1155)', () => { + it('adding one new order / promise', async () => { + const txOrder = await contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.PROMISE_DEPOSITSE1, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + { + from: users.seller.address, + to: contractCashier.address, + value: constants.PROMISE_DEPOSITSE1, + } + ); + + // // would need truffle-events as the event emitted is from a nested + // // contract, so truffle-assert doesn't detect it + // truffleAssert.eventEmitted(txOrder, 'LogOrderCreated', (ev) => { + // tokenSupplyKey = ev._tokenIdSupply; + // return ev._seller === Seller; + // }, "order1 not created successfully"); + + // // instead, we check that the escrow increased for the seller + // let escrowAmount = await contractBosonRouter.getEscrowAmount.call(Seller); + // assert.isAbove(escrowAmount.toNumber(), 0, + // "seller's escrowed deposit should be more than zero"); + + // move events from VoucherKernel to Cashier: + truffleAssert.eventEmitted( + txOrder, + 'LogOrderCreated', + (ev) => { + tokenSupplyKey1 = ev._tokenIdSupply; + return ev._seller === users.seller.address; + }, + 'order1 not created successfully' + ); + }); + + it('adding second order', async () => { + const txOrder = await contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE2, + constants.PROMISE_DEPOSITSE2, + constants.PROMISE_DEPOSITBU2, + constants.ORDER_QUANTITY2, + ], + { + from: users.seller.address, + to: contractCashier.address, + value: constants.PROMISE_DEPOSITSE2, + } + ); + + truffleAssert.eventEmitted( + txOrder, + 'LogOrderCreated', + (ev) => { + tokenSupplyKey2 = ev._tokenIdSupply; + return ev._seller === users.seller.address; + }, + 'order2 not created successfully' + ); + }); + + it('fill one order (aka buy a voucher)', async () => { + const txFillOrder = await contractBosonRouter.requestVoucherETHETH( + tokenSupplyKey1, + users.seller.address, + { + from: users.buyer.address, + to: contractBosonRouter.address, + value: constants.PROMISE_PRICE1 + constants.PROMISE_DEPOSITBU1, + } + ); + const internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + + const filtered = internalTx.logs.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + tokenVoucherKey1 = filtered.returnValues['_tokenIdVoucher']; + }); + + it('fill second order (aka buy a voucher)', async () => { + const txFillOrder = await contractBosonRouter.requestVoucherETHETH( + tokenSupplyKey2, + users.seller.address, + { + from: users.buyer.address, + to: contractBosonRouter.address, + value: constants.PROMISE_PRICE2 + constants.PROMISE_DEPOSITBU2, + } + ); + const internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey2 = ev._tokenIdVoucher; + return ev._tokenIdSupply.toString() === tokenSupplyKey2.toString(); + }, + 'order1 not filled successfully' + ); + }); + + it('must fail: adding new order with incorrect value sent', async () => { + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.PROMISE_DEPOSITSE1, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + { + from: users.seller.address, + to: contractBosonRouter.address, + value: 0, + } + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('must fail: fill an order with incorrect value', async () => { + await truffleAssert.reverts( + contractBosonRouter.requestVoucherETHETH( + tokenSupplyKey1, + users.seller.address, + { + from: users.buyer.address, + to: contractBosonRouter.address, + value: 0, + } + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Voucher tokens', function () { + it('redeeming one voucher', async () => { + const txRedeem = await contractBosonRouter.redeem(tokenVoucherKey1, { + from: users.buyer.address, + }); + const internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txRedeem.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherRedeemed', + (ev) => { + return ev._tokenIdVoucher.toString() === tokenVoucherKey1.toString(); + }, + 'voucher not redeemed successfully' + ); + }); + + it('mark non-redeemed voucher as expired', async () => { + const statusBefore = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey2 + ); + + // [1000.0000] = hex"80" = 128 = COMMITTED + assert.equal( + web3.utils.toHex(statusBefore[0]), + web3.utils.numberToHex(128), + 'initial voucher status not as expected (COMMITTED)' + ); + + // fast-forward for a year + await timemachine.advanceTimeSeconds(constants.SECONDS_IN_DAY * 365); + await contractVoucherKernel.triggerExpiration(tokenVoucherKey2); + + const statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey2 + ); + + //[1001.0000] = hex"90" = 144 = EXPIRED + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(144), + 'end voucher status not as expected (EXPIRED)' + ); + }); + + it('mark voucher as finalized', async () => { + const txFinalize = await contractVoucherKernel.triggerFinalizeVoucher( + tokenVoucherKey1, + {from: users.buyer.address} + ); + + truffleAssert.eventEmitted( + txFinalize, + 'LogFinalizeVoucher', + (ev) => { + return ev._tokenIdVoucher.toString() === tokenVoucherKey1.toString(); + }, + 'voucher not finalized successfully' + ); + }); + + it('must fail: unauthorized redemption', async () => { + await truffleAssert.reverts( + contractBosonRouter.redeem(tokenVoucherKey1, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Withdrawals', function () { + it('withdraw the escrowed payment from one redeemed voucher', async () => { + const escrowedBefore = await contractCashier.getEscrowAmount.call( + users.buyer.address + ); + + await contractCashier.withdraw(tokenVoucherKey1); + + const escrowedAfter = await contractCashier.getEscrowAmount.call( + users.buyer.address + ); + + assert.isBelow( + escrowedAfter.toNumber(), + escrowedBefore.toNumber(), + 'escrowed amount not decreased' + ); + }); + + // it("must fail: unauthorized withdrawal of escrowed pool", async () => { + // await truffleAssert.reverts( + // contractCashier.withdrawPool({from: Attacker}), + // truffleAssert.ErrorType.REVERT + // ); + // }); + }); + + after(async () => { + await timemachine.revertToSnapShot(snapshot.id); + }); }); - - -contract("Voucher tests - UNHAPPY PATH", async accounts => { - - let Seller = accounts[0]; - let Buyer = accounts[1]; - let Attacker = accounts[2]; - - let contractERC1155ERC721, contractVoucherKernel, contractCashier, contractFundLimitsOracle; - let promiseKey1, promiseKey2; - let order1payment, order1depositSe, order1depositBu; - let ordersCount; - let tokenSupplyKey1, tokenSupplyKey2, tokenVoucherKey1, tokenVoucherKey2; - - before('setup promise dates based on the block timestamp', async () => { - snapshot = await timemachine.takeSnapshot(); - - const timestamp = await Utils.getCurrTimestamp() - - helpers.PROMISE_VALID_FROM = timestamp - helpers.PROMISE_VALID_TO = timestamp + 2 * helpers.SECONDS_IN_DAY; - - contractFundLimitsOracle = await FundLimitsOracle.new() - contractERC1155ERC721 = await ERC1155ERC721.new(); - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address); - contractCashier = await Cashier.new(contractVoucherKernel.address); - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true'); - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address); - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address); - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setComplainPeriod(60); //60 seconds - await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds - }) - - beforeEach('setup contracts for tests', async () => { - - //INIT - // await contractVoucherKernel.createTokenSupplyID(helpers.ASSET_TITLE, helpers.ASSET_PIN1, helpers.ASSET_QR1, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.PROMISE_CHALLENGE_PERIOD * helpers.SECONDS_IN_DAY, helpers.PROMISE_CANCELORFAULT_PERIOD * helpers.SECONDS_IN_DAY); - - // promiseKey1 = await contractVoucherKernel.promiseKeys.call(0); - - // assert.notEqual(promiseKey1, helpers.ZERO_ADDRESS, "promise not added"); - - let txOrder = await contractBosonRouter.requestCreateOrder_ETH_ETH( [helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.PROMISE_PRICE1, helpers.PROMISE_DEPOSITSE1, helpers.PROMISE_DEPOSITBU1, helpers.ORDER_QUANTITY1], {from: Seller, to: contractBosonRouter.address, value: helpers.PROMISE_DEPOSITSE1}); - - truffleAssert.eventEmitted(txOrder, 'LogOrderCreated', (ev) => { - tokenSupplyKey1 = ev._tokenIdSupply; - return ev._seller === Seller; - }, "order1 not created successfully"); - - let txFillOrder = await contractBosonRouter.requestVoucher_ETH_ETH(tokenSupplyKey1, Seller, {from: Buyer, to: contractBosonRouter.address, value: helpers.PROMISE_PRICE1 + helpers.PROMISE_DEPOSITBU1}); - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey1 = ev._tokenIdVoucher - return ev._issuer === Seller; - }, "order1 not created successfully"); - - //\INIT - }) - - - describe('Wait periods', function() { - it("change complain period", async () => { - let txChangePeriod = await contractVoucherKernel.setComplainPeriod(helpers.PROMISE_CHALLENGE_PERIOD * helpers.SECONDS_IN_DAY); - - truffleAssert.eventEmitted(txChangePeriod, 'LogComplainPeriodChanged', (ev) => { - return ev._newComplainPeriod.toString() === (helpers.PROMISE_CHALLENGE_PERIOD * helpers.SECONDS_IN_DAY).toString(); - }, "complain period not changed successfully"); - }); - - - it("must fail: unauthorized change of complain period", async () => { - await truffleAssert.reverts(contractVoucherKernel.setComplainPeriod(helpers.PROMISE_CHALLENGE_PERIOD * helpers.SECONDS_IN_DAY, {from: Attacker}), - truffleAssert.ErrorType.REVERT - ); - }); - - - it("change cancelOrFault period", async () => { - let txChangePeriod = await contractVoucherKernel.setCancelFaultPeriod(helpers.PROMISE_CANCELORFAULT_PERIOD * helpers.SECONDS_IN_DAY); - - await truffleAssert.eventEmitted(txChangePeriod, 'LogCancelFaultPeriodChanged', (ev) => { - return ev._newCancelFaultPeriod.toString() === (helpers.PROMISE_CANCELORFAULT_PERIOD * helpers.SECONDS_IN_DAY).toString(); - }, "complain period not changed successfully"); - }); - - - it("must fail: unauthorized change of cancelOrFault period", async () => { - await truffleAssert.reverts(contractVoucherKernel.setCancelFaultPeriod(helpers.PROMISE_CANCELORFAULT_PERIOD * helpers.SECONDS_IN_DAY, {from: Attacker}), - truffleAssert.ErrorType.REVERT - ); - }); - - }) - - - describe('Refunds ...', function() { - - it("refunding one voucher", async () => { - let txRefund = await contractBosonRouter.refund(tokenVoucherKey1, {from: Buyer}); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1010.0000] = hex"A0" = 160 = REFUND - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(160), "end voucher status not as expected (REFUNDED)"); - }); - - - it("refunding one voucher, then complain", async () => { - let txRefund = await contractBosonRouter.refund(tokenVoucherKey1, {from: Buyer}); - let txComplain = await contractBosonRouter.complain(tokenVoucherKey1, {from: Buyer}); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1010.1000] = hex"A8" = 168 = REFUND_COMPLAIN - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(168), "end voucher status not as expected (REFUNDED_COMPLAINED)"); - }); - - - it("refunding one voucher, then complain, then cancel/fault", async () => { - let txRefund = await contractBosonRouter.refund(tokenVoucherKey1, {from: Buyer}); - let txComplain = await contractBosonRouter.complain(tokenVoucherKey1, {from: Buyer}); - let txCoF = await contractBosonRouter.cancelOrFault(tokenVoucherKey1, {from: Seller}); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1010.1100] = hex"AC" = 172 = REFUND_COMPLAIN_COF - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(172), "end voucher status not as expected (REFUNDED_COMPLAINED_CANCELORFAULT)"); - }); - - - it("must fail: refund then try to redeem", async () => { - let txRefund = await contractBosonRouter.refund(tokenVoucherKey1, {from: Buyer}); - - await truffleAssert.reverts(contractBosonRouter.redeem(tokenVoucherKey1, {from: Buyer}), - truffleAssert.ErrorType.REVERT - ); - }); - - }) - - - describe('Cancel/Fault by the seller ...', function() { - - it("canceling one voucher", async () => { - let txCoF = await contractBosonRouter.cancelOrFault(tokenVoucherKey1, {from: Seller}); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1000.0100] = hex"84" = 132 = CANCELORFAULT - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(132), "end voucher status not as expected (CANCELORFAULT)"); - }); - - - it("must fail: cancel/fault then try to redeem", async () => { - let txCoF = await contractBosonRouter.cancelOrFault(tokenVoucherKey1, {from: Seller}); - - await truffleAssert.reverts(contractBosonRouter.redeem(tokenVoucherKey1, {from: Buyer}), - truffleAssert.ErrorType.REVERT - ); - }); - - }) - - - describe('Expirations (one universal test) ...', function() { - - it("Expired, then complain, then Cancel/Fault, then try to redeem", async () => { - await timemachine.advanceTimeSeconds(helpers.SECONDS_IN_DAY*3); //fast-forward for three days - await contractVoucherKernel.triggerExpiration(tokenVoucherKey1); - - let statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1001.0000] = hex"90" = 144 = EXPIRED - let txComplain = await contractBosonRouter.complain(tokenVoucherKey1, {from: Buyer}); - - statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1001.1000] = hex"98" = 152 = EXPIRED_COMPLAIN - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(152), "end voucher status not as expected (EXPIRED_COMPLAINED)"); - - //in the same test, because the EVM time machine is funky ... - let txCoF = await contractBosonRouter.cancelOrFault(tokenVoucherKey1, {from: Seller}); - statusAfter = await contractVoucherKernel.getVoucherStatus.call(tokenVoucherKey1); //[1001.1000] = hex"9C" = 156 = EXPIRED_COMPLAINED_CANCELORFAULT - assert.equal(web3.utils.toHex(statusAfter[0]), web3.utils.numberToHex(156), "end voucher status not as expected (EXPIRED_COMPLAINED_CANCELORFAULT)"); - - //in the same test, because the EVM time machine is funky ... - await truffleAssert.reverts(contractBosonRouter.redeem(tokenVoucherKey1, {from: Buyer}), - truffleAssert.ErrorType.REVERT - ); - }); - - after(async () => { - await timemachine.revertToSnapShot(snapshot.id) - }) - - }) - -}); \ No newline at end of file +contract('Voucher tests - UNHAPPY PATH', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractFundLimitsOracle; + let tokenSupplyKey1, tokenVoucherKey1; + + before('setup promise dates based on the block timestamp', async () => { + const sixtySeconds = 60; + + snapshot = await timemachine.takeSnapshot(); + + const timestamp = await Utils.getCurrTimestamp(); + + constants.PROMISE_VALID_FROM = timestamp; + constants.PROMISE_VALID_TO = timestamp + 2 * constants.SECONDS_IN_DAY; + + contractFundLimitsOracle = await FundLimitsOracle.new(); + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + + await contractVoucherKernel.setComplainPeriod(sixtySeconds); + await contractVoucherKernel.setCancelFaultPeriod(sixtySeconds); + }); + + beforeEach('setup contracts for tests', async () => { + const txOrder = await contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.PROMISE_DEPOSITSE1, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + { + from: users.seller.address, + to: contractBosonRouter.address, + value: constants.PROMISE_DEPOSITSE1, + } + ); + + truffleAssert.eventEmitted( + txOrder, + 'LogOrderCreated', + (ev) => { + tokenSupplyKey1 = ev._tokenIdSupply; + return ev._seller === users.seller.address; + }, + 'order1 not created successfully' + ); + + const txFillOrder = await contractBosonRouter.requestVoucherETHETH( + tokenSupplyKey1, + users.seller.address, + { + from: users.buyer.address, + to: contractBosonRouter.address, + value: constants.PROMISE_PRICE1 + constants.PROMISE_DEPOSITBU1, + } + ); + const internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey1 = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + }); + + describe('Wait periods', () => { + it('change complain period', async () => { + const complainPeriodSeconds = + constants.PROMISE_CHALLENGE_PERIOD * constants.SECONDS_IN_DAY; + + const txChangePeriod = await contractVoucherKernel.setComplainPeriod( + complainPeriodSeconds + ); + + truffleAssert.eventEmitted( + txChangePeriod, + 'LogComplainPeriodChanged', + (ev) => { + return ( + ev._newComplainPeriod.toString() === + complainPeriodSeconds.toString() + ); + }, + 'complain period not changed successfully' + ); + }); + + it('must fail: unauthorized change of complain period', async () => { + const complainPeriodSeconds = + constants.PROMISE_CHALLENGE_PERIOD * constants.SECONDS_IN_DAY; + + await truffleAssert.reverts( + contractVoucherKernel.setComplainPeriod(complainPeriodSeconds, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('change cancelOrFault period', async () => { + const cancelFaultPeriodSeconds = + constants.PROMISE_CANCELORFAULT_PERIOD * constants.SECONDS_IN_DAY; + const txChangePeriod = await contractVoucherKernel.setCancelFaultPeriod( + cancelFaultPeriodSeconds + ); + + await truffleAssert.eventEmitted( + txChangePeriod, + 'LogCancelFaultPeriodChanged', + (ev) => { + return ( + ev._newCancelFaultPeriod.toString() === + cancelFaultPeriodSeconds.toString() + ); + }, + 'complain period not changed successfully' + ); + }); + + it('must fail: unauthorized change of cancelOrFault period', async () => { + const cancelFaultPeriodSeconds = + constants.PROMISE_CANCELORFAULT_PERIOD * constants.SECONDS_IN_DAY; + await truffleAssert.reverts( + contractVoucherKernel.setCancelFaultPeriod(cancelFaultPeriodSeconds, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Refunds ...', function () { + it('refunding one voucher', async () => { + await contractBosonRouter.refund(tokenVoucherKey1, { + from: users.buyer.address, + }); + + const statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1010.0000] = hex"A0" = 160 = REFUND + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(160), + 'end voucher status not as expected (REFUNDED)' + ); + }); + + it('refunding one voucher, then complain', async () => { + await contractBosonRouter.refund(tokenVoucherKey1, { + from: users.buyer.address, + }); + await contractBosonRouter.complain(tokenVoucherKey1, { + from: users.buyer.address, + }); + + const statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1010.1000] = hex"A8" = 168 = REFUND_COMPLAIN + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(168), + 'end voucher status not as expected (REFUNDED_COMPLAINED)' + ); + }); + + it('refunding one voucher, then complain, then cancel/fault', async () => { + await contractBosonRouter.refund(tokenVoucherKey1, { + from: users.buyer.address, + }); + await contractBosonRouter.complain(tokenVoucherKey1, { + from: users.buyer.address, + }); + await contractBosonRouter.cancelOrFault(tokenVoucherKey1, { + from: users.seller.address, + }); + + const statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1010.1100] = hex"AC" = 172 = REFUND_COMPLAIN_COF + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(172), + 'end voucher status not as expected ' + + '(REFUNDED_COMPLAINED_CANCELORFAULT)' + ); + }); + + it('must fail: refund then try to redeem', async () => { + await contractBosonRouter.refund(tokenVoucherKey1, { + from: users.buyer.address, + }); + + await truffleAssert.reverts( + contractBosonRouter.redeem(tokenVoucherKey1, { + from: users.buyer.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Cancel/Fault by the seller ...', () => { + it('canceling one voucher', async () => { + await contractBosonRouter.cancelOrFault(tokenVoucherKey1, { + from: users.seller.address, + }); + + const statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1000.0100] = hex"84" = 132 = CANCELORFAULT + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(132), + 'end voucher status not as expected (CANCELORFAULT)' + ); + }); + + it('must fail: cancel/fault then try to redeem', async () => { + await contractBosonRouter.cancelOrFault(tokenVoucherKey1, { + from: users.seller.address, + }); + + await truffleAssert.reverts( + contractBosonRouter.redeem(tokenVoucherKey1, { + from: users.buyer.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Expirations (one universal test) ...', () => { + it('Expired, then complain, then Cancel/Fault, then try to redeem', async () => { + // fast-forward for three days + const secondsInThreeDays = constants.SECONDS_IN_DAY * 3; + await timemachine.advanceTimeSeconds(secondsInThreeDays); + + await contractVoucherKernel.triggerExpiration(tokenVoucherKey1); + + let statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1001.0000] = hex"90" = 144 = EXPIRED + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(144), + 'end voucher status not as expected (EXPIRED)' + ); + + await contractBosonRouter.complain(tokenVoucherKey1, { + from: users.buyer.address, + }); + + statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1001.1000] = hex"98" = 152 = EXPIRED_COMPLAIN + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(152), + 'end voucher status not as expected (EXPIRED_COMPLAINED)' + ); + + // in the same test, because the EVM time machine is funky ... + await contractBosonRouter.cancelOrFault(tokenVoucherKey1, { + from: users.seller.address, + }); + + statusAfter = await contractVoucherKernel.getVoucherStatus.call( + tokenVoucherKey1 + ); + + // [1001.1000] = hex"9C" = 156 = EXPIRED_COMPLAINED_CANCELORFAULT + assert.equal( + web3.utils.toHex(statusAfter[0]), + web3.utils.numberToHex(156), + 'end voucher status not as expected ' + + '(EXPIRED_COMPLAINED_CANCELORFAULT)' + ); + + // in the same test, because the EVM time machine is funky ... + await truffleAssert.reverts( + contractBosonRouter.redeem(tokenVoucherKey1, { + from: users.buyer.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + after(async () => { + await timemachine.revertToSnapShot(snapshot.id); + }); + }); +}); diff --git a/test/2_test_fullpath_with_permit.js b/test/2_test_fullpath_with_permit.js index 4cda623b..44e21a2f 100644 --- a/test/2_test_fullpath_with_permit.js +++ b/test/2_test_fullpath_with_permit.js @@ -1,2901 +1,4283 @@ -const helpers = require("../testHelpers/constants"); -const timemachine = require('../testHelpers/timemachine'); +const {assert} = require('chai'); +const {ecsign} = require('ethereumjs-util'); const truffleAssert = require('truffle-assertions'); -//later consider using https://github.com/OpenZeppelin/openzeppelin-test-helpers +// later consider using +// https://github.com/OpenZeppelin/openzeppelin-test-helpers -const ERC1155ERC721 = artifacts.require("ERC1155ERC721"); -const VoucherKernel = artifacts.require("VoucherKernel"); -const Cashier = artifacts.require("Cashier"); -const BosonRouter = artifacts.require("BosonRouter") -const BosonToken = artifacts.require("BosonTokenPrice"); -const FundLimitsOracle = artifacts.require('FundLimitsOracle'); - -const BN = web3.utils.BN - -const UtilsBuilder = require('../testHelpers/utilsBuilder'); +const constants = require('../testHelpers/constants'); +const timemachine = require('../testHelpers/timemachine'); const Utils = require('../testHelpers/utils'); -let utils; -const config = require('../testHelpers/config.json') - - -const { ecsign } = require('ethereumjs-util'); -const { - PERMIT_TYPEHASH, - toWei, - getApprovalDigest -} = require('../testHelpers/permitUtils'); -const { assert } = require("chai"); - -contract("Cashier && VK", async accounts => { - let Deployer = config.accounts.deployer - let Seller = config.accounts.seller - let Buyer = config.accounts.buyer - let Attacker = config.accounts.attacker - - let contractERC1155ERC721, - contractVoucherKernel, - contractCashier, - contractBosonRouter, - contractBSNTokenPrice, - contractBSNTokenDeposit, - contractFundLimitsOracle; - let tokenSupplyKey, tokenVoucherKey; - const ONE_VOUCHER = 1 - const deadline = toWei(1) - let timestamp - let ZERO = new BN(0); - - let distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - async function deployContracts() { - const timestamp = await Utils.getCurrTimestamp() - helpers.PROMISE_VALID_FROM = timestamp - helpers.PROMISE_VALID_TO = timestamp + 2 * helpers.SECONDS_IN_DAY; - - contractFundLimitsOracle = await FundLimitsOracle.new() - contractERC1155ERC721 = await ERC1155ERC721.new(); - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address); - contractCashier = await Cashier.new(contractVoucherKernel.address); - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - - contractBSNTokenPrice = await BosonToken.new("BosonTokenPrice", "BPRC"); - contractBSNTokenDeposit = await BosonToken.new("BosonTokenDeposit", "BDEP"); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true'); - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address); - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address); - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setComplainPeriod(60); //60 seconds - await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds - - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenDeposit.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setETHLimit(helpers.ETHER_LIMIT) - } - - describe('TOKEN SUPPLY CREATION (Voucher batch creation)', () => { - - let remQty = helpers.QTY_10 - let vouchersToBuy = 5 - - const paymentMethods = { - ETH_ETH: 1, - ETH_TKN: 2, - TKN_ETH: 3, - TKN_TKN: 4 - } - - afterEach(() => { - remQty = helpers.QTY_10 - }) - - describe("ETH_ETH", () => { - - before(async() => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter); - - timestamp = await Utils.getCurrTimestamp() - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10) - }) - - it("ESCROW has correct initial balance", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const escrowAmount = await contractCashier.getEscrowAmount(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Cashier Contract has correct amount of ETH", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const cashierBalance = await web3.eth.getBalance(contractCashier.address) - - assert.isTrue((new BN(cashierBalance)).eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Get correct remaining qty for supply", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, remQty, "Remaining qty is not correct") - - for (let i = 0; i < vouchersToBuy; i++) { - await utils.commitToBuy(Buyer, Seller, tokenSupplyKey) - remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, --remQty , "Remaining qty is not correct") - } - - }); - - it("Should create payment method ETH_ETH", async () => { - timestamp = await Utils.getCurrTimestamp() - let tokenSupplyKey = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10); - - const paymentDetails = await contractVoucherKernel.paymentDetails(tokenSupplyKey); - - assert.equal(paymentDetails.paymentMethod.toString(), paymentMethods.ETH_ETH, "Payment Method ETH_ETH not set correctly") - assert.equal(paymentDetails.addressTokenPrice.toString(), helpers.ZERO_ADDRESS, "ETH_ETH Method Price Token Address mismatch") - assert.equal(paymentDetails.addressTokenDeposits.toString(), helpers.ZERO_ADDRESS, "ETH_ETH Method Deposit Token Address mismatch") - }) - - it("[NEGATIVE] Should fail if additional token address is provided", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - timestamp = await Utils.getCurrTimestamp() - - await truffleAssert.fails( - contractBosonRouter.requestCreateOrder_ETH_ETH( - contractBSNTokenDeposit.address, - [ - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue} - ) - ); - - }) - - it("[NEGATIVE] Should not create a supply if price is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_ETH( - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.ABOVE_ETH_LIMIT, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositBu is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_ETH( - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.ABOVE_ETH_LIMIT, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositSe is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_ETH( - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.ABOVE_ETH_LIMIT, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - - before(async() => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_20)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - timestamp = await Utils.getCurrTimestamp() - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - - }) - - it("ESCROW has correct initial balance", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - const escrowAmount = await contractBSNTokenDeposit.balanceOf(contractCashier.address) - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Get correct remaining qty for supply", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - assert.equal(remainingQtyInContract, remQty, "Remaining qty is not correct") - - for (let i = 0; i < vouchersToBuy; i++) { - await utils.commitToBuy(Buyer, Seller, tokenSupplyKey) - remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, --remQty , "Remaining qty is not correct") - } - }); - - it("Should create payment method ETH_TKN", async () => { - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10, - ); - - const paymentDetails = await contractVoucherKernel.paymentDetails(tokenSupplyKey); - - assert.equal(paymentDetails.paymentMethod.toString(), paymentMethods.ETH_TKN, "Payment Method ETH_TKN not set correctly") - assert.equal(paymentDetails.addressTokenPrice.toString(), helpers.ZERO_ADDRESS, "ETH_TKN Method Price Token Address mismatch") - assert.equal(paymentDetails.addressTokenDeposits.toString(), contractBSNTokenDeposit.address, "ETH_TKN Method Deposit Token Address mismatch") - }) - - it("[NEGATIVE] Should fail if token deposit contract address is not provided", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - await truffleAssert.fails( - contractBosonRouter.requestCreateOrder_ETH_TKN_WithPermit( - '', - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ) - ) - }) - - it("[NEGATIVE] Should revert if token deposit contract address is zero address", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_TKN_WithPermit( - helpers.ZERO_ADDRESS, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Should not create a supply if price is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - const deadline = toWei(1) - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_TKN_WithPermit( - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.ABOVE_ETH_LIMIT, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositBu is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - const deadline = toWei(1) - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_TKN_WithPermit( - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.ABOVE_TOKEN_LIMIT, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositSe is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - const deadline = toWei(1) - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_ETH_TKN_WithPermit( - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.ABOVE_TOKEN_LIMIT, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_ETH", () => { - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - timestamp = await Utils.getCurrTimestamp() - - const tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("ESCROW has correct initial balance", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const escrowAmount = await contractCashier.getEscrowAmount(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Cashier Contract has correct amount of ETH", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const cashierBalance = await web3.eth.getBalance(contractCashier.address) - - assert.isTrue((new BN(cashierBalance)).eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Get correct remaining qty for supply", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, remQty, "Remaining qty is not correct") - - for (let i = 0; i < vouchersToBuy; i++) { - await utils.commitToBuy(Buyer, Seller, tokenSupplyKey) - remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, --remQty , "Remaining qty is not correct") - } - }); - - it("Should create payment method TKN_ETH", async () => { - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - - const paymentDetails = await contractVoucherKernel.paymentDetails(tokenSupplyKey); - - assert.equal(paymentDetails.paymentMethod.toString(), paymentMethods.TKN_ETH, "Payment Method TKN_ETH not set correctly") - assert.equal(paymentDetails.addressTokenPrice.toString(), contractBSNTokenPrice.address, "TKN_ETH Method Price Token Address mismatch") - assert.equal(paymentDetails.addressTokenDeposits.toString(), helpers.ZERO_ADDRESS, "TKN_ETH Method Deposit Token Address mismatch") - }) - - it("[NEGATIVE] Should fail if price token contract address is not provided", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.fails( - contractBosonRouter.requestCreateOrder_TKN_ETH( - '', - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue.toString() } - ) - ); - - }) - - it("[NEGATIVE] Should fail if token price contract is zero address", async () => { - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_ETH( - helpers.ZERO_ADDRESS, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ); - - }) - - it("[NEGATIVE] Should not create a supply if price is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_ETH( - contractBSNTokenPrice.address, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.ABOVE_TOKEN_LIMIT, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue.toString() } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositBu is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_ETH( - contractBSNTokenPrice.address, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.ABOVE_ETH_LIMIT, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue.toString() } - ), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Should not create a supply if depositSe is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_ETH( - contractBSNTokenPrice.address, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.ABOVE_ETH_LIMIT, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address, value: txValue.toString() } - ), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_TKN", () => { - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - timestamp = await Utils.getCurrTimestamp() - - const tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_20)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("ESCROW has correct initial balance", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const escrowAmount = await contractBSNTokenDeposit.balanceOf(contractCashier.address) - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("Get correct remaining qty for supply", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, remQty, "Remaining qty is not correct") - - for (let i = 0; i < vouchersToBuy; i++) { - await utils.commitToBuy(Buyer, Seller, tokenSupplyKey) - remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(tokenSupplyKey, Seller.address) - - assert.equal(remainingQtyInContract, --remQty , "Remaining qty is not correct") - } - }); - - it("Should create payment method TKN_TKN", async () => { - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - - const paymentDetails = await contractVoucherKernel.paymentDetails(tokenSupplyKey); - - assert.equal(paymentDetails.paymentMethod.toString(), paymentMethods.TKN_TKN, "Payment Method TKN_TKN not set correctly") - assert.equal(paymentDetails.addressTokenPrice.toString(), contractBSNTokenPrice.address, "TKN_TKN Method Price Token Address mismatch") - assert.equal(paymentDetails.addressTokenDeposits.toString(), contractBSNTokenDeposit.address, "TKN_TKN Method Deposit Token Address mismatch") - }) - - it("[NEGATIVE] Should fail if token price contract address is not provided", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.fails( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - '', - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ) - ); - - }) - - it("[NEGATIVE] Should fail if token deposit contract address is not provided", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.fails( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - contractBSNTokenPrice.address, - '', - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ) - ); - - }) - - it("[NEGATIVE] Should revert if token price contract address is zero address", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - helpers.ZERO_ADDRESS, - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ); - - }) - - it("[NEGATIVE] Should revert if token deposit contract address is zero address", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(ONE_VOUCHER)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - const deadline = toWei(1) - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - contractBSNTokenPrice.address, - helpers.ZERO_ADDRESS, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ); - - }) - - it("[NEGATIVE] Should not create a supply if price is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - contractBSNTokenPrice.address, - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.ABOVE_TOKEN_LIMIT, - helpers.seller_deposit, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositBu is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - contractBSNTokenPrice.address, - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.seller_deposit, - helpers.ABOVE_TOKEN_LIMIT, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create a supply if depositSe is above the limit", async () => { - const txValue = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - const nonce = await contractBSNTokenDeposit.nonces(Seller.address); - - const digest = await getApprovalDigest( - contractBSNTokenDeposit, - Seller.address, - contractCashier.address, - txValue, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Seller.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestCreateOrder_TKN_TKN_WithPermit( - contractBSNTokenPrice.address, - contractBSNTokenDeposit.address, - txValue, - deadline, - v, r, s, - [ - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.PROMISE_PRICE1, - helpers.ABOVE_TOKEN_LIMIT, - helpers.PROMISE_DEPOSITBU1, - helpers.ORDER_QUANTITY1 - ], - { from: Seller.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - }) - }) - - describe("VOUCHER CREATION (Commit to buy)", () => { - const ORDER_QTY = 5 - let TOKEN_SUPPLY_ID; - - describe("ETH_ETH", async () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.seller_deposit, helpers.QTY_10) - }) - - it("Should create order", async () => { - const txValue = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)) - let txFillOrder = await contractBosonRouter.requestVoucher_ETH_ETH( - TOKEN_SUPPLY_ID, - Seller.address, - { - from: Buyer.address, value: txValue - }); - - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey = ev._tokenIdVoucher - return ev._issuer === Seller.address; - }, "order1 not created successfully"); - }) - - it("Cashier Contract has correct amount of funds", async () => { - const sellerDeposits = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - const buyerETHSent = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - const expectedBalance = sellerDeposits.add(buyerETHSent) - - const cashierBalance = await web3.eth.getBalance(contractCashier.address) - - assert.isTrue((new BN(cashierBalance)).eq(expectedBalance), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Should not create order with incorrect price", async () => { - const txValue = new BN(helpers.buyer_deposit).add(new BN(helpers.incorrect_product_price)) - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_ETH_ETH( - TOKEN_SUPPLY_ID, - Seller.address, - { from: Buyer.address, value: txValue}), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Should not create order with incorrect deposit", async () => { - const txValue = new BN(helpers.buyer_incorrect_deposit).add(new BN(helpers.product_price)) - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_ETH_ETH( - TOKEN_SUPPLY_ID, - Seller.address, - { from: Buyer.address, value: txValue }), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", async () => { - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - - const tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const tokensToMintBuyer = new BN(helpers.buyer_deposit).mul(new BN(ORDER_QTY)) - - await contractBSNTokenDeposit.mint(Seller.address, tokensToMintSeller) - await contractBSNTokenDeposit.mint(Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.seller_deposit, - ORDER_QTY - ) - - }) - - it("Should create order", async () => { - const nonce = await contractBSNTokenDeposit.nonces(Buyer.address); - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractBosonRouter.address, - helpers.buyer_deposit, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - const txFillOrder = await contractBosonRouter.requestVoucher_ETH_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.buyer_deposit, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.product_price} - ) - - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey = ev._tokenIdVoucher - return ev._issuer === Seller.address; - }, "order1 not created successfully"); - }) - - it("Cashier Contract has correct amount of funds", async () => { - const expectedETHBalance = new BN(helpers.product_price) - const cashierETHBalance = await web3.eth.getBalance(contractCashier.address) - - const cashierDepositTokenBalance = await contractBSNTokenDeposit.balanceOf(contractCashier.address) - const sellerTokenDeposits = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const expectedTokenBalance = new BN(helpers.buyer_deposit).add(sellerTokenDeposits) - - assert.isTrue((new BN(cashierETHBalance)).eq(expectedETHBalance), "Escrow amount is incorrect") - assert.isTrue(expectedTokenBalance.eq(cashierDepositTokenBalance), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Should not create order with incorrect price", async () => { - const nonce = await contractBSNTokenDeposit.nonces(Buyer.address); - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractCashier.address, - helpers.buyer_deposit, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_ETH_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.buyer_deposit, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.incorrect_product_price } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create order with incorrect deposit", async () => { - const nonce = await contractBSNTokenDeposit.nonces(Buyer.address); - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractCashier.address, - helpers.buyer_deposit, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_ETH_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.buyer_incorrect_deposit, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.product_price } - ), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_TKN", () => { - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - - const tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(ORDER_QTY)) - - await contractBSNTokenDeposit.mint(Seller.address, tokensToMintSeller) - await contractBSNTokenDeposit.mint(Buyer.address, tokensToMintBuyer) - await contractBSNTokenPrice.mint(Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.seller_deposit, - ORDER_QTY - ) - - }) - - it("Should create order", async () => { - const nonce1 = await contractBSNTokenDeposit.nonces(Buyer.address); - const tokensToSend = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractBosonRouter.address, - helpers.buyer_deposit, - nonce1, - deadline - ) - - let VRS_DEPOSIT = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vDeposit = VRS_DEPOSIT.v - let rDeposit = VRS_DEPOSIT.r - let sDeposit = VRS_DEPOSIT.s - - const nonce2 = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestPrice = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractBosonRouter.address, - helpers.product_price, - nonce2, - deadline - ) - - let VRS_PRICE = ecsign( - Buffer.from(digestPrice.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vPrice = VRS_PRICE.v - let rPrice = VRS_PRICE.r - let sPrice = VRS_PRICE.s - - let txFillOrder = await contractBosonRouter.requestVoucher_TKN_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - tokensToSend, - deadline, - vPrice, rPrice, sPrice, - vDeposit, rDeposit, sDeposit, - { from: Buyer.address }); - - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey = ev._tokenIdVoucher - return ev._issuer === Seller.address; - }, "order1 not created successfully"); - }) - - it("Cashier Contract has correct amount of funds", async () => { - const cashierPriceTokenBalance = await contractBSNTokenPrice.balanceOf(contractCashier.address) - const cashierDepositTokenBalance = await contractBSNTokenDeposit.balanceOf(contractCashier.address) - const sellerDeposit = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const expectedDepositBalance = new BN(helpers.buyer_deposit).add(sellerDeposit) - - assert.isTrue((new BN(cashierPriceTokenBalance)).eq(new BN(helpers.product_price)), "Escrow amount is incorrect") - assert.isTrue((new BN(cashierDepositTokenBalance)).eq(expectedDepositBalance), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Should not create order with incorrect price", async () => { - const nonce1 = await contractBSNTokenDeposit.nonces(Buyer.address); - const tokensToSend = new BN(helpers.incorrect_product_price).add(new BN(helpers.buyer_deposit)) - - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractCashier.address, - helpers.buyer_deposit, - nonce1, - deadline - ) - - let VRS_DEPOSIT = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vDeposit = VRS_DEPOSIT.v - let rDeposit = VRS_DEPOSIT.r - let sDeposit = VRS_DEPOSIT.s - - const nonce2 = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestPrice = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractCashier.address, - helpers.product_price, - nonce2, - deadline - ) - - let VRS_PRICE = ecsign( - Buffer.from(digestPrice.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vPrice = VRS_PRICE.v - let rPrice = VRS_PRICE.r - let sPrice = VRS_PRICE.s - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - tokensToSend, - deadline, - vPrice, rPrice, sPrice, - vDeposit, rDeposit, sDeposit, - { from: Buyer.address }), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create order with incorrect deposit", async () => { - const nonce1 = await contractBSNTokenDeposit.nonces(Buyer.address); - const tokensToSend = new BN(helpers.product_price).add(new BN(helpers.buyer_incorrect_deposit)) - - const digestDeposit = await getApprovalDigest( - contractBSNTokenDeposit, - Buyer.address, - contractCashier.address, - helpers.buyer_deposit, - nonce1, - deadline - ) - - let VRS_DEPOSIT = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vDeposit = VRS_DEPOSIT.v - let rDeposit = VRS_DEPOSIT.r - let sDeposit = VRS_DEPOSIT.s - - const nonce2 = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestPrice = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractCashier.address, - helpers.product_price, - nonce2, - deadline - ) - - let VRS_PRICE = ecsign( - Buffer.from(digestPrice.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let vPrice = VRS_PRICE.v - let rPrice = VRS_PRICE.r - let sPrice = VRS_PRICE.s - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_TKN_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - tokensToSend, - deadline, - vPrice, rPrice, sPrice, - vDeposit, rDeposit, sDeposit, - { from: Buyer.address }), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_TKN_SAME", () => { - - const tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(ORDER_QTY)) - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN_SAME() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - await utils.contractBSNTokenSAME.mint(Seller.address, tokensToMintSeller) - await utils.contractBSNTokenSAME.mint(Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.seller_deposit, - ORDER_QTY - ) - - }) - - it("Should create voucher", async () => { - - const nonce = await utils.contractBSNTokenSAME.nonces(Buyer.address); - const tokensToSend = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - - const digestTokens = await getApprovalDigest( - utils.contractBSNTokenSAME, - Buyer.address, - contractBosonRouter.address, - tokensToSend, - nonce, - deadline - ) - - let VRS_TOKENS = ecsign( - Buffer.from(digestTokens.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let v = VRS_TOKENS.v - let r = VRS_TOKENS.r - let s = VRS_TOKENS.s - - let txFillOrder = await contractBosonRouter.requestVoucher_TKN_TKN_Same_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - tokensToSend, - deadline, - v, r, s, - { from: Buyer.address }); - - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey1 = ev._tokenIdVoucher - return ev._issuer === Seller.address; - }, "order1 not created successfully"); - }) - - it("Cashier Contract has correct amount of funds", async () => { - const cashierTokenBalanceSame = await utils.contractBSNTokenSAME.balanceOf(contractCashier.address) - const sellerDeposits = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const buyerTokensSent = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - const expectedDepositBalance = buyerTokensSent.add(sellerDeposits) - - assert.isTrue((new BN(cashierTokenBalanceSame)).eq(expectedDepositBalance), "Cashier amount is incorrect") - }) - - it("[NEGATIVE] Should not create order with incorrect price", async () => { - - const nonce = await contractBSNTokenDeposit.nonces(Buyer.address); - const incorrectTokensToSign = new BN(helpers.incorrect_product_price).add(new BN(helpers.buyer_deposit)) - const digestTokens = await getApprovalDigest( - utils.contractBSNTokenSAME, - Buyer.address, - contractCashier.address, - incorrectTokensToSign, - nonce, - deadline - ) - - let VRS_TOKENS = ecsign( - Buffer.from(digestTokens.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let v = VRS_TOKENS.v - let r = VRS_TOKENS.r - let s = VRS_TOKENS.s - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_TKN_Same_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - incorrectTokensToSign, - deadline, - v, r, s, - { from: Buyer.address }), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create order with incorrect deposit", async () => { - - const nonce = await contractBSNTokenDeposit.nonces(Buyer.address); - const incorrectTokensToSign = new BN(helpers.product_price).add(new BN(helpers.buyer_incorrect_deposit)) - const digestTokens = await getApprovalDigest( - utils.contractBSNTokenSAME, - Buyer.address, - contractCashier.address, - incorrectTokensToSign, - nonce, - deadline - ) - - let VRS_TOKENS = ecsign( - Buffer.from(digestTokens.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let v = VRS_TOKENS.v - let r = VRS_TOKENS.r - let s = VRS_TOKENS.s - - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_TKN_Same_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - incorrectTokensToSign, - deadline, - v, r, s, - { from: Buyer.address }), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should revert if Price Token and Deposit Token are diff contracts", async () => { - - //get instance with different Price token and Deposit Token addresses - let utilsTKN_TKN = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - await contractBSNTokenDeposit.mint(Seller.address, tokensToMintSeller) - await contractBSNTokenDeposit.mint(Buyer.address, tokensToMintBuyer) - await contractBSNTokenPrice.mint(Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utilsTKN_TKN.createOrder( - Seller, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.seller_deposit, - ORDER_QTY - ) - - const nonce = await utils.contractBSNTokenSAME.nonces(Buyer.address); - const tokensToSend = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - - const digestTokens = await getApprovalDigest( - utils.contractBSNTokenSAME, - Buyer.address, - contractBosonRouter.address, - tokensToSend, - nonce, - deadline - ) - - let VRS_TOKENS = ecsign( - Buffer.from(digestTokens.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let v = VRS_TOKENS.v - let r = VRS_TOKENS.r - let s = VRS_TOKENS.s - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_TKN_Same_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - tokensToSend, - deadline, - v, r, s, - { from: Buyer.address } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_ETH", () => { - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(ORDER_QTY)) - - await contractBSNTokenPrice.mint(Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.seller_deposit, - ORDER_QTY - ) - - }) - - it("Should create order", async () => { - const nonce = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestDeposit = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractBosonRouter.address, - helpers.product_price, - nonce, - deadline - ) - - let { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - let txFillOrder = await contractBosonRouter.requestVoucher_TKN_ETH_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.product_price, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.buyer_deposit } - ); - - let internalTx = (await truffleAssert.createTransactionResult(contractVoucherKernel, txFillOrder.tx)) - - truffleAssert.eventEmitted(internalTx, 'LogVoucherDelivered', (ev) => { - tokenVoucherKey = ev._tokenIdVoucher - return ev._issuer === Seller.address; - }, "order1 not created successfully"); - }) - - it("Cashier Contract has correct amount of funds", async () => { - const cashierDepositETH = await web3.eth.getBalance(contractCashier.address) - const sellerDeposits = new BN(helpers.seller_deposit).mul(new BN(ORDER_QTY)) - const expectedDepositBalance = new BN(helpers.buyer_deposit).add(sellerDeposits) - - const cashierPriceTokenBalance = await contractBSNTokenPrice.balanceOf(contractCashier.address) - - assert.isTrue((new BN(cashierDepositETH)).eq(expectedDepositBalance), "Cashier amount is incorrect") - assert.isTrue((new BN(cashierPriceTokenBalance)).eq(new BN(helpers.product_price)), "Cashier amount is incorrect") - }) - - it("[NEGATIVE] Should not create order with incorrect deposit", async () => { - const nonce = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestDeposit = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractCashier.address, - helpers.product_price, - nonce, - deadline - ) - - let { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_ETH_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.product_price, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.buyer_incorrect_deposit } - ), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not create order with incorrect price", async () => { - const nonce = await contractBSNTokenPrice.nonces(Buyer.address); - - const digestDeposit = await getApprovalDigest( - contractBSNTokenPrice, - Buyer.address, - contractCashier.address, - helpers.product_price, - nonce, - deadline - ) - - let { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await truffleAssert.reverts( - contractBosonRouter.requestVoucher_TKN_ETH_WithPermit( - TOKEN_SUPPLY_ID, - Seller.address, - helpers.incorrect_product_price, - deadline, - v, r, s, - { from: Buyer.address, value: helpers.buyer_deposit } - ), - truffleAssert.ErrorType.REVERT - ) - }) - }) - }) - }) - - describe("TOKEN SUPPLY TRANSFER", () => { - let OldSupplyOwner = config.accounts.randomUser - let NewSupplyOwner = config.accounts.randomUser2 - - let actualOldOwnerBalanceFromEscrow = new BN(0); - let actualNewOwnerBalanceFromEscrow = new BN(0); - let expectedBalanceInEscrow = new BN(0); - - afterEach(()=> { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - }) - - describe("Common transfer", () => { - - beforeEach(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - const timestamp = await Utils.getCurrTimestamp() - - tokenSupplyKey = await utils.createOrder(OldSupplyOwner, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - it("Should transfer voucher supply", async () => { - - let transferTx = await utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_10, {from: OldSupplyOwner.address}); - - truffleAssert.eventEmitted(transferTx, 'TransferSingle', (ev) => { - assert.equal(ev._from, OldSupplyOwner.address) - assert.equal(ev._to, NewSupplyOwner.address) - assert.equal(ev._id.toString(), tokenSupplyKey) - assert.equal(ev._value.toString(), helpers.QTY_10) - - return true - }, "TransferSingle not emitted") - - }) - - it("[NEGATIVE] Should revert if owner tries to transfer voucher supply partially", async () => { - - await truffleAssert.reverts( - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Should revert if Attacker tries to transfer voucher supply", async () => { - - await truffleAssert.reverts( - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_10, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("Should transfer batch voucher supply", async () => { - - let transferTx = await utils.safeBatchTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, [tokenSupplyKey], [helpers.QTY_10], {from: OldSupplyOwner.address}); - - truffleAssert.eventEmitted(transferTx, 'TransferBatch', (ev) => { - - assert.equal(ev._from, OldSupplyOwner.address) - assert.equal(ev._to, NewSupplyOwner.address) - assert.equal(JSON.stringify(ev._ids), JSON.stringify([new BN(tokenSupplyKey)])) - assert.equal(JSON.stringify(ev._values), JSON.stringify([new BN(helpers.QTY_10)])) - - return true - }, "TransferSingle not emitted") - - }) - - it("[NEGATIVE] Should revert if owner tries to transfer voucher supply batch partially", async () => { - - await truffleAssert.reverts( - utils.safeBatchTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, [tokenSupplyKey], [helpers.QTY_1], {from: OldSupplyOwner.address}), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Should revert if Attacker tries to transfer batch voucher supply", async () => { - - await truffleAssert.reverts( - utils.safeBatchTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, [tokenSupplyKey], [helpers.QTY_10], {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - - }) - - }) - - describe("ETH_ETH", () => { - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - tokenSupplyKey = await utils.createOrder(OldSupplyOwner, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.seller_deposit, helpers.QTY_1) - }) - - it("Should update escrow amounts after transfer", async () => { - - expectedBalanceInEscrow = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldSupplyOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewSupplyOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(ZERO), "New owner balance from escrow does not match") - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}), - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldSupplyOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewSupplyOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(ZERO), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "New owner balance from escrow does not match") - - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerAmount = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerAmount = new BN(helpers.seller_deposit).add(new BN(helpers.product_price)) // 0.35 - const expectedEscrowAmount = new BN(0) // 0 - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - let withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, NewSupplyOwner.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - - }) - - it("New owner should be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await utils.cancel(voucherID, NewSupplyOwner.address) - }) - - it("[NEGATIVE] Old owner should not be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await truffleAssert.reverts( - utils.cancel(voucherID, OldSupplyOwner.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - - let balanceBuyerFromDeposits = new BN(0) - - let balanceSellerFromDeposits = new BN(0) - - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - - await utils.mintTokens('contractBSNTokenDeposit', OldSupplyOwner.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, helpers.buyer_deposit); - - tokenSupplyKey = await utils.createOrder( - OldSupplyOwner, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - - }) - - async function getBalancesDepositToken() { - - balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Buyer.address) - balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(NewSupplyOwner.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - - } - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) //// 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy( - Buyer, - NewSupplyOwner, - tokenSupplyKey - ) - - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - let withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesDepositToken(); - - // Payment should have been sent to seller - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, NewSupplyOwner.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDeposits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDeposits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }) - - it("New owner should be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await utils.cancel(voucherID, NewSupplyOwner.address) - }) - - it("[NEGATIVE] Old owner should not be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await truffleAssert.reverts( - utils.cancel(voucherID, OldSupplyOwner.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_TKN", () => { - - let balanceBuyerFromPayment = new BN(0) - let balanceBuyerFromDeposits = new BN(0) - - let balanceSellerFromPayment = new BN(0) - let balanceSellerFromDeposits = new BN(0) - - let escrowBalanceFromPayment = new BN(0) - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - - await utils.mintTokens('contractBSNTokenDeposit', OldSupplyOwner.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, helpers.product_price); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, helpers.buyer_deposit); - - tokenSupplyKey = await utils.createOrder( - OldSupplyOwner, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - - }) - - async function getBalancesFromPiceTokenAndDepositToken() { - - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Buyer.address) - balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Buyer.address) - - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(NewSupplyOwner.address) - balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(NewSupplyOwner.address) - - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - - } - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) //// 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDeposits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDeposits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(ZERO), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(ZERO), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }) - - it("New owner should be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await utils.cancel(voucherID, NewSupplyOwner.address) - }) - - it("[NEGATIVE] Old owner should not be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await truffleAssert.reverts( - utils.cancel(voucherID, OldSupplyOwner.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_ETH", () => { - let balanceBuyerFromPayment = new BN(0) - let balanceSellerFromPayment = new BN(0) - let escrowBalanceFromPayment = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, helpers.product_price); - - tokenSupplyKey = await utils.createOrder( - OldSupplyOwner, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - }) - - async function getBalancesPriceToken() { - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Buyer.address) - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(NewSupplyOwner.address) - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - } - - it("Should update escrow amounts after transfer", async () => { - - expectedBalanceInEscrow = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_1)) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldSupplyOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewSupplyOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(ZERO), "New owner balance from escrow does not match") - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldSupplyOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewSupplyOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(ZERO), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "New owner balance from escrow does not match") - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerPrice = new BN(0) - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy( - Buyer, - NewSupplyOwner, - tokenSupplyKey - ) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - let withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been sent to seller - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, NewSupplyOwner.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }) - - it("New owner should be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await utils.cancel(voucherID, NewSupplyOwner.address) - }) - - it("[NEGATIVE] Old owner should not be able to COF", async () => { - - utils.safeTransfer1155(OldSupplyOwner.address, NewSupplyOwner.address, tokenSupplyKey, helpers.QTY_1, {from: OldSupplyOwner.address}) - - const voucherID = await utils.commitToBuy(Buyer, NewSupplyOwner, tokenSupplyKey) - - await utils.redeem(voucherID, Buyer.address) - - await truffleAssert.reverts( - utils.cancel(voucherID, OldSupplyOwner.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - }) - }) - - describe("VOUCHER TRANSFER", () => { - - let OldVoucherOwner = config.accounts.randomUser - let NewVoucherOwner = config.accounts.randomUser2 - - let actualOldOwnerBalanceFromEscrow = new BN(0); - let actualNewOwnerBalanceFromEscrow = new BN(0); - let expectedBalanceInEscrow = new BN(0); - - afterEach(() => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - actualOldOwnerBalanceFromEscrow = new BN(0); - actualNewOwnerBalanceFromEscrow = new BN(0); - expectedBalanceInEscrow = new BN(0); - }) - - describe("Common transfer", () => { - - before(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - tokenSupplyKey = await utils.createOrder(Seller, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.seller_deposit, helpers.QTY_10) - }) - - it("Should transfer a voucher", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - let transferTx = await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - truffleAssert.eventEmitted(transferTx, 'Transfer', (ev) => { - - assert.equal(ev._from, OldVoucherOwner.address) - assert.equal(ev._to, NewVoucherOwner.address) - assert.equal(ev._tokenId.toString(), voucherID) - - return true - }, "Transfer not emitted") - }) - }) - - describe("ETH_ETH", async () => { - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - tokenSupplyKey = await utils.createOrder(Seller, helpers.PROMISE_VALID_FROM, helpers.PROMISE_VALID_TO, helpers.seller_deposit, helpers.QTY_10) - }) - - it("Should update escrow amounts after transfer", async () => { - - expectedBalanceInEscrow = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(ZERO), "New owner balance from escrow does not match") - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(ZERO), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "New owner balance from escrow does not match") - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.3 + 0.04 + 0.025 - const expectedSellerAmount = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmount = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await utils.refund(voucherID, NewVoucherOwner.address) - await utils.complain(voucherID, NewVoucherOwner.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', NewVoucherOwner.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }) +const Users = require('../testHelpers/users'); +const UtilsBuilder = require('../testHelpers/utilsBuilder'); +const {toWei, getApprovalDigest} = require('../testHelpers/permitUtils'); - it("[NEGATIVE] Old owner should not be able to interact with the voucher", async () => { +const ERC1155ERC721 = artifacts.require('ERC1155ERC721'); +const VoucherKernel = artifacts.require('VoucherKernel'); +const Cashier = artifacts.require('Cashier'); +const BosonRouter = artifacts.require('BosonRouter'); +const BosonToken = artifacts.require('BosonTokenPrice'); +const FundLimitsOracle = artifacts.require('FundLimitsOracle'); - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) +const BN = web3.utils.BN; - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await truffleAssert.reverts( - utils.redeem(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) +let utils; - await truffleAssert.reverts( - utils.refund(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await truffleAssert.reverts( - utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - let balanceBuyerFromDeposits = new BN(0) - let balanceSellerFromDeposits = new BN(0) - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - - async function getBalancesDepositToken() { - balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(NewVoucherOwner.address) - balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Seller.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', OldVoucherOwner.address, helpers.buyer_deposit); - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - }) - - afterEach(async () => { - - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - balanceBuyerFromPayment = new BN(0) - balanceBuyerFromDeposits = new BN(0) - - balanceSellerFromPayment = new BN(0) - balanceSellerFromDeposits = new BN(0) - - escrowBalanceFromPayment = new BN(0) - escrowBalanceFromDeposits = new BN(0) - - cashierPaymentLeft = new BN(0) - cashierDepositLeft = new BN(0) - - const isPaused = await contractCashier.paused(); - if (isPaused) { - await contractCashier.unpause(); - } - - }) - - it("Should update escrow amounts after transfer", async () => { - - expectedBalanceInEscrow = new BN(helpers.product_price) - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(ZERO), "New owner balance from escrow does not match") - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(ZERO), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "New owner balance from escrow does not match") - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await utils.refund(voucherID, NewVoucherOwner.address) - await utils.complain(voucherID, NewVoucherOwner.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, NewVoucherOwner.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogAmountDistribution was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDeposits.eq(expectedBuyerDeposit), "NewVoucherOwner did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDeposits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', NewVoucherOwner.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - }) - - it("[NEGATIVE] Old owner should not be able to interact with the voucher", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await truffleAssert.reverts( - utils.redeem(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - await truffleAssert.reverts( - utils.refund(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await truffleAssert.reverts( - utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_TKN", () => { - - let balanceBuyerFromPayment = new BN(0) - let balanceBuyerFromDeposits = new BN(0) - - let balanceSellerFromPayment = new BN(0) - let balanceSellerFromDeposits = new BN(0) - - let escrowBalanceFromPayment = new BN(0) - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - - async function getBalancesFromPiceTokenAndDepositToken() { - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(NewVoucherOwner.address) - balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(NewVoucherOwner.address) - - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Seller.address) - balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Seller.address) - - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', OldVoucherOwner.address, helpers.product_price); - await utils.mintTokens('contractBSNTokenDeposit', OldVoucherOwner.address, helpers.buyer_deposit); - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountPrice = new BN(0) - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await utils.refund(voucherID, NewVoucherOwner.address) - await utils.complain(voucherID, NewVoucherOwner.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDeposits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDeposits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }) - - it("[NEGATIVE] Old owner should not be able to interact with the voucher", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}) - - await truffleAssert.reverts( - utils.redeem(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - await truffleAssert.reverts( - utils.refund(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await truffleAssert.reverts( - utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_ETH", () => { - - let balanceBuyerFromPayment = new BN(0) - let balanceSellerFromPayment = new BN(0) - let escrowBalanceFromPayment = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - beforeEach(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - await utils.mintTokens('contractBSNTokenPrice', OldVoucherOwner.address, helpers.product_price); - - tokenSupplyKey = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - - }) - - async function getBalancesPriceToken() { - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(NewVoucherOwner.address) - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Seller.address) - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - } - - it("Should update escrow amounts after transfer", async () => { - - expectedBalanceInEscrow = new BN(helpers.buyer_deposit) - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(ZERO), "New owner balance from escrow does not match") - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}), - - actualOldOwnerBalanceFromEscrow = await contractCashier.escrow(OldVoucherOwner.address) - actualNewOwnerBalanceFromEscrow = await contractCashier.escrow(NewVoucherOwner.address) - - assert.isTrue(actualOldOwnerBalanceFromEscrow.eq(ZERO), "Old owner balance from escrow does not match") - assert.isTrue(actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), "New owner balance from escrow does not match") - }) - - it("Should finalize 1 voucher to ensure payments are sent to the new owner", async () => { - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}), - - await utils.refund(voucherID, NewVoucherOwner.address) - await utils.complain(voucherID, NewVoucherOwner.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await utils.withdraw(voucherID, Deployer.address); - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', NewVoucherOwner.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }) - - it("[NEGATIVE] Old owner should not be able to interact with the voucher", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: OldVoucherOwner.address}), - - await truffleAssert.reverts( - utils.redeem(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - await truffleAssert.reverts( - utils.refund(voucherID, OldVoucherOwner.address), - truffleAssert.ErrorType.REVERT - ) - - }) - - it("[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer", async () => { - - voucherID = await utils.commitToBuy(OldVoucherOwner, Seller, tokenSupplyKey) - - await truffleAssert.reverts( - utils.safeTransfer721(OldVoucherOwner.address, NewVoucherOwner.address, voucherID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - }) - - }) +contract('Cashier && VK', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit, + contractFundLimitsOracle; + let tokenSupplyKey, tokenVoucherKey, tokenVoucherKey1; + + const ZERO = new BN(0); + const ONE_VOUCHER = 1; + + const deadline = toWei(1); + + let timestamp; + + let distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + async function deployContracts() { + const sixtySeconds = 60; + + const timestamp = await Utils.getCurrTimestamp(); + + constants.PROMISE_VALID_FROM = timestamp; + constants.PROMISE_VALID_TO = timestamp + 2 * constants.SECONDS_IN_DAY; + + contractFundLimitsOracle = await FundLimitsOracle.new(); + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + + contractBSNTokenPrice = await BosonToken.new('BosonTokenPrice', 'BPRC'); + contractBSNTokenDeposit = await BosonToken.new('BosonTokenDeposit', 'BDEP'); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + + await contractVoucherKernel.setComplainPeriod(sixtySeconds); + await contractVoucherKernel.setCancelFaultPeriod(sixtySeconds); + + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + constants.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenDeposit.address, + constants.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setETHLimit(constants.ETHER_LIMIT); + } + + describe('TOKEN SUPPLY CREATION (Voucher batch creation)', () => { + let remQty = constants.QTY_10; + let vouchersToBuy = 5; + + const paymentMethods = { + ETHETH: 1, + ETHTKN: 2, + TKNETH: 3, + TKNTKN: 4, + }; + + afterEach(() => { + remQty = constants.QTY_10; + }); + + describe('ETHETH', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + timestamp = await Utils.getCurrTimestamp(); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('ESCROW has correct initial balance', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(remQty) + ); + const escrowAmount = await contractCashier.getEscrowAmount( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Cashier Contract has correct amount of ETH', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(remQty) + ); + const cashierBalance = await web3.eth.getBalance( + contractCashier.address + ); + + assert.isTrue( + new BN(cashierBalance).eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Get correct remaining qty for supply', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + remQty, + 'Remaining qty is not correct' + ); + + for (let i = 0; i < vouchersToBuy; i++) { + await utils.commitToBuy(users.buyer, users.seller, tokenSupplyKey); + remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + --remQty, + 'Remaining qty is not correct' + ); + } + }); + + it('Should create payment method ETHETH', async () => { + timestamp = await Utils.getCurrTimestamp(); + let tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + + const paymentDetails = await contractVoucherKernel.paymentDetails( + tokenSupplyKey + ); + + assert.equal( + paymentDetails.paymentMethod.toString(), + paymentMethods.ETHETH, + 'Payment Method ETHETH not set correctly' + ); + assert.equal( + paymentDetails.addressTokenPrice.toString(), + constants.ZERO_ADDRESS, + 'ETHETH Method Price Token Address mismatch' + ); + assert.equal( + paymentDetails.addressTokenDeposits.toString(), + constants.ZERO_ADDRESS, + 'ETHETH Method Deposit Token Address mismatch' + ); + }); + + it('[NEGATIVE] Should fail if additional token address is provided', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + timestamp = await Utils.getCurrTimestamp(); + + await truffleAssert.fails( + contractBosonRouter.requestCreateOrderETHETH( + contractBSNTokenDeposit.address, + [ + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue} + ) + ); + }); + + it('[NEGATIVE] Should not create a supply if price is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.ABOVE_ETH_LIMIT, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositBu is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.ABOVE_ETH_LIMIT, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositSe is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHETH( + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.ABOVE_ETH_LIMIT, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const tokensToMint = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_20) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + + timestamp = await Utils.getCurrTimestamp(); + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('ESCROW has correct initial balance', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_10) + ); + const escrowAmount = await contractBSNTokenDeposit.balanceOf( + contractCashier.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Get correct remaining qty for supply', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + assert.equal( + remainingQtyInContract, + remQty, + 'Remaining qty is not correct' + ); + + for (let i = 0; i < vouchersToBuy; i++) { + await utils.commitToBuy(users.buyer, users.seller, tokenSupplyKey); + remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + --remQty, + 'Remaining qty is not correct' + ); + } + }); + + it('Should create payment method ETHTKN', async () => { + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + + const paymentDetails = await contractVoucherKernel.paymentDetails( + tokenSupplyKey + ); + + assert.equal( + paymentDetails.paymentMethod.toString(), + paymentMethods.ETHTKN, + 'Payment Method ETHTKN not set correctly' + ); + assert.equal( + paymentDetails.addressTokenPrice.toString(), + constants.ZERO_ADDRESS, + 'ETHTKN Method Price Token Address mismatch' + ); + assert.equal( + paymentDetails.addressTokenDeposits.toString(), + contractBSNTokenDeposit.address, + 'ETHTKN Method Deposit Token Address mismatch' + ); + }); + + it('[NEGATIVE] Should fail if token deposit contract address is not provided', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.fails( + contractBosonRouter.requestCreateOrderETHTKNWithPermit( + '', + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ) + ); + }); + + it('[NEGATIVE] Should revert if token deposit contract address is zero address', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHTKNWithPermit( + constants.ZERO_ADDRESS, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if price is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + const deadline = toWei(1); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHTKNWithPermit( + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.ABOVE_ETH_LIMIT, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositBu is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + const deadline = toWei(1); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHTKNWithPermit( + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.ABOVE_TOKEN_LIMIT, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositSe is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + const deadline = toWei(1); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderETHTKNWithPermit( + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.ABOVE_TOKEN_LIMIT, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + timestamp = await Utils.getCurrTimestamp(); + + const tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('ESCROW has correct initial balance', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(remQty) + ); + const escrowAmount = await contractCashier.getEscrowAmount( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Cashier Contract has correct amount of ETH', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(remQty) + ); + const cashierBalance = await web3.eth.getBalance( + contractCashier.address + ); + + assert.isTrue( + new BN(cashierBalance).eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Get correct remaining qty for supply', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + remQty, + 'Remaining qty is not correct' + ); + + for (let i = 0; i < vouchersToBuy; i++) { + await utils.commitToBuy(users.buyer, users.seller, tokenSupplyKey); + remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + --remQty, + 'Remaining qty is not correct' + ); + } + }); + + it('Should create payment method TKNETH', async () => { + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const paymentDetails = await contractVoucherKernel.paymentDetails( + tokenSupplyKey + ); + + assert.equal( + paymentDetails.paymentMethod.toString(), + paymentMethods.TKNETH, + 'Payment Method TKNETH not set correctly' + ); + assert.equal( + paymentDetails.addressTokenPrice.toString(), + contractBSNTokenPrice.address, + 'TKNETH Method Price Token Address mismatch' + ); + assert.equal( + paymentDetails.addressTokenDeposits.toString(), + constants.ZERO_ADDRESS, + 'TKNETH Method Deposit Token Address mismatch' + ); + }); + + it('[NEGATIVE] Should fail if price token contract address is not provided', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.fails( + contractBosonRouter.requestCreateOrderTKNETH( + '', + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue.toString()} + ) + ); + }); + + it('[NEGATIVE] Should fail if token price contract is zero address', async () => { + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNETH( + constants.ZERO_ADDRESS, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if price is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNETH( + contractBSNTokenPrice.address, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.ABOVE_TOKEN_LIMIT, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue.toString()} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositBu is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNETH( + contractBSNTokenPrice.address, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.ABOVE_ETH_LIMIT, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue.toString()} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositSe is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNETH( + contractBSNTokenPrice.address, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.ABOVE_ETH_LIMIT, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address, value: txValue.toString()} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + timestamp = await Utils.getCurrTimestamp(); + + const tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_20) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('ESCROW has correct initial balance', async () => { + const expectedBalance = new BN(constants.seller_deposit).mul( + new BN(remQty) + ); + const escrowAmount = await contractBSNTokenDeposit.balanceOf( + contractCashier.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Get correct remaining qty for supply', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + remQty, + 'Remaining qty is not correct' + ); + + for (let i = 0; i < vouchersToBuy; i++) { + await utils.commitToBuy(users.buyer, users.seller, tokenSupplyKey); + remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + tokenSupplyKey, + users.seller.address + ); + + assert.equal( + remainingQtyInContract, + --remQty, + 'Remaining qty is not correct' + ); + } + }); + + it('Should create payment method TKNTKN', async () => { + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const paymentDetails = await contractVoucherKernel.paymentDetails( + tokenSupplyKey + ); + + assert.equal( + paymentDetails.paymentMethod.toString(), + paymentMethods.TKNTKN, + 'Payment Method TKNTKN not set correctly' + ); + assert.equal( + paymentDetails.addressTokenPrice.toString(), + contractBSNTokenPrice.address, + 'TKNTKN Method Price Token Address mismatch' + ); + assert.equal( + paymentDetails.addressTokenDeposits.toString(), + contractBSNTokenDeposit.address, + 'TKNTKN Method Deposit Token Address mismatch' + ); + }); + + it('[NEGATIVE] Should fail if token price contract address is not provided', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.fails( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + '', + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ) + ); + }); + + it('[NEGATIVE] Should fail if token deposit contract address is not provided', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.fails( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + contractBSNTokenPrice.address, + '', + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ) + ); + }); + + it('[NEGATIVE] Should revert if token price contract address is zero address', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + constants.ZERO_ADDRESS, + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should revert if token deposit contract address is zero address', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(ONE_VOUCHER) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + const deadline = toWei(1); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + contractBSNTokenPrice.address, + constants.ZERO_ADDRESS, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if price is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + contractBSNTokenPrice.address, + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.ABOVE_TOKEN_LIMIT, + constants.seller_deposit, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositBu is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + contractBSNTokenPrice.address, + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.seller_deposit, + constants.ABOVE_TOKEN_LIMIT, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create a supply if depositSe is above the limit', async () => { + const txValue = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + const nonce = await contractBSNTokenDeposit.nonces( + users.seller.address + ); + + const digest = await getApprovalDigest( + contractBSNTokenDeposit, + users.seller.address, + contractCashier.address, + txValue, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.seller.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestCreateOrderTKNTKNWithPermit( + contractBSNTokenPrice.address, + contractBSNTokenDeposit.address, + txValue, + deadline, + v, + r, + s, + [ + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.PROMISE_PRICE1, + constants.ABOVE_TOKEN_LIMIT, + constants.PROMISE_DEPOSITBU1, + constants.ORDER_QUANTITY1, + ], + {from: users.seller.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + describe('VOUCHER CREATION (Commit to buy)', () => { + const ORDER_QTY = 5; + let TOKEN_SUPPLY_ID; + + describe('ETHETH', async () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('Should create order', async () => { + const txValue = new BN(constants.buyer_deposit).add( + new BN(constants.product_price) + ); + let txFillOrder = await contractBosonRouter.requestVoucherETHETH( + TOKEN_SUPPLY_ID, + users.seller.address, + { + from: users.buyer.address, + value: txValue, + } + ); + + let internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + }); + + it('Cashier Contract has correct amount of funds', async () => { + const sellerDeposits = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_10) + ); + const buyerETHSent = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + const expectedBalance = sellerDeposits.add(buyerETHSent); + + const cashierBalance = await web3.eth.getBalance( + contractCashier.address + ); + + assert.isTrue( + new BN(cashierBalance).eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Should not create order with incorrect price', async () => { + const txValue = new BN(constants.buyer_deposit).add( + new BN(constants.incorrect_product_price) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherETHETH( + TOKEN_SUPPLY_ID, + users.seller.address, + {from: users.buyer.address, value: txValue} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create order with incorrect deposit', async () => { + const txValue = new BN(constants.buyer_incorrect_deposit).add( + new BN(constants.product_price) + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherETHETH( + TOKEN_SUPPLY_ID, + users.seller.address, + {from: users.buyer.address, value: txValue} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', async () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const tokensToMintSeller = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const tokensToMintBuyer = new BN(constants.buyer_deposit).mul( + new BN(ORDER_QTY) + ); + + await contractBSNTokenDeposit.mint( + users.seller.address, + tokensToMintSeller + ); + await contractBSNTokenDeposit.mint( + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + ORDER_QTY + ); + }); + + it('Should create order', async () => { + const nonce = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractBosonRouter.address, + constants.buyer_deposit, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + const txFillOrder = await contractBosonRouter.requestVoucherETHTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.buyer_deposit, + deadline, + v, + r, + s, + {from: users.buyer.address, value: constants.product_price} + ); + + let internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + }); + + it('Cashier Contract has correct amount of funds', async () => { + const expectedETHBalance = new BN(constants.product_price); + const cashierETHBalance = await web3.eth.getBalance( + contractCashier.address + ); + + const cashierDepositTokenBalance = await contractBSNTokenDeposit.balanceOf( + contractCashier.address + ); + const sellerTokenDeposits = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const expectedTokenBalance = new BN(constants.buyer_deposit).add( + sellerTokenDeposits + ); + + assert.isTrue( + new BN(cashierETHBalance).eq(expectedETHBalance), + 'Escrow amount is incorrect' + ); + assert.isTrue( + expectedTokenBalance.eq(cashierDepositTokenBalance), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Should not create order with incorrect price', async () => { + const nonce = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractCashier.address, + constants.buyer_deposit, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherETHTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.buyer_deposit, + deadline, + v, + r, + s, + { + from: users.buyer.address, + value: constants.incorrect_product_price, + } + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create order with incorrect deposit', async () => { + const nonce = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractCashier.address, + constants.buyer_deposit, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherETHTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.buyer_incorrect_deposit, + deadline, + v, + r, + s, + {from: users.buyer.address, value: constants.product_price} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const tokensToMintSeller = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const tokensToMintBuyer = new BN(constants.product_price).mul( + new BN(ORDER_QTY) + ); + + await contractBSNTokenDeposit.mint( + users.seller.address, + tokensToMintSeller + ); + await contractBSNTokenDeposit.mint( + users.buyer.address, + tokensToMintBuyer + ); + await contractBSNTokenPrice.mint( + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + ORDER_QTY + ); + }); + + it('Should create order', async () => { + const nonce1 = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const tokensToSend = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractBosonRouter.address, + constants.buyer_deposit, + nonce1, + deadline + ); + + let VRS_DEPOSIT = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vDeposit = VRS_DEPOSIT.v; + let rDeposit = VRS_DEPOSIT.r; + let sDeposit = VRS_DEPOSIT.s; + + const nonce2 = await contractBSNTokenPrice.nonces( + users.buyer.address + ); + + const digestPrice = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractBosonRouter.address, + constants.product_price, + nonce2, + deadline + ); + + let VRS_PRICE = ecsign( + Buffer.from(digestPrice.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vPrice = VRS_PRICE.v; + let rPrice = VRS_PRICE.r; + let sPrice = VRS_PRICE.s; + + let txFillOrder = await contractBosonRouter.requestVoucherTKNTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + tokensToSend, + deadline, + vPrice, + rPrice, + sPrice, + vDeposit, + rDeposit, + sDeposit, + {from: users.buyer.address} + ); + + let internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + }); + + it('Cashier Contract has correct amount of funds', async () => { + const cashierPriceTokenBalance = await contractBSNTokenPrice.balanceOf( + contractCashier.address + ); + const cashierDepositTokenBalance = await contractBSNTokenDeposit.balanceOf( + contractCashier.address + ); + const sellerDeposit = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const expectedDepositBalance = new BN(constants.buyer_deposit).add( + sellerDeposit + ); + + assert.isTrue( + new BN(cashierPriceTokenBalance).eq( + new BN(constants.product_price) + ), + 'Escrow amount is incorrect' + ); + assert.isTrue( + new BN(cashierDepositTokenBalance).eq(expectedDepositBalance), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Should not create order with incorrect price', async () => { + const nonce1 = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const tokensToSend = new BN(constants.incorrect_product_price).add( + new BN(constants.buyer_deposit) + ); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractCashier.address, + constants.buyer_deposit, + nonce1, + deadline + ); + + let VRS_DEPOSIT = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vDeposit = VRS_DEPOSIT.v; + let rDeposit = VRS_DEPOSIT.r; + let sDeposit = VRS_DEPOSIT.s; + + const nonce2 = await contractBSNTokenPrice.nonces( + users.buyer.address + ); + + const digestPrice = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractCashier.address, + constants.product_price, + nonce2, + deadline + ); + + let VRS_PRICE = ecsign( + Buffer.from(digestPrice.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vPrice = VRS_PRICE.v; + let rPrice = VRS_PRICE.r; + let sPrice = VRS_PRICE.s; + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + tokensToSend, + deadline, + vPrice, + rPrice, + sPrice, + vDeposit, + rDeposit, + sDeposit, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create order with incorrect deposit', async () => { + const nonce1 = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const tokensToSend = new BN(constants.product_price).add( + new BN(constants.buyer_incorrect_deposit) + ); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenDeposit, + users.buyer.address, + contractCashier.address, + constants.buyer_deposit, + nonce1, + deadline + ); + + let VRS_DEPOSIT = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vDeposit = VRS_DEPOSIT.v; + let rDeposit = VRS_DEPOSIT.r; + let sDeposit = VRS_DEPOSIT.s; + + const nonce2 = await contractBSNTokenPrice.nonces( + users.buyer.address + ); + + const digestPrice = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractCashier.address, + constants.product_price, + nonce2, + deadline + ); + + let VRS_PRICE = ecsign( + Buffer.from(digestPrice.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let vPrice = VRS_PRICE.v; + let rPrice = VRS_PRICE.r; + let sPrice = VRS_PRICE.s; + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNTKNWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + tokensToSend, + deadline, + vPrice, + rPrice, + sPrice, + vDeposit, + rDeposit, + sDeposit, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN Same', () => { + const tokensToMintSeller = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const tokensToMintBuyer = new BN(constants.product_price).mul( + new BN(ORDER_QTY) + ); + + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKNSame() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + await utils.contractBSNTokenSame.mint( + users.seller.address, + tokensToMintSeller + ); + await utils.contractBSNTokenSame.mint( + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + ORDER_QTY + ); + }); + + it('Should create voucher', async () => { + const nonce = await utils.contractBSNTokenSame.nonces( + users.buyer.address + ); + const tokensToSend = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + + const digestTokens = await getApprovalDigest( + utils.contractBSNTokenSame, + users.buyer.address, + contractBosonRouter.address, + tokensToSend, + nonce, + deadline + ); + + let VRS_TOKENS = ecsign( + Buffer.from(digestTokens.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let v = VRS_TOKENS.v; + let r = VRS_TOKENS.r; + let s = VRS_TOKENS.s; + + let txFillOrder = await contractBosonRouter.requestVoucherTKNTKNSameWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + tokensToSend, + deadline, + v, + r, + s, + {from: users.buyer.address} + ); + + let internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey1 = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + + assert.isDefined(tokenVoucherKey1); + }); + + it('Cashier Contract has correct amount of funds', async () => { + const cashierTokenBalanceSame = await utils.contractBSNTokenSame.balanceOf( + contractCashier.address + ); + const sellerDeposits = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const buyerTokensSent = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + const expectedDepositBalance = buyerTokensSent.add(sellerDeposits); + + assert.isTrue( + new BN(cashierTokenBalanceSame).eq(expectedDepositBalance), + 'Cashier amount is incorrect' + ); + }); + + it('[NEGATIVE] Should not create order with incorrect price', async () => { + const nonce = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const incorrectTokensToSign = new BN( + constants.incorrect_product_price + ).add(new BN(constants.buyer_deposit)); + const digestTokens = await getApprovalDigest( + utils.contractBSNTokenSame, + users.buyer.address, + contractCashier.address, + incorrectTokensToSign, + nonce, + deadline + ); + + let VRS_TOKENS = ecsign( + Buffer.from(digestTokens.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let v = VRS_TOKENS.v; + let r = VRS_TOKENS.r; + let s = VRS_TOKENS.s; + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNTKNSameWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + incorrectTokensToSign, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create order with incorrect deposit', async () => { + const nonce = await contractBSNTokenDeposit.nonces( + users.buyer.address + ); + const incorrectTokensToSign = new BN(constants.product_price).add( + new BN(constants.buyer_incorrect_deposit) + ); + const digestTokens = await getApprovalDigest( + utils.contractBSNTokenSame, + users.buyer.address, + contractCashier.address, + incorrectTokensToSign, + nonce, + deadline + ); + + let VRS_TOKENS = ecsign( + Buffer.from(digestTokens.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let v = VRS_TOKENS.v; + let r = VRS_TOKENS.r; + let s = VRS_TOKENS.s; + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNTKNSameWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + incorrectTokensToSign, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should revert if Price Token and Deposit Token are diff contracts', async () => { + //get instance with different Price token and Deposit Token addresses + let utilsTKNTKN = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + await contractBSNTokenDeposit.mint( + users.seller.address, + tokensToMintSeller + ); + await contractBSNTokenDeposit.mint( + users.buyer.address, + tokensToMintBuyer + ); + await contractBSNTokenPrice.mint( + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utilsTKNTKN.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + ORDER_QTY + ); + + const nonce = await utils.contractBSNTokenSame.nonces( + users.buyer.address + ); + const tokensToSend = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + + const digestTokens = await getApprovalDigest( + utils.contractBSNTokenSame, + users.buyer.address, + contractBosonRouter.address, + tokensToSend, + nonce, + deadline + ); + + let VRS_TOKENS = ecsign( + Buffer.from(digestTokens.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let v = VRS_TOKENS.v; + let r = VRS_TOKENS.r; + let s = VRS_TOKENS.s; + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNTKNSameWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + tokensToSend, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const tokensToMintBuyer = new BN(constants.product_price).mul( + new BN(ORDER_QTY) + ); + + await contractBSNTokenPrice.mint( + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + ORDER_QTY + ); + }); + + it('Should create order', async () => { + const nonce = await contractBSNTokenPrice.nonces(users.buyer.address); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractBosonRouter.address, + constants.product_price, + nonce, + deadline + ); + + let {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + let txFillOrder = await contractBosonRouter.requestVoucherTKNETHWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.product_price, + deadline, + v, + r, + s, + {from: users.buyer.address, value: constants.buyer_deposit} + ); + + let internalTx = await truffleAssert.createTransactionResult( + contractVoucherKernel, + txFillOrder.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'LogVoucherDelivered', + (ev) => { + tokenVoucherKey = ev._tokenIdVoucher; + return ev._issuer === users.seller.address; + }, + 'order1 not created successfully' + ); + + assert.isDefined(tokenVoucherKey); + }); + + it('Cashier Contract has correct amount of funds', async () => { + const cashierDepositETH = await web3.eth.getBalance( + contractCashier.address + ); + const sellerDeposits = new BN(constants.seller_deposit).mul( + new BN(ORDER_QTY) + ); + const expectedDepositBalance = new BN(constants.buyer_deposit).add( + sellerDeposits + ); + + const cashierPriceTokenBalance = await contractBSNTokenPrice.balanceOf( + contractCashier.address + ); + + assert.isTrue( + new BN(cashierDepositETH).eq(expectedDepositBalance), + 'Cashier amount is incorrect' + ); + assert.isTrue( + new BN(cashierPriceTokenBalance).eq( + new BN(constants.product_price) + ), + 'Cashier amount is incorrect' + ); + }); + + it('[NEGATIVE] Should not create order with incorrect deposit', async () => { + const nonce = await contractBSNTokenPrice.nonces(users.buyer.address); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractCashier.address, + constants.product_price, + nonce, + deadline + ); + + let {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNETHWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.product_price, + deadline, + v, + r, + s, + { + from: users.buyer.address, + value: constants.buyer_incorrect_deposit, + } + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not create order with incorrect price', async () => { + const nonce = await contractBSNTokenPrice.nonces(users.buyer.address); + + const digestDeposit = await getApprovalDigest( + contractBSNTokenPrice, + users.buyer.address, + contractCashier.address, + constants.product_price, + nonce, + deadline + ); + + let {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + contractBosonRouter.requestVoucherTKNETHWithPermit( + TOKEN_SUPPLY_ID, + users.seller.address, + constants.incorrect_product_price, + deadline, + v, + r, + s, + {from: users.buyer.address, value: constants.buyer_deposit} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + describe('TOKEN SUPPLY TRANSFER', () => { + let actualOldOwnerBalanceFromEscrow = new BN(0); + let actualNewOwnerBalanceFromEscrow = new BN(0); + let expectedBalanceInEscrow = new BN(0); + + afterEach(() => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + }); + + describe('Common transfer', () => { + beforeEach(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokenSupplyKey = await utils.createOrder( + users.other1, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('Should transfer voucher supply', async () => { + let transferTx = await utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_10, + {from: users.other1.address} + ); + + truffleAssert.eventEmitted( + transferTx, + 'TransferSingle', + (ev) => { + assert.equal(ev._from, users.other1.address); + assert.equal(ev._to, users.other2.address); + assert.equal(ev._id.toString(), tokenSupplyKey); + assert.equal(ev._value.toString(), constants.QTY_10); + + return true; + }, + 'TransferSingle not emitted' + ); + }); + + it('[NEGATIVE] Should revert if owner tries to transfer voucher supply partially', async () => { + await truffleAssert.reverts( + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should revert if Attacker tries to transfer voucher supply', async () => { + await truffleAssert.reverts( + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_10, + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should transfer batch voucher supply', async () => { + let transferTx = await utils.safeBatchTransfer1155( + users.other1.address, + users.other2.address, + [tokenSupplyKey], + [constants.QTY_10], + {from: users.other1.address} + ); + + truffleAssert.eventEmitted( + transferTx, + 'TransferBatch', + (ev) => { + assert.equal(ev._from, users.other1.address); + assert.equal(ev._to, users.other2.address); + assert.equal( + JSON.stringify(ev._ids), + JSON.stringify([new BN(tokenSupplyKey)]) + ); + assert.equal( + JSON.stringify(ev._values), + JSON.stringify([new BN(constants.QTY_10)]) + ); + + return true; + }, + 'TransferSingle not emitted' + ); + }); + + it('[NEGATIVE] Should revert if owner tries to transfer voucher supply batch partially', async () => { + await truffleAssert.reverts( + utils.safeBatchTransfer1155( + users.other1.address, + users.other2.address, + [tokenSupplyKey], + [constants.QTY_1], + {from: users.other1.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should revert if Attacker tries to transfer batch voucher supply', async () => { + await truffleAssert.reverts( + utils.safeBatchTransfer1155( + users.other1.address, + users.other2.address, + [tokenSupplyKey], + [constants.QTY_10], + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('ETHETH', () => { + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + tokenSupplyKey = await utils.createOrder( + users.other1, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + constants.QTY_1 + ); + }); + + it('Should update escrow amounts after transfer', async () => { + expectedBalanceInEscrow = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(ZERO), + 'New owner balance from escrow does not match' + ); + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ), + (actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + )); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(ZERO), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'New owner balance from escrow does not match' + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerAmount = new BN(constants.buyer_deposit); // 0.04 + const expectedSellerAmount = new BN(constants.seller_deposit).add( + new BN(constants.product_price) + ); // 0.35 + const expectedEscrowAmount = new BN(0); // 0 + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + let withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.other2.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('New owner should be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await utils.cancel(voucherID, users.other2.address); + }); + + it('[NEGATIVE] Old owner should not be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await truffleAssert.reverts( + utils.cancel(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + let balanceBuyerFromDeposits = new BN(0); + + let balanceSellerFromDeposits = new BN(0); + + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const tokensToMint = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.other1.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + constants.buyer_deposit + ); + + tokenSupplyKey = await utils.createOrder( + users.other1, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + }); + + async function getBalancesDepositToken() { + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.buyer.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.other2.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); + } + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerDeposit = new BN(constants.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(constants.product_price); //// 0.3 + const expectedSellerDeposit = new BN(constants.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + let withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesDepositToken(); + + // Payment should have been sent to seller + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.other2.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('New owner should be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await utils.cancel(voucherID, users.other2.address); + }); + + it('[NEGATIVE] Old owner should not be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await truffleAssert.reverts( + utils.cancel(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + let balanceBuyerFromPayment = new BN(0); + let balanceBuyerFromDeposits = new BN(0); + + let balanceSellerFromPayment = new BN(0); + let balanceSellerFromDeposits = new BN(0); + + let escrowBalanceFromPayment = new BN(0); + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMint = new BN(constants.seller_deposit).mul( + new BN(supplyQty) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.other1.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + constants.product_price + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + constants.buyer_deposit + ); + + tokenSupplyKey = await utils.createOrder( + users.other1, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + supplyQty + ); + }); + + async function getBalancesFromPiceTokenAndDepositToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.buyer.address + ); + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.buyer.address + ); + + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.other2.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.other2.address + ); + + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); + } + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(constants.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(constants.product_price); //// 0.3 + const expectedSellerDeposit = new BN(constants.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesFromPiceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(ZERO), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(ZERO), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('New owner should be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await utils.cancel(voucherID, users.other2.address); + }); + + it('[NEGATIVE] Old owner should not be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await truffleAssert.reverts( + utils.cancel(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + let balanceBuyerFromPayment = new BN(0); + let balanceSellerFromPayment = new BN(0); + let escrowBalanceFromPayment = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + constants.product_price + ); + + tokenSupplyKey = await utils.createOrder( + users.other1, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + }); + + async function getBalancesPriceToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.buyer.address + ); + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.other2.address + ); + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + } + + it('Should update escrow amounts after transfer', async () => { + expectedBalanceInEscrow = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_1) + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(ZERO), + 'New owner balance from escrow does not match' + ); + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(ZERO), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'New owner balance from escrow does not match' + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerPrice = new BN(0); + const expectedSellerPrice = new BN(constants.product_price); // 0.3 + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(constants.buyer_deposit); // 0.04 + const expectedSellerDeposit = new BN(constants.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + let withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been sent to seller + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.other2.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('New owner should be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await utils.cancel(voucherID, users.other2.address); + }); + + it('[NEGATIVE] Old owner should not be able to COF', async () => { + utils.safeTransfer1155( + users.other1.address, + users.other2.address, + tokenSupplyKey, + constants.QTY_1, + {from: users.other1.address} + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.other2, + tokenSupplyKey + ); + + await utils.redeem(voucherID, users.buyer.address); + + await truffleAssert.reverts( + utils.cancel(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + describe('VOUCHER TRANSFER', () => { + let actualOldOwnerBalanceFromEscrow = new BN(0); + let actualNewOwnerBalanceFromEscrow = new BN(0); + let expectedBalanceInEscrow = new BN(0); + + afterEach(() => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + actualOldOwnerBalanceFromEscrow = new BN(0); + actualNewOwnerBalanceFromEscrow = new BN(0); + expectedBalanceInEscrow = new BN(0); + }); + + describe('Common transfer', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('Should transfer a voucher', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + let transferTx = await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + truffleAssert.eventEmitted( + transferTx, + 'Transfer', + (ev) => { + assert.equal(ev._from, users.other1.address); + assert.equal(ev._to, users.other2.address); + assert.equal(ev._tokenId.toString(), voucherID); + + return true; + }, + 'Transfer not emitted' + ); + }); + }); + + describe('ETHETH', async () => { + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + constants.PROMISE_VALID_FROM, + constants.PROMISE_VALID_TO, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('Should update escrow amounts after transfer', async () => { + expectedBalanceInEscrow = new BN(constants.product_price).add( + new BN(constants.buyer_deposit) + ); + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(ZERO), + 'New owner balance from escrow does not match' + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(ZERO), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'New owner balance from escrow does not match' + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerAmount = new BN(constants.buyer_deposit) + .add(new BN(constants.product_price)) + .add(new BN(constants.seller_deposit).div(new BN(2))); // 0.3 + 0.04 + 0.025 + const expectedSellerAmount = new BN(constants.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmount = new BN(constants.seller_deposit).div( + new BN(4) + ); // 0.0125 + + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await utils.refund(voucherID, users.other2.address); + await utils.complain(voucherID, users.other2.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.other2.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('[NEGATIVE] Old owner should not be able to interact with the voucher', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await truffleAssert.reverts( + utils.redeem(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + + await truffleAssert.reverts( + utils.refund(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await truffleAssert.reverts( + utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + let balanceBuyerFromDeposits = new BN(0); + let balanceSellerFromDeposits = new BN(0); + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + async function getBalancesDepositToken() { + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.other2.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); + } + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMint = new BN(constants.seller_deposit).mul( + new BN(supplyQty) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.other1.address, + constants.buyer_deposit + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + supplyQty + ); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + balanceBuyerFromDeposits = new BN(0); + balanceSellerFromDeposits = new BN(0); + escrowBalanceFromDeposits = new BN(0); + + cashierPaymentLeft = new BN(0); + cashierDepositLeft = new BN(0); + + const isPaused = await contractCashier.paused(); + if (isPaused) { + await contractCashier.unpause(); + } + }); + + it('Should update escrow amounts after transfer', async () => { + expectedBalanceInEscrow = new BN(constants.product_price); + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(ZERO), + 'New owner balance from escrow does not match' + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(ZERO), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'New owner balance from escrow does not match' + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerPrice = new BN(constants.product_price); // 0.3 + const expectedBuyerDeposit = new BN(constants.buyer_deposit).add( + new BN(constants.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(constants.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + constants.seller_deposit + ).div(new BN(4)); // 0.0125 + + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await utils.refund(voucherID, users.other2.address); + await utils.complain(voucherID, users.other2.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.other2.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'NewVoucherOwner did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.other2.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] Old owner should not be able to interact with the voucher', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await truffleAssert.reverts( + utils.redeem(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + + await truffleAssert.reverts( + utils.refund(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await truffleAssert.reverts( + utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + let balanceBuyerFromPayment = new BN(0); + let balanceBuyerFromDeposits = new BN(0); + + let balanceSellerFromPayment = new BN(0); + let balanceSellerFromDeposits = new BN(0); + + let escrowBalanceFromPayment = new BN(0); + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + async function getBalancesFromPiceTokenAndDepositToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.other2.address + ); + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.other2.address + ); + + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.seller.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); + } + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMint = new BN(constants.seller_deposit).mul( + new BN(supplyQty) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.other1.address, + constants.product_price + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.other1.address, + constants.buyer_deposit + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + supplyQty + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerPrice = new BN(constants.product_price); // 0.3 + const expectedBuyerDeposit = new BN(constants.buyer_deposit).add( + new BN(constants.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(constants.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + constants.seller_deposit + ).div(new BN(4)); // 0.0125 + const expectedEscrowAmountPrice = new BN(0); + + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await utils.refund(voucherID, users.other2.address); + await utils.complain(voucherID, users.other2.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesFromPiceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('[NEGATIVE] Old owner should not be able to interact with the voucher', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ); + + await truffleAssert.reverts( + utils.redeem(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + + await truffleAssert.reverts( + utils.refund(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await truffleAssert.reverts( + utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + let balanceBuyerFromPayment = new BN(0); + let balanceSellerFromPayment = new BN(0); + let escrowBalanceFromPayment = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + beforeEach(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.other1.address, + constants.product_price + ); + + tokenSupplyKey = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + }); + + async function getBalancesPriceToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.other2.address + ); + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.seller.address + ); + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + } + + it('Should update escrow amounts after transfer', async () => { + expectedBalanceInEscrow = new BN(constants.buyer_deposit); + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + ); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(ZERO), + 'New owner balance from escrow does not match' + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ), + (actualOldOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other1.address + )); + actualNewOwnerBalanceFromEscrow = await contractCashier.escrow( + users.other2.address + ); + + assert.isTrue( + actualOldOwnerBalanceFromEscrow.eq(ZERO), + 'Old owner balance from escrow does not match' + ); + assert.isTrue( + actualNewOwnerBalanceFromEscrow.eq(expectedBalanceInEscrow), + 'New owner balance from escrow does not match' + ); + }); + + it('Should finalize 1 voucher to ensure payments are sent to the new owner', async () => { + const expectedBuyerPrice = new BN(constants.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(constants.buyer_deposit).add( + new BN(constants.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(constants.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + constants.seller_deposit + ).div(new BN(4)); // 0.0125 + + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ), + await utils.refund(voucherID, users.other2.address); + await utils.complain(voucherID, users.other2.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await utils.withdraw( + voucherID, + users.deployer.address + ); + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.other2.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('[NEGATIVE] Old owner should not be able to interact with the voucher', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.other1.address} + ), + await truffleAssert.reverts( + utils.redeem(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + + await truffleAssert.reverts( + utils.refund(voucherID, users.other1.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Transfer should revert if Attacker tries to execute voucher transfer', async () => { + const voucherID = await utils.commitToBuy( + users.other1, + users.seller, + tokenSupplyKey + ); + + await truffleAssert.reverts( + utils.safeTransfer721( + users.other1.address, + users.other2.address, + voucherID, + {from: users.attacker.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); }); - - - - - - diff --git a/test/3_withdrawals.js b/test/3_withdrawals.js index 59d61a4c..d8c74233 100644 --- a/test/3_withdrawals.js +++ b/test/3_withdrawals.js @@ -1,2564 +1,4226 @@ -const chai = require('chai') -const assert = chai.assert - -const BN = web3.utils.BN -const UtilsBuilder = require('../testHelpers/utilsBuilder') -const Utils = require('../testHelpers/utils') -let utils - -const ERC1155ERC721 = artifacts.require("ERC1155ERC721") -const VoucherKernel = artifacts.require("VoucherKernel") -const Cashier = artifacts.require("Cashier") -const BosonRouter = artifacts.require("BosonRouter") -const BosonTKN = artifacts.require("BosonTokenPrice") -const FundLimitsOracle = artifacts.require('FundLimitsOracle'); - -const helpers = require("../testHelpers/constants") -const timemachine = require('../testHelpers/timemachine') -const truffleAssert = require('truffle-assertions') -const config = require('../testHelpers/config.json') - -let TOKEN_SUPPLY_ID - -contract("Cashier withdrawals ", async accounts => { - - let Deployer = config.accounts.deployer - let Seller = config.accounts.seller - let Buyer = config.accounts.buyer - let Attacker = config.accounts.attacker - let RandomUser = config.accounts.randomUser // will be used to clear tokens received after every successful test - - let contractERC1155ERC721, - contractVoucherKernel, - contractCashier, - contractBosonRouter, - contractBSNTokenPrice, - contractBSNTokenDeposit, - contractFundLimitsOracle - const PAUSED_WITHPERMIT = 1; - const PAUSED_LABEL = "[PAUSED]"; - - let distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) +const {assert} = require('chai'); + +const helpers = require('../testHelpers/constants'); +const timemachine = require('../testHelpers/timemachine'); +const truffleAssert = require('truffle-assertions'); +const Users = require('../testHelpers/users'); +const UtilsBuilder = require('../testHelpers/utilsBuilder'); +const Utils = require('../testHelpers/utils'); + +const ERC1155ERC721 = artifacts.require('ERC1155ERC721'); +const VoucherKernel = artifacts.require('VoucherKernel'); +const Cashier = artifacts.require('Cashier'); +const BosonRouter = artifacts.require('BosonRouter'); +const BosonTKN = artifacts.require('BosonTokenPrice'); +const FundLimitsOracle = artifacts.require('FundLimitsOracle'); + +const BN = web3.utils.BN; + +let utils; + +let TOKEN_SUPPLY_ID; + +contract('Cashier withdrawals ', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit, + contractFundLimitsOracle; + + const PAUSED_WITHPERMIT = 1; + const PAUSED_LABEL = '[PAUSED]'; + + let distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + async function deployContracts() { + contractFundLimitsOracle = await FundLimitsOracle.new(); + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + contractBSNTokenPrice = await BosonTKN.new('BosonTokenPrice', 'BPRC'); + contractBSNTokenDeposit = await BosonTKN.new('BosonTokenDeposit', 'BDEP'); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + helpers.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenDeposit.address, + helpers.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setETHLimit(helpers.ETHER_LIMIT); + + await contractVoucherKernel.setComplainPeriod(60); //60 seconds + await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds + } + + // this function is used after each interaction with tokens to clear balances + async function giveAwayToRandom() { + const balanceBuyerFromPayment = await contractBSNTokenPrice.balanceOf( + users.buyer.address + ); + const balanceBuyerFromDesosits = await contractBSNTokenDeposit.balanceOf( + users.buyer.address + ); + + const balanceSellerFromPayment = await contractBSNTokenPrice.balanceOf( + users.seller.address + ); + const balanceSellerFromDesosits = await contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + + const escrowBalanceFromPayment = await contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + const escrowBalanceFromDeposits = await contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + + await contractBSNTokenPrice.transfer( + users.other1.address, + balanceBuyerFromPayment, + {from: users.buyer.address} + ); + await contractBSNTokenDeposit.transfer( + users.other1.address, + balanceBuyerFromDesosits, + {from: users.buyer.address} + ); + await contractBSNTokenPrice.transfer( + users.other1.address, + balanceSellerFromPayment, + {from: users.seller.address} + ); + await contractBSNTokenDeposit.transfer( + users.other1.address, + balanceSellerFromDesosits, + {from: users.seller.address} + ); + await contractBSNTokenPrice.transfer( + users.other1.address, + escrowBalanceFromPayment, + {from: users.deployer.address} + ); + await contractBSNTokenDeposit.transfer( + users.other1.address, + escrowBalanceFromDeposits, + {from: users.deployer.address} + ); + } + + async function withdraw(utils, index, voucherID) { + if (index === 1) { + await utils.pause(users.deployer.address); + return await utils.withdrawWhenPaused(voucherID, users.seller.address); + } else { + return await utils.withdraw(voucherID, users.deployer.address); } - - async function deployContracts() { - contractFundLimitsOracle = await FundLimitsOracle.new() - contractERC1155ERC721 = await ERC1155ERC721.new() - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address) - contractCashier = await Cashier.new(contractVoucherKernel.address); - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - contractBSNTokenPrice = await BosonTKN.new('BosonTokenPrice', 'BPRC'); - contractBSNTokenDeposit = await BosonTKN.new('BosonTokenDeposit', 'BDEP'); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true') - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address) - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address) - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenDeposit.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setETHLimit(helpers.ETHER_LIMIT) - - await contractVoucherKernel.setComplainPeriod(60); //60 seconds - await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds - } - - // this function is used after each interaction with tokens to clear balances - async function giveAwayToRandom() { - const balanceBuyerFromPayment = await contractBSNTokenPrice.balanceOf(Buyer.address) - const balanceBuyerFromDesosits = await contractBSNTokenDeposit.balanceOf(Buyer.address) - - const balanceSellerFromPayment = await contractBSNTokenPrice.balanceOf(Seller.address) - const balanceSellerFromDesosits = await contractBSNTokenDeposit.balanceOf(Seller.address) - - const escrowBalanceFromPayment = await contractBSNTokenPrice.balanceOf(Deployer.address) - const escrowBalanceFromDeposits = await contractBSNTokenDeposit.balanceOf(Deployer.address) - - await contractBSNTokenPrice.transfer(RandomUser.address, balanceBuyerFromPayment, { from: Buyer.address }) - await contractBSNTokenDeposit.transfer(RandomUser.address, balanceBuyerFromDesosits, { from: Buyer.address }) - await contractBSNTokenPrice.transfer(RandomUser.address, balanceSellerFromPayment, { from: Seller.address }) - await contractBSNTokenDeposit.transfer(RandomUser.address, balanceSellerFromDesosits, { from: Seller.address }) - await contractBSNTokenPrice.transfer(RandomUser.address, escrowBalanceFromPayment, { from: Deployer.address }) - await contractBSNTokenDeposit.transfer(RandomUser.address, escrowBalanceFromDeposits, { from: Deployer.address }) - - } - - async function withdraw(utils, index, voucherID) { - if (index == 1) { - await utils.pause(Deployer.address) - return await utils.withdrawWhenPaused(voucherID, Seller.address); - } else { - return await utils.withdraw(voucherID, Deployer.address); + } + + for (let i = 0; i <= PAUSED_WITHPERMIT; i++) { + describe('Withdraw scenarios', async () => { + before(async () => { + await deployContracts(); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + const isPaused = await contractBosonRouter.paused(); + if (isPaused) { + await contractBosonRouter.unpause(); + } + }); + + describe(`ETHETH ${ + i === PAUSED_WITHPERMIT ? PAUSED_LABEL : '' + }`, async () => { + before(async () => { + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + const timestamp = await Utils.getCurrTimestamp(); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_10 + ); + }); + + it('COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit) + .add(new BN(helpers.product_price)) + .add(new BN(helpers.seller_deposit).div(new BN(2))); // 0.3 + 0.04 + 0.025 + const expectedSellerAmount = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmount = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.product_price); // 0.3 + const expectedSellerAmount = new BN(0); // 0 + const expectedEscrowAmount = new BN(helpers.seller_deposit).add( + new BN(helpers.buyer_deposit) + ); // 0.09 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit) + .add(new BN(helpers.product_price)) + .add(new BN(helpers.seller_deposit).div(new BN(2))); // 0.3 + 0.04 + 0.025 + const expectedSellerAmount = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmount = new BN(0); //0 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REFUND->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.product_price); // 0.3 + const expectedSellerAmount = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmount = new BN(helpers.buyer_deposit); // 0.04 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->CANCEL->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit) + .add(new BN(helpers.product_price)) + .add(new BN(helpers.seller_deposit).div(new BN(2))); // 0.3 + 0.04 + 0.025 + const expectedSellerAmount = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmount = new BN(0); // 0 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REDEEM->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerAmount = new BN(helpers.seller_deposit).add( + new BN(helpers.product_price) + ); // 0.35 + const expectedEscrowAmount = new BN(0); // 0 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerAmount = new BN(helpers.product_price); // 0.3 + const expectedEscrowAmount = new BN(helpers.seller_deposit); // 0.05 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerAmount = new BN(helpers.product_price).add( + new BN(helpers.seller_deposit).div(new BN(4)) + ); // 0.3125 + const expectedEscrowAmount = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + + it('COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW', async () => { + const expectedBuyerAmount = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerAmount = new BN(helpers.product_price).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.325 + const expectedEscrowAmount = new BN(0); // 0 + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_to', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerAmount), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerAmount), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmount), + 'Escrow Amount is not as expected' + ); + }); + }); + + describe(`TKNTKN [WITH PERMIT]${ + i === PAUSED_WITHPERMIT ? PAUSED_LABEL : '' + }`, async () => { + let balanceBuyerFromPayment = new BN(0); + let balanceBuyerFromDeposits = new BN(0); + + let balanceSellerFromPayment = new BN(0); + let balanceSellerFromDeposits = new BN(0); + + let escrowBalanceFromPayment = new BN(0); + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + async function getBalancesFromPriceTokenAndDepositToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.buyer.address + ); + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.buyer.address + ); + + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.seller.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); } - } - - for (let i = 0; i <= PAUSED_WITHPERMIT; i++) { - describe('Withdraw scenarios', async () => { - - before(async () => { - await deployContracts(); - }) - - afterEach(async () => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - const isPaused = await contractBosonRouter.paused(); - if (isPaused) { - await contractBosonRouter.unpause(); - } - }) - - describe(`ETH - ETH${i == PAUSED_WITHPERMIT ? PAUSED_LABEL : ''}`, async () => { - - before(async () => { - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - - const timestamp = await Utils.getCurrTimestamp() - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - it("COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.3 + 0.04 + 0.025 - const expectedSellerAmount = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmount = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.product_price) // 0.3 - const expectedSellerAmount = new BN(0) // 0 - const expectedEscrowAmount = new BN(helpers.seller_deposit).add(new BN(helpers.buyer_deposit)) // 0.09 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await timemachine.advanceTimeSeconds(60); - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.3 + 0.04 + 0.025 - const expectedSellerAmount = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmount = new BN(0) //0 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REFUND->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.product_price) // 0.3 - const expectedSellerAmount = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmount = new BN(helpers.buyer_deposit) // 0.04 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->CANCEL->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.3 + 0.04 + 0.025 - const expectedSellerAmount = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmount = new BN(0) // 0 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REDEEM->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerAmount = new BN(helpers.seller_deposit).add(new BN(helpers.product_price)) // 0.35 - const expectedEscrowAmount = new BN(0) // 0 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerAmount = new BN(helpers.product_price) // 0.3 - const expectedEscrowAmount = new BN(helpers.seller_deposit) // 0.05 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerAmount = new BN(helpers.product_price).add(new BN(helpers.seller_deposit).div(new BN(4))) // 0.3125 - const expectedEscrowAmount = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - it("COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW", async () => { - const expectedBuyerAmount = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerAmount = new BN(helpers.product_price).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.325 - const expectedEscrowAmount = new BN(0) // 0 - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_to', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerAmount), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerAmount), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmount), 'Escrow Amount is not as expected') - }); - - - }) - - describe(`TKN - TKN [WITH PERMIT]${i == PAUSED_WITHPERMIT ? PAUSED_LABEL : ''}`, async () => { - let balanceBuyerFromPayment = new BN(0) - let balanceBuyerFromDesosits = new BN(0) - - let balanceSellerFromPayment = new BN(0) - let balanceSellerFromDesosits = new BN(0) - - let escrowBalanceFromPayment = new BN(0) - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - - async function getBalancesFromPiceTokenAndDepositToken() { - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Buyer.address) - balanceBuyerFromDesosits = await utils.contractBSNTokenDeposit.balanceOf(Buyer.address) - - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Seller.address) - balanceSellerFromDesosits = await utils.contractBSNTokenDeposit.balanceOf(Seller.address) - - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, helpers.product_price); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, helpers.buyer_deposit); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - }) - - it("COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60); - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).add(new BN(helpers.buyer_deposit)) // 0.09 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REFUND->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) //// 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit) // 0.05 - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesFromPiceTokenAndDepositToken(); - - //Payments - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PriceTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PriceTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), "Escrow did not get expected tokens from PriceTokenContract"); - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - - }); - - afterEach(async () => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - balanceBuyerFromPayment = new BN(0) - balanceBuyerFromDesosits = new BN(0) - - balanceSellerFromPayment = new BN(0) - balanceSellerFromDesosits = new BN(0) - - escrowBalanceFromPayment = new BN(0) - escrowBalanceFromDeposits = new BN(0) - - cashierPaymentLeft = new BN(0) - cashierDepositLeft = new BN(0) - - await giveAwayToRandom(); - }) - - }) - - describe(`TKN - TKN SAME [WITH PERMIT]${i == PAUSED_WITHPERMIT ? PAUSED_LABEL : ''}`, async () => { - - let balanceBuyer = new BN(0) - let balanceSeller = new BN(0) - let escrowBalance = new BN(0) - let cashierBalance = new BN(0) - - - async function getBalancesFromSameTokenContract() { - balanceBuyer = await utils.contractBSNTokenSAME.balanceOf(Buyer.address) - balanceSeller = await utils.contractBSNTokenSAME.balanceOf(Seller.address) - escrowBalance = await utils.contractBSNTokenSAME.balanceOf(Deployer.address) - cashierBalance = await utils.contractBSNTokenSAME.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN_SAME() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - const tokensToMintBuyer = new BN(helpers.product_price).add(new BN(helpers.buyer_deposit)) - - await utils.mintTokens('contractBSNTokenSAME', Seller.address, tokensToMintSeller) - await utils.mintTokens('contractBSNTokenSAME', Buyer.address, tokensToMintBuyer) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - }) - - afterEach(async () => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - balanceBuyer = new BN(0) - balanceSeller = new BN(0) - escrowBalance = new BN(0) - cashierBalance = new BN(0) - - await giveAwayToRandom(); - }) - - it("COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60); - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).add(new BN(helpers.buyer_deposit)) // 0.09 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REFUND->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedEscrowAmountPrice = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) //// 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit) // 0.05 - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountPrice = new BN(0) - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesFromSameTokenContract(); - - assert.isTrue(balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), "Buyer did not get expected tokens from SameTokenContract"); - assert.isTrue(balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), "Seller did not get expected tokens from SameTokenContract"); - assert.isTrue(escrowBalance.eq(expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit)), "Escrow did not get expected tokens from SameTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierBalance.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - - }); - - }) - - describe(`ETH - TKN [WITH PERMIT]${ i == PAUSED_WITHPERMIT ? PAUSED_LABEL : '' }`, async () => { - let balanceBuyerFromPayment = new BN(0) - let balanceBuyerFromDesosits = new BN(0) - - let balanceSellerFromPayment = new BN(0) - let balanceSellerFromDesosits = new BN(0) - - let escrowBalanceFromPayment = new BN(0) - let escrowBalanceFromDeposits = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - async function getBalancesDepositToken() { - balanceBuyerFromDesosits = await utils.contractBSNTokenDeposit.balanceOf(Buyer.address) - balanceSellerFromDesosits = await utils.contractBSNTokenDeposit.balanceOf(Seller.address) - escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf(Deployer.address) - cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - const supplyQty = 1 - const tokensToMint = new BN(helpers.seller_deposit).mul(new BN(supplyQty)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, helpers.buyer_deposit); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - supplyQty - ) - }) - - afterEach(async () => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - balanceBuyerFromPayment = new BN(0) - balanceBuyerFromDesosits = new BN(0) - - balanceSellerFromPayment = new BN(0) - balanceSellerFromDesosits = new BN(0) - - escrowBalanceFromPayment = new BN(0) - escrowBalanceFromDeposits = new BN(0) - - cashierPaymentLeft = new BN(0) - cashierDepositLeft = new BN(0) - - await giveAwayToRandom(); - }) - - it("COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Buyer.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogAmountDistribution was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60); - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).add(new BN(helpers.buyer_deposit)) // 0.09 - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Buyer.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Buyer.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit) // 0.04 - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Buyer.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesDepositToken(); - - // Payment should have been returned to buyer - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Buyer.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedBuyerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) //// 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesDepositToken(); - - // Payment should have been sent to seller - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit) // 0.05 - - await getBalancesDepositToken(); - - // Payment should have been sent to seller - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesDepositToken(); - - // Payment should have been sent to seller - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerPrice)) + beforeEach(async () => { + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMint = new BN(helpers.seller_deposit).mul( + new BN(supplyQty) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + helpers.product_price + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + helpers.buyer_deposit + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + supplyQty + ); + }); + + it('COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).add(new BN(helpers.buyer_deposit)); // 0.09 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); //// 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit); // 0.05 + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesFromPriceTokenAndDepositToken(); + + //Payments + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PriceTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowAmountPrice), + 'Escrow did not get expected tokens from PriceTokenContract' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + balanceBuyerFromPayment = new BN(0); + balanceBuyerFromDeposits = new BN(0); + + balanceSellerFromPayment = new BN(0); + balanceSellerFromDeposits = new BN(0); + + escrowBalanceFromPayment = new BN(0); + escrowBalanceFromDeposits = new BN(0); + + cashierPaymentLeft = new BN(0); + cashierDepositLeft = new BN(0); + + await giveAwayToRandom(); + }); + }); + + describe(`TKNTKN SAME [WITH PERMIT]${ + i === PAUSED_WITHPERMIT ? PAUSED_LABEL : '' + }`, async () => { + let balanceBuyer = new BN(0); + let balanceSeller = new BN(0); + let escrowBalance = new BN(0); + let cashierBalance = new BN(0); + + async function getBalancesFromSameTokenContract() { + balanceBuyer = await utils.contractBSNTokenSame.balanceOf( + users.buyer.address + ); + balanceSeller = await utils.contractBSNTokenSame.balanceOf( + users.seller.address + ); + escrowBalance = await utils.contractBSNTokenSame.balanceOf( + users.deployer.address + ); + cashierBalance = await utils.contractBSNTokenSame.balanceOf( + utils.contractCashier.address + ); + } - return true - }, "Event LogWithdrawal was not emitted") + beforeEach(async () => { + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKNSame() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMintSeller = new BN(helpers.seller_deposit).mul( + new BN(supplyQty) + ); + const tokensToMintBuyer = new BN(helpers.product_price).add( + new BN(helpers.buyer_deposit) + ); + + await utils.mintTokens( + 'contractBSNTokenSame', + users.seller.address, + tokensToMintSeller + ); + await utils.mintTokens( + 'contractBSNTokenSame', + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + supplyQty + ); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + balanceBuyer = new BN(0); + balanceSeller = new BN(0); + escrowBalance = new BN(0); + cashierBalance = new BN(0); + + await giveAwayToRandom(); + }); + + it('COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).add(new BN(helpers.buyer_deposit)); // 0.09 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedEscrowAmountPrice = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); //// 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit); // 0.05 + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountPrice = new BN(0); + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesFromSameTokenContract(); + + assert.isTrue( + balanceBuyer.eq(expectedBuyerPrice.add(expectedBuyerDeposit)), + 'Buyer did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + balanceSeller.eq(expectedSellerPrice.add(expectedSellerDeposit)), + 'Seller did not get expected tokens from SameTokenContract' + ); + assert.isTrue( + escrowBalance.eq( + expectedEscrowAmountPrice.add(expectedEscrowAmountDeposit) + ), + 'Escrow did not get expected tokens from SameTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierBalance.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + }); + + describe(`ETHTKN [WITH PERMIT]${ + i === PAUSED_WITHPERMIT ? PAUSED_LABEL : '' + }`, async () => { + let balanceBuyerFromDeposits = new BN(0); + let balanceSellerFromDeposits = new BN(0); + let escrowBalanceFromDeposits = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + async function getBalancesDepositToken() { + balanceBuyerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.buyer.address + ); + balanceSellerFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + escrowBalanceFromDeposits = await utils.contractBSNTokenDeposit.balanceOf( + users.deployer.address + ); + cashierDepositLeft = await utils.contractBSNTokenDeposit.balanceOf( + utils.contractCashier.address + ); + } - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesDepositToken(); - - // Payment should have been sent to seller - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerPrice)) - - return true - }, "Event LogWithdrawal was not emitted") - - //Deposits - assert.isTrue(balanceBuyerFromDesosits.eq(expectedBuyerDeposit), "Buyer did not get expected tokens from DepositTokenContract"); - assert.isTrue(balanceSellerFromDesosits.eq(expectedSellerDeposit), "Seller did not get expected tokens from DepositTokenContract"); - assert.isTrue(escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), "Escrow did not get expected tokens from DepositTokenContract"); - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - }) - - describe(`TKN - ETH [WITH PERMIT]${i == PAUSED_WITHPERMIT ? PAUSED_LABEL : ''}`, async () => { - let balanceBuyerFromPayment = new BN(0) - let balanceSellerFromPayment = new BN(0) - let escrowBalanceFromPayment = new BN(0) - - let cashierPaymentLeft = new BN(0) - let cashierDepositLeft = new BN(0) - - async function getBalancesPriceToken() { - balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Buyer.address) - balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf(Seller.address) - escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf(Deployer.address) - cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf(utils.contractCashier.address) - } - - beforeEach(async () => { - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, helpers.product_price); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_1 - ) - }) - - it("COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60); - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(0) - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).add(new BN(helpers.buyer_deposit)) // 0.09 - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.refund(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - - }); - - it("COMMIT->REFUND->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(0) - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit) // 0.04 - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(helpers.product_price) // 0.3 - const expectedSellerPrice = new BN(0) - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been returned to buyer - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerDeposit = new BN(helpers.seller_deposit) // 0.05 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been sent to seller - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit) // 0.04 - const expectedSellerDeposit = new BN(0) - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit) // 0.05 - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been sent to seller - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - await utils.redeem(voucherID, Buyer.address) - await utils.complain(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit).div(new BN(4)) // 0.0125 - - await getBalancesPriceToken(); - - // Payments in TKN - // Payment should have been sent to seller - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - it("COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW", async () => { - const voucherID = await utils.commitToBuy( - Buyer, - Seller, - TOKEN_SUPPLY_ID - ) - - await utils.redeem(voucherID, Buyer.address) - await utils.cancel(voucherID, Seller.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - const withdrawTx = await withdraw(utils, i, voucherID) - - const expectedBuyerPrice = new BN(0) - const expectedSellerPrice = new BN(helpers.product_price) // 0.3 - const expectedEscrowPrice = new BN(0) - const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add(new BN(helpers.seller_deposit).div(new BN(2))) // 0.065 - const expectedSellerDeposit = new BN(helpers.seller_deposit).div(new BN(2)) // 0.025 - const expectedEscrowAmountDeposit = new BN(0) - - await getBalancesPriceToken(); - // Payments in TKN - // Payment should have been sent to seller - assert.isTrue(balanceBuyerFromPayment.eq(expectedBuyerPrice), "Buyer did not get expected tokens from PaymentTokenContract"); - assert.isTrue(balanceSellerFromPayment.eq(expectedSellerPrice), "Seller did not get expected tokens from PaymentTokenContract"); - assert.isTrue(escrowBalanceFromPayment.eq(expectedEscrowPrice), "Escrow did not get expected tokens from PaymentTokenContract"); - - //Deposits in ETH - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - utils.calcTotalAmountToRecipients(ev, distributedAmounts, '_payee', Buyer.address, Seller.address) - return true - }, "Amounts not distributed successfully") - - assert.isTrue(distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), 'Buyer Amount is not as expected') - assert.isTrue(distributedAmounts.sellerAmount.eq(expectedSellerDeposit), 'Seller Amount is not as expected') - assert.isTrue(distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), 'Escrow Amount is not as expected') - - //Cashier Should be Empty - assert.isTrue(cashierPaymentLeft.eq(new BN(0)), "Cashier Contract is not empty"); - assert.isTrue(cashierDepositLeft.eq(new BN(0)), "Cashier Contract is not empty"); - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Event LogAmountDistribution was not emitted") - }); - - afterEach(async () => { - distributedAmounts = { - buyerAmount: new BN(0), - sellerAmount: new BN(0), - escrowAmount: new BN(0) - } - - balanceBuyerFromPayment = new BN(0) - balanceSellerFromPayment = new BN(0) - escrowBalanceFromPayment = new BN(0) - - cashierPaymentLeft = new BN(0) - cashierDepositLeft = new BN(0) - - await giveAwayToRandom(); - }) - }) - - }) - } + beforeEach(async () => { + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + const supplyQty = 1; + const tokensToMint = new BN(helpers.seller_deposit).mul( + new BN(supplyQty) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + helpers.buyer_deposit + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + supplyQty + ); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + balanceBuyerFromDeposits = new BN(0); + balanceSellerFromDeposits = new BN(0); + escrowBalanceFromDeposits = new BN(0); + + cashierPaymentLeft = new BN(0); + cashierDepositLeft = new BN(0); + + await giveAwayToRandom(); + }); + + it('COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.buyer.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).add(new BN(helpers.buyer_deposit)); // 0.09 + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.buyer.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.buyer.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit); // 0.04 + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.buyer.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesDepositToken(); + + // Payment should have been returned to buyer + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.buyer.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedBuyerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); //// 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesDepositToken(); + + // Payment should have been sent to seller + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit); // 0.05 + + await getBalancesDepositToken(); + + // Payment should have been sent to seller + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesDepositToken(); + + // Payment should have been sent to seller + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesDepositToken(); + + // Payment should have been sent to seller + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerPrice)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + + //Deposits + assert.isTrue( + balanceBuyerFromDeposits.eq(expectedBuyerDeposit), + 'Buyer did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + balanceSellerFromDeposits.eq(expectedSellerDeposit), + 'Seller did not get expected tokens from DepositTokenContract' + ); + assert.isTrue( + escrowBalanceFromDeposits.eq(expectedEscrowAmountDeposit), + 'Escrow did not get expected tokens from DepositTokenContract' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + }); + + describe(`TKNETH [WITH PERMIT]${ + i === PAUSED_WITHPERMIT ? PAUSED_LABEL : '' + }`, async () => { + let balanceBuyerFromPayment = new BN(0); + let balanceSellerFromPayment = new BN(0); + let escrowBalanceFromPayment = new BN(0); + + let cashierPaymentLeft = new BN(0); + let cashierDepositLeft = new BN(0); + + async function getBalancesPriceToken() { + balanceBuyerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.buyer.address + ); + balanceSellerFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.seller.address + ); + escrowBalanceFromPayment = await utils.contractBSNTokenPrice.balanceOf( + users.deployer.address + ); + cashierPaymentLeft = await utils.contractBSNTokenPrice.balanceOf( + utils.contractCashier.address + ); + } - describe("[WHEN PAUSED] Seller withdraws deposit locked in escrow", async () => { - - let remQty = 10; - let voucherToBuyBeforeBurn = 5 - let tokensToMintSeller, tokensToMintBuyer - - describe("ETH ETH", () => { - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter); - - const timestamp = await Utils.getCurrTimestamp() - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - after(() => { - remQty = 10; - voucherToBuyBeforeBurn = 5 - }) - - it("[NEGATIVE] Should revert if called when contract is not paused", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should pause the contract", async () => { - // Does nothing in particular .. - // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly - // Pauses contract as below tests are dependant to paused contract - - for (let i = 0; i < voucherToBuyBeforeBurn; i++) { - await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - remQty--; - } - - await contractBosonRouter.pause(); - }) - - it("[NEGATIVE] should revert if not called from the seller", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Seller should be able to withdraw deposits for the remaining QTY in Token Supply", async () => { - let withdrawTx = await contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}); - const expectedSellerDeposit = new BN(helpers.seller_deposit).mul(new BN(remQty)) - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerDeposit)) - - return true - }, "Event LogWithdrawal was not emitted") - }); - - it("Escrow should have correct balance after burning the rest of the supply", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(voucherToBuyBeforeBurn)) - const escrowAmount = await contractCashier.getEscrowAmount(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }); - - it("Remaining QTY for Token Supply should be ZERO", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(TOKEN_SUPPLY_ID, Seller.address) - - assert.isTrue(remainingQtyInContract.eq(new BN(0)), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply", async () => { - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }); - - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMintSeller); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMintBuyer); - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - after(() => { - remQty = 10; - voucherToBuyBeforeBurn = 5 - }) - - it("[NEGATIVE] Should revert if called when contract is not paused", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should pause the contract", async () => { - // Does nothing in particular .. - // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly - // Pauses contract as below tests are dependant to paused contract - - for (let i = 0; i < voucherToBuyBeforeBurn; i++) { - await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - remQty--; - } - - await contractBosonRouter.pause(); - }) - - it("[NEGATIVE] should revert if not called from the seller", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Seller should be able to withdraw deposits for the remaining QTY in Token Supply", async () => { - let withdrawTx = await contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}); - const expectedSellerDeposit = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const internalTx = (await truffleAssert.createTransactionResult(contractBSNTokenDeposit, withdrawTx.tx)) - - truffleAssert.eventEmitted(internalTx, 'Transfer', (ev) => { - assert.equal(ev.to, Seller.address, "Incorrect Payee") - assert.isTrue(ev.value.eq(expectedSellerDeposit)) - - return true - }, "Event Transfer was not emitted") - }); - - it("Escrow should have correct balance after burning the rest of the supply", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(voucherToBuyBeforeBurn)) - const escrowAmount = await contractBSNTokenDeposit.balanceOf(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }); - - it("Remaining QTY for Token Supply should be ZERO", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(TOKEN_SUPPLY_ID, Seller.address) - - assert.isTrue(remainingQtyInContract.eq(new BN(0)), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply", async () => { - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }); - - }) - - describe("TKN_ETH", () => { - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMintBuyer); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - after(() => { - remQty = 10; - voucherToBuyBeforeBurn = 5 - }) - - it("[NEGATIVE] Should revert if called when contract is not paused", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should pause the contract", async () => { - // Does nothing in particular .. - // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly - // Pauses contract as below tests are dependant to paused contract - - for (let i = 0; i < voucherToBuyBeforeBurn; i++) { - await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - remQty--; - } - - await contractBosonRouter.pause(); - }) - - it("[NEGATIVE] should revert if not called from the seller", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Seller should be able to withdraw deposits for the remaining QTY in Token Supply", async () => { - let withdrawTx = await contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}); - const expectedSellerDeposit = new BN(helpers.seller_deposit).mul(new BN(remQty)) - truffleAssert.eventEmitted(withdrawTx, 'LogWithdrawal', (ev) => { - assert.equal(ev._payee, Seller.address, "Incorrect Payee") - assert.isTrue(ev._payment.eq(expectedSellerDeposit)) - - return true - }, "Event LogWithdrawal was not emitted") - }); - - it("Escrow should have correct balance after burning the rest of the supply", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(voucherToBuyBeforeBurn)) - const escrowAmount = await contractCashier.getEscrowAmount(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }); - - it("Remaining QTY for Token Supply should be ZERO", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(TOKEN_SUPPLY_ID, Seller.address) - - assert.isTrue(remainingQtyInContract.eq(new BN(0)), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply", async () => { - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }); - - - }) - - describe("TKN_TKN", () => { - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMintSeller = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - tokensToMintBuyer = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMintSeller); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMintBuyer); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMintBuyer); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - after(() => { - remQty = 10; - voucherToBuyBeforeBurn = 5 - }) - - it("[NEGATIVE] Should revert if called when contract is not paused", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should pause the contract", async () => { - // Does nothing in particular .. - // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly - // Pauses contract as below tests are dependant to paused contract - - for (let i = 0; i < voucherToBuyBeforeBurn; i++) { - await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - remQty--; - } - - await contractBosonRouter.pause(); - }) - - it("[NEGATIVE] should revert if not called from the seller", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Seller should be able to withdraw deposits for the remaining QTY in Token Supply", async () => { - let withdrawTx = await contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}); - const expectedSellerDeposit = new BN(helpers.seller_deposit).mul(new BN(remQty)) - const internalTx = (await truffleAssert.createTransactionResult(contractBSNTokenDeposit, withdrawTx.tx)) - - truffleAssert.eventEmitted(internalTx, 'Transfer', (ev) => { - assert.equal(ev.to, Seller.address, "Incorrect Payee") - assert.isTrue(ev.value.eq(expectedSellerDeposit)) - - return true - }, "Event Transfer was not emitted") - }); - - it("Escrow should have correct balance after burning the rest of the supply", async () => { - const expectedBalance = new BN(helpers.seller_deposit).mul(new BN(voucherToBuyBeforeBurn)) - const escrowAmount = await contractBSNTokenDeposit.balanceOf(Seller.address); - - assert.isTrue(escrowAmount.eq(expectedBalance), "Escrow amount is incorrect") - }); - - it("Remaining QTY for Token Supply should be ZERO", async () => { - let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply(TOKEN_SUPPLY_ID, Seller.address) - - assert.isTrue(remainingQtyInContract.eq(new BN(0)), "Escrow amount is incorrect") - }) - - it("[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply", async () => { - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice", async () => { - await truffleAssert.reverts( - contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, {from: Seller.address}), - truffleAssert.ErrorType.REVERT - ) - }); - - }) - - }) - }) - -}) + beforeEach(async () => { + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + helpers.product_price + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_1 + ); + }); + + it('COMMIT->REFUND->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(0); + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).add(new BN(helpers.buyer_deposit)); // 0.09 + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REFUND->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(0); + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(helpers.buyer_deposit); // 0.04 + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(helpers.product_price); // 0.3 + const expectedSellerPrice = new BN(0); + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been returned to buyer + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerDeposit = new BN(helpers.seller_deposit); // 0.05 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been sent to seller + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit); // 0.04 + const expectedSellerDeposit = new BN(0); + const expectedEscrowAmountDeposit = new BN(helpers.seller_deposit); // 0.05 + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been sent to seller + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->COMPLAIN->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(voucherID, users.buyer.address); + await utils.complain(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(4) + ); // 0.0125 + const expectedEscrowAmountDeposit = new BN( + helpers.seller_deposit + ).div(new BN(4)); // 0.0125 + + await getBalancesPriceToken(); + + // Payments in TKN + // Payment should have been sent to seller + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + it('COMMIT->REDEEM->CANCEL->FINALIZE->WITHDRAW', async () => { + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.redeem(voucherID, users.buyer.address); + await utils.cancel(voucherID, users.seller.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + const withdrawTx = await withdraw(utils, i, voucherID); + + const expectedBuyerPrice = new BN(0); + const expectedSellerPrice = new BN(helpers.product_price); // 0.3 + const expectedEscrowPrice = new BN(0); + const expectedBuyerDeposit = new BN(helpers.buyer_deposit).add( + new BN(helpers.seller_deposit).div(new BN(2)) + ); // 0.065 + const expectedSellerDeposit = new BN(helpers.seller_deposit).div( + new BN(2) + ); // 0.025 + const expectedEscrowAmountDeposit = new BN(0); + + await getBalancesPriceToken(); + // Payments in TKN + // Payment should have been sent to seller + assert.isTrue( + balanceBuyerFromPayment.eq(expectedBuyerPrice), + 'Buyer did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + balanceSellerFromPayment.eq(expectedSellerPrice), + 'Seller did not get expected tokens from PaymentTokenContract' + ); + assert.isTrue( + escrowBalanceFromPayment.eq(expectedEscrowPrice), + 'Escrow did not get expected tokens from PaymentTokenContract' + ); + + //Deposits in ETH + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + utils.calcTotalAmountToRecipients( + ev, + distributedAmounts, + '_payee', + users.buyer.address, + users.seller.address + ); + return true; + }, + 'Amounts not distributed successfully' + ); + + assert.isTrue( + distributedAmounts.buyerAmount.eq(expectedBuyerDeposit), + 'Buyer Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.sellerAmount.eq(expectedSellerDeposit), + 'Seller Amount is not as expected' + ); + assert.isTrue( + distributedAmounts.escrowAmount.eq(expectedEscrowAmountDeposit), + 'Escrow Amount is not as expected' + ); + + //Cashier Should be Empty + assert.isTrue( + cashierPaymentLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + assert.isTrue( + cashierDepositLeft.eq(new BN(0)), + 'Cashier Contract is not empty' + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Event LogAmountDistribution was not emitted' + ); + }); + + afterEach(async () => { + distributedAmounts = { + buyerAmount: new BN(0), + sellerAmount: new BN(0), + escrowAmount: new BN(0), + }; + + balanceBuyerFromPayment = new BN(0); + balanceSellerFromPayment = new BN(0); + escrowBalanceFromPayment = new BN(0); + + cashierPaymentLeft = new BN(0); + cashierDepositLeft = new BN(0); + + await giveAwayToRandom(); + }); + }); + }); + } + + describe('[WHEN PAUSED] Seller withdraws deposit locked in escrow', async () => { + let remQty = 10; + let voucherToBuyBeforeBurn = 5; + let tokensToMintSeller, tokensToMintBuyer; + + describe('ETHETH', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + const timestamp = await Utils.getCurrTimestamp(); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_10 + ); + }); + + after(() => { + remQty = 10; + voucherToBuyBeforeBurn = 5; + }); + + it('[NEGATIVE] Should revert if called when contract is not paused', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should pause the contract', async () => { + // Does nothing in particular .. + // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly + // Pauses contract as below tests are dependant to paused contract + + for (let i = 0; i < voucherToBuyBeforeBurn; i++) { + await utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID); + remQty--; + } + await contractBosonRouter.pause(); + }); + + it('[NEGATIVE] should revert if not called from the seller', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Seller should be able to withdraw deposits for the remaining QTY in Token Supply', async () => { + let withdrawTx = await contractCashier.withdrawDeposits( + TOKEN_SUPPLY_ID, + {from: users.seller.address} + ); + const expectedSellerDeposit = new BN(helpers.seller_deposit).mul( + new BN(remQty) + ); + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerDeposit)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + }); + + it('Escrow should have correct balance after burning the rest of the supply', async () => { + const expectedBalance = new BN(helpers.seller_deposit).mul( + new BN(voucherToBuyBeforeBurn) + ); + const escrowAmount = await contractCashier.getEscrowAmount( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Remaining QTY for Token Supply should be ZERO', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + TOKEN_SUPPLY_ID, + users.seller.address + ); + + assert.isTrue( + remainingQtyInContract.eq(new BN(0)), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply', async () => { + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMintSeller = new BN(helpers.seller_deposit).mul( + new BN(helpers.QTY_10) + ); + tokensToMintBuyer = new BN(helpers.product_price).mul( + new BN(helpers.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMintSeller + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_10 + ); + }); + + after(() => { + remQty = 10; + voucherToBuyBeforeBurn = 5; + }); + + it('[NEGATIVE] Should revert if called when contract is not paused', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should pause the contract', async () => { + // Does nothing in particular .. + // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly + // Pauses contract as below tests are dependant to paused contract + + for (let i = 0; i < voucherToBuyBeforeBurn; i++) { + await utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID); + remQty--; + } + + await contractBosonRouter.pause(); + }); + + it('[NEGATIVE] should revert if not called from the seller', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Seller should be able to withdraw deposits for the remaining QTY in Token Supply', async () => { + let withdrawTx = await contractCashier.withdrawDeposits( + TOKEN_SUPPLY_ID, + {from: users.seller.address} + ); + const expectedSellerDeposit = new BN(helpers.seller_deposit).mul( + new BN(remQty) + ); + const internalTx = await truffleAssert.createTransactionResult( + contractBSNTokenDeposit, + withdrawTx.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'Transfer', + (ev) => { + assert.equal(ev.to, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev.value.eq(expectedSellerDeposit)); + + return true; + }, + 'Event Transfer was not emitted' + ); + }); + + it('Escrow should have correct balance after burning the rest of the supply', async () => { + const expectedBalance = new BN(helpers.seller_deposit).mul( + new BN(voucherToBuyBeforeBurn) + ); + const escrowAmount = await contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Remaining QTY for Token Supply should be ZERO', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + TOKEN_SUPPLY_ID, + users.seller.address + ); + + assert.isTrue( + remainingQtyInContract.eq(new BN(0)), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply', async () => { + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMintBuyer = new BN(helpers.product_price).mul( + new BN(helpers.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_10 + ); + }); + + after(() => { + remQty = 10; + voucherToBuyBeforeBurn = 5; + }); + + it('[NEGATIVE] Should revert if called when contract is not paused', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should pause the contract', async () => { + // Does nothing in particular .. + // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly + // Pauses contract as below tests are dependant to paused contract + + for (let i = 0; i < voucherToBuyBeforeBurn; i++) { + await utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID); + remQty--; + } + + await contractBosonRouter.pause(); + }); + + it('[NEGATIVE] should revert if not called from the seller', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Seller should be able to withdraw deposits for the remaining QTY in Token Supply', async () => { + let withdrawTx = await contractCashier.withdrawDeposits( + TOKEN_SUPPLY_ID, + {from: users.seller.address} + ); + const expectedSellerDeposit = new BN(helpers.seller_deposit).mul( + new BN(remQty) + ); + truffleAssert.eventEmitted( + withdrawTx, + 'LogWithdrawal', + (ev) => { + assert.equal(ev._payee, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev._payment.eq(expectedSellerDeposit)); + + return true; + }, + 'Event LogWithdrawal was not emitted' + ); + }); + + it('Escrow should have correct balance after burning the rest of the supply', async () => { + const expectedBalance = new BN(helpers.seller_deposit).mul( + new BN(voucherToBuyBeforeBurn) + ); + const escrowAmount = await contractCashier.getEscrowAmount( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Remaining QTY for Token Supply should be ZERO', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + TOKEN_SUPPLY_ID, + users.seller.address + ); + + assert.isTrue( + remainingQtyInContract.eq(new BN(0)), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply', async () => { + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMintSeller = new BN(helpers.seller_deposit).mul( + new BN(helpers.QTY_10) + ); + tokensToMintBuyer = new BN(helpers.product_price).mul( + new BN(helpers.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMintSeller + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMintBuyer + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMintBuyer + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + helpers.SECONDS_IN_DAY, + helpers.seller_deposit, + helpers.QTY_10 + ); + }); + + after(() => { + remQty = 10; + voucherToBuyBeforeBurn = 5; + }); + + it('[NEGATIVE] Should revert if called when contract is not paused', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should pause the contract', async () => { + // Does nothing in particular .. + // Buys 5 vouchers before pausing the contract so as to test if the locked seller deposit should be returned correctly + // Pauses contract as below tests are dependant to paused contract + + for (let i = 0; i < voucherToBuyBeforeBurn; i++) { + await utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID); + remQty--; + } + + await contractBosonRouter.pause(); + }); + + it('[NEGATIVE] should revert if not called from the seller', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Seller should be able to withdraw deposits for the remaining QTY in Token Supply', async () => { + let withdrawTx = await contractCashier.withdrawDeposits( + TOKEN_SUPPLY_ID, + {from: users.seller.address} + ); + const expectedSellerDeposit = new BN(helpers.seller_deposit).mul( + new BN(remQty) + ); + const internalTx = await truffleAssert.createTransactionResult( + contractBSNTokenDeposit, + withdrawTx.tx + ); + + truffleAssert.eventEmitted( + internalTx, + 'Transfer', + (ev) => { + assert.equal(ev.to, users.seller.address, 'Incorrect Payee'); + assert.isTrue(ev.value.eq(expectedSellerDeposit)); + + return true; + }, + 'Event Transfer was not emitted' + ); + }); + + it('Escrow should have correct balance after burning the rest of the supply', async () => { + const expectedBalance = new BN(helpers.seller_deposit).mul( + new BN(voucherToBuyBeforeBurn) + ); + const escrowAmount = await contractBSNTokenDeposit.balanceOf( + users.seller.address + ); + + assert.isTrue( + escrowAmount.eq(expectedBalance), + 'Escrow amount is incorrect' + ); + }); + + it('Remaining QTY for Token Supply should be ZERO', async () => { + let remainingQtyInContract = await contractVoucherKernel.getRemQtyForSupply( + TOKEN_SUPPLY_ID, + users.seller.address + ); + + assert.isTrue( + remainingQtyInContract.eq(new BN(0)), + 'Escrow amount is incorrect' + ); + }); + + it('[NEGATIVE] Buyer should not be able to commit to buy anything from the burnt supply', async () => { + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Seller should not be able withdraw its deposit for the Token Supply twice', async () => { + await truffleAssert.reverts( + contractCashier.withdrawDeposits(TOKEN_SUPPLY_ID, { + from: users.seller.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); +}); diff --git a/test/4_Boson_Token.js b/test/4_Boson_Token.js index 0c11475f..4d008177 100644 --- a/test/4_Boson_Token.js +++ b/test/4_Boson_Token.js @@ -1,343 +1,425 @@ -const chai = require('chai') -const ethers = require('ethers') -const assert = chai.assert const truffleAssert = require('truffle-assertions'); - -const { ecsign } = require('ethereumjs-util'); - -const BN = web3.utils.BN -const BosonToken = artifacts.require("BosonTokenPrice") -const helpers = require('../testHelpers/constants') - -const { - hexlify, - getAddress, - keccak256, - defaultAbiCoder, - toUtf8Bytes, - solidityPack -} = require('ethers').utils; - -const { - PERMIT_TYPEHASH, - toWei, - getApprovalDigest -} = require('../testHelpers/permitUtils'); - -const config = require('../testHelpers/config.json') - -contract('Boson token', accounts => { - - let BosonTokenContract, bosonContractAddress; - - let Deployer = config.accounts.deployer - let Seller = config.accounts.seller - let Buyer = config.accounts.buyer - let Attacker = config.accounts.attacker //0x56A32fFf5E5A8B40d6A21538579fB8922DF5258c - let RandomUser = config.accounts.randomUser - - beforeEach(async () => { - - BosonTokenContract = await BosonToken.new('BOSON TOKEN', 'BSNT') - bosonContractAddress = BosonTokenContract.address - }) - - describe('Boson Token', async () => { - - const ADMIN_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("ADMIN_ROLE")) - const MINTER_ROLE = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("MINTER_ROLE")) - - it("Only Deployer Should have admin and minter rights initially ", async () => { - - const buyerIsAdmin = await BosonTokenContract.hasRole(ADMIN_ROLE, Buyer.address); - const buyerIsMinter = await BosonTokenContract.hasRole(MINTER_ROLE, Buyer.address); - const deployerIsAdmin = await BosonTokenContract.hasRole(ADMIN_ROLE, Deployer.address); - const deployerIsMinter = await BosonTokenContract.hasRole(MINTER_ROLE, Deployer.address); - - assert.isTrue(deployerIsAdmin) - assert.isTrue(deployerIsMinter) - - assert.isFalse(buyerIsAdmin) - assert.isFalse(buyerIsMinter) - }) - - it("should revert if unauthorized address tries to mint tokens ", async () => { - await truffleAssert.reverts(BosonTokenContract.mint(Seller.address, 1000, { from: Attacker.address} )) - }) - - it("should grant minter role to address", async () => { - await BosonTokenContract.grantMinterRole(Buyer.address); - - const buyerIsMinter = await BosonTokenContract.hasRole(MINTER_ROLE, Buyer.address); - - assert.isTrue(buyerIsMinter) - }) - - it("should mint tokens after minter role is granted", async () => { - const tokensToMint = 1000; - const randomAddress = accounts[7]; - let addressBalance = await BosonTokenContract.balanceOf(randomAddress) - - assert.equal(addressBalance, 0, 'address has more tokens than expected') - - await BosonTokenContract.mint(randomAddress, 1000); - - addressBalance = await BosonTokenContract.balanceOf(randomAddress) - assert.equal(addressBalance, tokensToMint, "minted tokens do not correspond to address balance") +const ethers = require('ethers'); +const {assert} = require('chai'); +const {ecsign} = require('ethereumjs-util'); + +const constants = require('../testHelpers/constants'); +const Users = require('../testHelpers/users'); +const {toWei, getApprovalDigest} = require('../testHelpers/permitUtils'); + +const BosonToken = artifacts.require('BosonTokenPrice'); + +contract('Boson token', (addresses) => { + const users = new Users(addresses); + + let BosonTokenContract, bosonContractAddress; + + beforeEach(async () => { + BosonTokenContract = await BosonToken.new('BOSON TOKEN', 'BSNT'); + bosonContractAddress = BosonTokenContract.address; + }); + + describe('Boson Token', async () => { + const ADMIN_ROLE = ethers.utils.keccak256( + ethers.utils.toUtf8Bytes('ADMIN_ROLE') + ); + const MINTER_ROLE = ethers.utils.keccak256( + ethers.utils.toUtf8Bytes('MINTER_ROLE') + ); + + it('Only Deployer Should have admin and minter rights initially ', async () => { + const buyerIsAdmin = await BosonTokenContract.hasRole( + ADMIN_ROLE, + users.buyer.address + ); + const buyerIsMinter = await BosonTokenContract.hasRole( + MINTER_ROLE, + users.buyer.address + ); + const deployerIsAdmin = await BosonTokenContract.hasRole( + ADMIN_ROLE, + users.deployer.address + ); + const deployerIsMinter = await BosonTokenContract.hasRole( + MINTER_ROLE, + users.deployer.address + ); + + assert.isTrue(deployerIsAdmin); + assert.isTrue(deployerIsMinter); + + assert.isFalse(buyerIsAdmin); + assert.isFalse(buyerIsMinter); + }); + + it('should revert if unauthorized address tries to mint tokens ', async () => { + await truffleAssert.reverts( + BosonTokenContract.mint(users.seller.address, 1000, { + from: users.attacker.address, }) - - describe("[PERMIT]", async () => { - it("Should approve successfully", async () => { - const balanceToApprove = 1200; - const nonce = await BosonTokenContract.nonces(Buyer.address) - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - bosonContractAddress, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await BosonTokenContract.permit( - Buyer.address, - bosonContractAddress, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ) - - const tokenAllowanceFromBuyer = await BosonTokenContract.allowance(Buyer.address, bosonContractAddress); - - assert.equal(tokenAllowanceFromBuyer, balanceToApprove, "Allowance does not equal the amount provided!") - + ); + }); + + it('should grant minter role to address', async () => { + await BosonTokenContract.grantMinterRole(users.buyer.address); + + const buyerIsMinter = await BosonTokenContract.hasRole( + MINTER_ROLE, + users.buyer.address + ); + + assert.isTrue(buyerIsMinter); + }); + + it('should mint tokens after minter role is granted', async () => { + const tokensToMint = 1000; + let addressBalance = await BosonTokenContract.balanceOf( + users.other2.address + ); + + assert.equal(addressBalance, 0, 'address has more tokens than expected'); + + await BosonTokenContract.mint(users.other2.address, 1000); + + addressBalance = await BosonTokenContract.balanceOf(users.other2.address); + + assert.equal( + addressBalance, + tokensToMint, + 'minted tokens do not correspond to address balance' + ); + }); + + describe('[PERMIT]', async () => { + it('Should approve successfully', async () => { + const balanceToApprove = 1200; + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + bosonContractAddress, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await BosonTokenContract.permit( + users.buyer.address, + bosonContractAddress, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ); + + const tokenAllowanceFromBuyer = await BosonTokenContract.allowance( + users.buyer.address, + bosonContractAddress + ); + + assert.equal( + tokenAllowanceFromBuyer, + balanceToApprove, + 'Allowance does not equal the amount provided!' + ); + }); + + it('should revert if incorrect nonce is provided', async () => { + const balanceToApprove = 1200; + const nonce = 7000000; + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + bosonContractAddress, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + BosonTokenContract.permit( + users.buyer.address, + bosonContractAddress, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('should revert if incorrect balance is provided', async () => { + const balanceToApprove = 1200; + const incorrectBalance = 1500; + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + bosonContractAddress, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + BosonTokenContract.permit( + users.buyer.address, + bosonContractAddress, + incorrectBalance, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('should revert if incorrect recipient is provided', async () => { + const incorrectAddress = addresses[6]; + const balanceToApprove = 1200; + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + bosonContractAddress, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + BosonTokenContract.permit( + users.buyer.address, + incorrectAddress, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('should revert if owner is incorrect', async () => { + const incorrectSender = users.other1.address; + const balanceToApprove = 1200; + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + bosonContractAddress, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await truffleAssert.reverts( + BosonTokenContract.permit( + incorrectSender, + bosonContractAddress, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should transfer tokens on behalf of the buyer', async () => { + // Buyer has 1000 preminted tokens + const tokensToMint = 1000; + await BosonTokenContract.mint(users.buyer.address, tokensToMint, { + from: users.deployer.address, + }); + const balanceToApprove = 200; + const tokensToSend = 200; + + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + users.deployer.address, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await BosonTokenContract.permit( + users.buyer.address, + users.deployer.address, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ); + + let sellerBalance = await BosonTokenContract.balanceOf( + users.seller.address + ); + assert.equal(sellerBalance.toString(), 0, 'Seller has funds'); + + await BosonTokenContract.transferFrom( + users.buyer.address, + users.seller.address, + tokensToSend, + { + from: users.deployer.address, + } + ); + + sellerBalance = await BosonTokenContract.balanceOf( + users.seller.address + ); + + assert.equal( + sellerBalance.toString(), + tokensToSend, + 'Seller has different amount of tokens' + ); + }); + + it('Should revert if attacker tries to transfer', async () => { + // Buyer has 1000 preminted tokens + const tokensToMint = 1000; + await BosonTokenContract.mint(users.buyer.address, tokensToMint, { + from: users.deployer.address, + }); + const balanceToApprove = 200; + const tokensToSend = 200; + + const nonce = await BosonTokenContract.nonces(users.buyer.address); + const deadline = toWei(1); + const digest = await getApprovalDigest( + BosonTokenContract, + users.buyer.address, + users.deployer.address, + balanceToApprove, + nonce, + deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(users.buyer.privateKey.slice(2), 'hex') + ); + + await BosonTokenContract.permit( + users.buyer.address, + users.deployer.address, + balanceToApprove, + deadline, + v, + r, + s, + {from: users.buyer.address} + ); + + await truffleAssert.reverts( + BosonTokenContract.transferFrom( + users.buyer.address, + users.seller.address, + tokensToSend, + { + from: users.attacker.address, + } + ) + ); + }); + }); + + describe('[OWNERSHIP]', async () => { + it('Deployer should be owner initially', async () => { + const owner = await BosonTokenContract.owner(); + + assert.equal(owner, users.deployer.address, 'Deployer is not an owner'); + }); + + it('Should transfer ownership', async () => { + await BosonTokenContract.transferOwnership(users.other1.address); + const newOwner = await BosonTokenContract.owner(); + + assert.equal( + newOwner, + users.other1.address, + 'ownership has not been transferred' + ); + }); + + it('Should renounce ownership', async () => { + const owner = await BosonTokenContract.owner(); + + await BosonTokenContract.renounceOwnership({from: owner}); + + const newOwner = await BosonTokenContract.owner(); + + assert.equal( + newOwner, + constants.ZERO_ADDRESS, + 'ownership has not been renounced' + ); + }); + + it( + '[NEGATIVE] Should revert if calling a function which is ' + + 'allowed only from owner', + async () => { + await truffleAssert.reverts( + BosonTokenContract.grantMinterRole(users.buyer.address, { + from: users.attacker.address, }) - - it("should revert if incorrect nonce is provided", async () => { - - const balanceToApprove = 1200; - const nonce = 7000000; - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - bosonContractAddress, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await truffleAssert.reverts(BosonTokenContract.permit( - Buyer.address, - bosonContractAddress, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ), truffleAssert.ErrorType.REVERT) - }) - - it("should revert if incorrect balance is provided", async () => { - - const balanceToApprove = 1200; - const incorrectBalance = 1500; - const nonce = await BosonTokenContract.nonces(Buyer.address); - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - bosonContractAddress, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await truffleAssert.reverts(BosonTokenContract.permit( - Buyer.address, - bosonContractAddress, - incorrectBalance, - deadline, - v, r, s, - { from: Buyer.address } - ), truffleAssert.ErrorType.REVERT) - }) - - it("should revert if incorrect recipient is provided", async () => { - const incorrectAddress = accounts[6] - const balanceToApprove = 1200; - const nonce = await BosonTokenContract.nonces(Buyer.address); - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - bosonContractAddress, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await truffleAssert.reverts(BosonTokenContract.permit( - Buyer.address, - incorrectAddress, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ), truffleAssert.ErrorType.REVERT) - }) - - it("should revert if owner is incorrect", async () => { - const incorrectSender = accounts[6] - const balanceToApprove = 1200; - const nonce = await BosonTokenContract.nonces(Buyer.address); - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - bosonContractAddress, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await truffleAssert.reverts(BosonTokenContract.permit( - incorrectSender, - bosonContractAddress, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ), truffleAssert.ErrorType.REVERT) - }) - - it("Should transfer tokens on behalf of the buyer", async() => { - //Buyer has 1000 preminted tokens - const tokensToMint = 1000 - await BosonTokenContract.mint(Buyer.address, tokensToMint, { from: Deployer.address }); - const balanceToApprove = 200; - const tokensToSend = 200; - - const nonce = await BosonTokenContract.nonces(Buyer.address) - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - Deployer.address, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await BosonTokenContract.permit( - Buyer.address, - Deployer.address, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ) - - - let sellerBalance = await BosonTokenContract.balanceOf(Seller.address) - assert.equal(sellerBalance.toString(), 0, 'Seller has funds') - - await BosonTokenContract.transferFrom(Buyer.address, Seller.address, tokensToSend, { from: Deployer.address}); - - sellerBalance = await BosonTokenContract.balanceOf(Seller.address) - assert.equal(sellerBalance.toString(), tokensToSend, 'Seller has different amount of tokens') - - }) - - it("Should revert if attacker tries to transfer", async () => { - //Buyer has 1000 preminted tokens - const tokensToMint = 1000 - await BosonTokenContract.mint(Buyer.address, tokensToMint, { from: Deployer.address }); - const balanceToApprove = 200; - const tokensToSend = 200; - - const nonce = await BosonTokenContract.nonces(Buyer.address) - const deadline = toWei(1); - const digest = await getApprovalDigest( - BosonTokenContract, - Buyer.address, - Deployer.address, - balanceToApprove, - nonce, - deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(Buyer.pk.slice(2), 'hex')); - - await BosonTokenContract.permit( - Buyer.address, - Deployer.address, - balanceToApprove, - deadline, - v, r, s, - { from: Buyer.address } - ) - - await truffleAssert.reverts(BosonTokenContract.transferFrom(Buyer.address, Seller.address, tokensToSend, { from: Attacker.address })); - - }) - }) - - describe("[OWNERSHIP]", async () => { - - it("Deployer should be owner initially", async () => { - const owner = await BosonTokenContract.owner() - assert.equal(owner, Deployer.address, "Deployer is not an owner") - }) - - it("Should transfer ownership", async () => { - await BosonTokenContract.transferOwnership(RandomUser.address) - const newOwner = await BosonTokenContract.owner() - - assert.equal(newOwner, RandomUser.address, "ownership has not been transferred") - }) - - it("Should renounce ownership", async () => { - const owner = await BosonTokenContract.owner() - - await BosonTokenContract.renounceOwnership({ from: owner}) - - const newOwner = await BosonTokenContract.owner() - - assert.equal(newOwner, helpers.ZERO_ADDRESS, "ownership has not been renounced") - }) - - it("[NEGATIVE] Should revert if calling a function which is allowed only from owner", async () => { - await truffleAssert.reverts(BosonTokenContract.grantMinterRole(Buyer.address, {from: Attacker.address})); - }) - }) - }) - -}) \ No newline at end of file + ); + } + ); + }); + }); +}); diff --git a/test/5_pausing_contracts.js b/test/5_pausing_contracts.js index 7cad378e..12e72213 100644 --- a/test/5_pausing_contracts.js +++ b/test/5_pausing_contracts.js @@ -1,1299 +1,1957 @@ -const chai = require('chai') -const assert = chai.assert - -const BN = web3.utils.BN -const UtilsBuilder = require('../testHelpers/utilsBuilder') -const Utils = require('../testHelpers/utils') -let utils - -const ERC1155ERC721 = artifacts.require("ERC1155ERC721") -const VoucherKernel = artifacts.require("VoucherKernel") -const Cashier = artifacts.require("Cashier") -const BosonRouter = artifacts.require("BosonRouter") -const BosonTKN = artifacts.require("BosonTokenPrice") -const FundLimitsOracle = artifacts.require('FundLimitsOracle'); - -const helpers = require("../testHelpers/constants") -const timemachine = require('../testHelpers/timemachine') -const truffleAssert = require('truffle-assertions') -const config = require('../testHelpers/config.json') - -let TOKEN_SUPPLY_ID -let VOUCHER_ID - -contract("Cashier && VK", async accounts => { - - let Deployer = config.accounts.deployer - let Seller = config.accounts.seller - let Buyer = config.accounts.buyer - let Attacker = config.accounts.attacker - - let contractERC1155ERC721, +const {assert} = require('chai'); +const truffleAssert = require('truffle-assertions'); + +const constants = require('../testHelpers/constants'); +const timemachine = require('../testHelpers/timemachine'); +const Users = require('../testHelpers/users'); +const UtilsBuilder = require('../testHelpers/utilsBuilder'); +const Utils = require('../testHelpers/utils'); + +const ERC1155ERC721 = artifacts.require('ERC1155ERC721'); +const VoucherKernel = artifacts.require('VoucherKernel'); +const Cashier = artifacts.require('Cashier'); +const BosonRouter = artifacts.require('BosonRouter'); +const BosonTKN = artifacts.require('BosonTokenPrice'); +const FundLimitsOracle = artifacts.require('FundLimitsOracle'); + +const BN = web3.utils.BN; + +let utils; + +let TOKEN_SUPPLY_ID; +let VOUCHER_ID; + +contract('Cashier && VK', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit, + contractFundLimitsOracle; + + let tokensToMint; + let timestamp; + + async function deployContracts() { + contractFundLimitsOracle = await FundLimitsOracle.new(); + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + contractBSNTokenPrice = await BosonTKN.new('BosonTokenPrice', 'BPRC'); + contractBSNTokenDeposit = await BosonTKN.new('BosonTokenDeposit', 'BDEP'); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + + await contractVoucherKernel.setComplainPeriod(60); //60 seconds + await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds + + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + constants.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenDeposit.address, + constants.TOKEN_LIMIT + ); + await contractFundLimitsOracle.setETHLimit(constants.ETHER_LIMIT); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, contractVoucherKernel, contractCashier, - contractBosonRouter, - contractBSNTokenPrice, - contractBSNTokenDeposit, - contractFundLimitsOracle - - let tokensToMint - let timestamp - - async function deployContracts() { - - contractFundLimitsOracle = await FundLimitsOracle.new() - contractERC1155ERC721 = await ERC1155ERC721.new() - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address) - contractCashier = await Cashier.new(contractVoucherKernel.address) - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - contractBSNTokenPrice = await BosonTKN.new('BosonTokenPrice', 'BPRC'); - contractBSNTokenDeposit = await BosonTKN.new('BosonTokenDeposit', 'BDEP'); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true') - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address) - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address) - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setComplainPeriod(60); //60 seconds - await contractVoucherKernel.setCancelFaultPeriod(60); //60 seconds - - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenDeposit.address, helpers.TOKEN_LIMIT) - await contractFundLimitsOracle.setETHLimit(helpers.ETHER_LIMIT) - - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter) - timestamp = await Utils.getCurrTimestamp() - } - - describe('Pausing Scenarios', function () { - - describe("BOSON ROUTER", () => { - - describe("COMMON PAUSING", () => { - before(async () => { - await deployContracts(); - }) - - it("Should not be paused on deployment", async () => { - const isPaused = await contractBosonRouter.paused(); - assert.isFalse(isPaused) - }); - - it("Owner should pause the contract", async () => { - await contractBosonRouter.pause(); - - const isPaused = await contractBosonRouter.paused(); - assert.isTrue(isPaused) - }); - - it("Owner should unpause the contract", async () => { - await contractBosonRouter.pause(); - await contractBosonRouter.unpause(); - - const isPaused = await contractBosonRouter.paused(); - assert.isFalse(isPaused) - }); - - it("[NEGATIVE] Attacker should not be able to pause the contract", async () => { - await truffleAssert.reverts( - contractBosonRouter.pause({ from: Attacker.address }), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Attacker should not be able to unpause the contract", async () => { - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - contractBosonRouter.unpause({ from: Attacker.address }), - truffleAssert.ErrorType.REVERT - ) - }); - }) - - describe("ETH_ETH", () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter); - - }) - - it("[NEGATIVE] Should not create voucher supply when contract is paused", async () => { - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should create voucher supply when contract is unpaused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - assert.isNotEmpty(TOKEN_SUPPLY_ID) - }) - - it("[NEGATIVE] Should not create voucherID from Buyer when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - - before(async () => { - - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - }) - - it("[NEGATIVE] Should not create voucher supply when contract is paused", async () => { - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should create voucher supply when contract is unpaused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - assert.isNotEmpty(TOKEN_SUPPLY_ID) - }) - - it("[NEGATIVE] Should not create voucherID for Buyer when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_ETH", () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("[NEGATIVE] Should not create voucher supply when contract is paused", async () => { - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should create voucher supply when contract is unpaused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - assert.isNotEmpty(TOKEN_SUPPLY_ID) - }) - - it("[NEGATIVE] Should not create voucherID for Buyer when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_TKN", () => { - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - tokensToMint = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - }) - - - it("[NEGATIVE] Should not create voucher supply when contract is paused", async () => { - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1), - truffleAssert.ErrorType.REVERT - ) - }) - - it("Should create voucher supply when contract is unpaused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - assert.isNotEmpty(TOKEN_SUPPLY_ID) - }) - - it("[NEGATIVE] Should not create voucherID for Buyer when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - }) - - }) - - describe("VOUCHER KERNEL", () => { - - describe("COMMON PAUSING", () => { - before(async () => { - await deployContracts(); - }) - - it("Should not be paused on deployment", async () => { - const isPaused = await contractVoucherKernel.paused(); - assert.isFalse(isPaused) - }); - - it("Should be paused from BR", async () => { - await contractBosonRouter.pause(); - - const isPaused = await contractVoucherKernel.paused(); - assert.isTrue(isPaused) - }); - - it("Should be unpaused from BR", async () => { - await contractBosonRouter.pause(); - await contractBosonRouter.unpause(); - - const isPaused = await contractVoucherKernel.paused(); - assert.isFalse(isPaused) - }); - - it("[NEGATIVE] Pause should not be called directly", async () => { - await truffleAssert.reverts( - contractVoucherKernel.pause(), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Unpause should not be called directly", async () => { - await truffleAssert.reverts( - contractVoucherKernel.unpause(), - truffleAssert.ErrorType.REVERT - ) - }); - - }) - - describe("ETH_ETH", () => { - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter); - - const timestamp = await Utils.getCurrTimestamp() - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - it("[NEGATIVE] Should not process refund when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.refund(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process complain when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.complain(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process redeem when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.redeem(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process cancel when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.cancel(VOUCHER_ID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - - before(async () => { - await deployContracts() - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_10) - - }) - - it("[NEGATIVE] Should not process refund when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.refund(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process complain when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.complain(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process redeem when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.redeem(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process cancel when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.cancel(VOUCHER_ID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - - }) - - describe("TKN_ETH", () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("[NEGATIVE] Should not process refund when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.refund(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process complain when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.complain(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process redeem when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.redeem(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process cancel when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.cancel(VOUCHER_ID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_TKN", () => { - - before(async () => { - - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("[NEGATIVE] Should not process refund when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.refund(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process complain when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.complain(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process redeem when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.redeem(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process cancel when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.cancel(VOUCHER_ID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_TKN_SAME", () => { - - before(async () => { - - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN_SAME() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenSAME', Seller.address, tokensToMint) - await utils.mintTokens('contractBSNTokenSAME', Buyer.address, tokensToMint) - - TOKEN_SUPPLY_ID = await utils.createOrder( - Seller, - timestamp, - timestamp + helpers.SECONDS_IN_DAY, - helpers.seller_deposit, - helpers.QTY_10 - ) - }) - - it("[NEGATIVE] Should not process refund when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.refund(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process complain when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await utils.refund(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.complain(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process redeem when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.redeem(VOUCHER_ID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] Should not process cancel when paused", async () => { - VOUCHER_ID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID); - await utils.redeem(VOUCHER_ID, Buyer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.cancel(VOUCHER_ID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - }) - }) - - }) - - describe("CASHIER", () => { - - describe("COMMON PAUSING", () => { - before(async () => { - await deployContracts(); - }) - - it("Should not be paused on deployment", async () => { - const isPaused = await contractCashier.paused(); - assert.isFalse(isPaused) - }); - - it("Should be paused from BR", async () => { - await contractBosonRouter.pause(); - - const isPaused = await contractCashier.paused(); - assert.isTrue(isPaused) - }); - - it("Should be unpaused from BR", async () => { - await contractBosonRouter.pause(); - await contractBosonRouter.unpause(); - - const isPaused = await contractCashier.paused(); - assert.isFalse(isPaused) - }); - - it("[NEGATIVE] Pause should not be called directly", async () => { - await truffleAssert.reverts( - contractCashier.pause(), - truffleAssert.ErrorType.REVERT - ) - }); - - it("[NEGATIVE] Unpause should not be called directly", async () => { - await truffleAssert.reverts( - contractCashier.unpause(), - truffleAssert.ErrorType.REVERT - ) - }); - - }) - - describe("ETH_ETH", () => { - - before(async () => { - - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ETH_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter); - }) - - it("[NEGATIVE] Should not process withdrawals when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdraw(voucherID, Deployer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Buyer should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Buyer.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Seller should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Seller.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("[WITH PERMIT]", () => { - - describe("ETH_TKN", () => { - - before(async () => { - await deployContracts(); - - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .ETH_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - - }) - - it("[NEGATIVE] Should not process withdrawals when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdraw(voucherID, Deployer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Buyer should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Buyer.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Seller should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Seller.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("TKN_ETH", () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_ETH() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, '') - - const timestamp = await Utils.getCurrTimestamp() - - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - }) - - it("[NEGATIVE] Should not process withdrawals when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdraw(voucherID, Deployer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Buyer should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Buyer.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Seller should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Seller.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - }) - - describe("TKN_TKN", () => { - - before(async () => { - await deployContracts(); - utils = UtilsBuilder - .NEW() - .ERC20withPermit() - .TKN_TKN() - .build(contractERC1155ERC721, contractVoucherKernel, contractCashier, contractBosonRouter, contractBSNTokenPrice, contractBSNTokenDeposit) - - tokensToMint = new BN(helpers.seller_deposit).mul(new BN(helpers.QTY_10)) - tokensToMint = new BN(helpers.product_price).mul(new BN(helpers.QTY_10)) - - await utils.mintTokens('contractBSNTokenDeposit', Seller.address, tokensToMint); - await utils.mintTokens('contractBSNTokenPrice', Buyer.address, tokensToMint); - await utils.mintTokens('contractBSNTokenDeposit', Buyer.address, tokensToMint); - }) - - it("[NEGATIVE] Should not process withdrawals when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdraw(voucherID, Deployer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Buyer should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Buyer.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Buyer.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("withdrawWhenPaused - Seller should be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - const withdrawTx = await utils.withdrawWhenPaused(voucherID, Seller.address) - - truffleAssert.eventEmitted(withdrawTx, 'LogAmountDistribution', (ev) => { - return true - }, "Amounts not distributed successfully") - }) - - it("[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Seller.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await contractBosonRouter.pause(); - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - it("[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused", async () => { - TOKEN_SUPPLY_ID = await utils.createOrder(Seller, timestamp, timestamp + helpers.SECONDS_IN_DAY, helpers.seller_deposit, helpers.QTY_1) - - const voucherID = await utils.commitToBuy(Buyer, Seller, TOKEN_SUPPLY_ID) - await utils.refund(voucherID, Buyer.address) - - await timemachine.advanceTimeSeconds(60) - await utils.finalize(voucherID, Deployer.address) - - await truffleAssert.reverts( - utils.withdrawWhenPaused(voucherID, Attacker.address), - truffleAssert.ErrorType.REVERT - ) - }) - - - }) - }) - }) - - afterEach(async () => { - const isPaused = await contractBosonRouter.paused(); - if (isPaused) { - await contractBosonRouter.unpause(); - } - }) - }) -}) - + contractBosonRouter + ); + timestamp = await Utils.getCurrTimestamp(); + } + + describe('Pausing Scenarios', function () { + describe('BOSON ROUTER', () => { + describe('COMMON PAUSING', () => { + before(async () => { + await deployContracts(); + }); + + it('Should not be paused on deployment', async () => { + const isPaused = await contractBosonRouter.paused(); + assert.isFalse(isPaused); + }); + + it('Owner should pause the contract', async () => { + await contractBosonRouter.pause(); + + const isPaused = await contractBosonRouter.paused(); + assert.isTrue(isPaused); + }); + + it('Owner should unpause the contract', async () => { + await contractBosonRouter.pause(); + await contractBosonRouter.unpause(); + + const isPaused = await contractBosonRouter.paused(); + assert.isFalse(isPaused); + }); + + it('[NEGATIVE] Attacker should not be able to pause the contract', async () => { + await truffleAssert.reverts( + contractBosonRouter.pause({from: users.attacker.address}), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Attacker should not be able to unpause the contract', async () => { + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + contractBosonRouter.unpause({from: users.attacker.address}), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('ETHETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + }); + + it('[NEGATIVE] Should not create voucher supply when contract is paused', async () => { + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should create voucher supply when contract is unpaused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + assert.isNotEmpty(TOKEN_SUPPLY_ID); + }); + + it('[NEGATIVE] Should not create voucherID from Buyer when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + }); + + it('[NEGATIVE] Should not create voucher supply when contract is paused', async () => { + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should create voucher supply when contract is unpaused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + assert.isNotEmpty(TOKEN_SUPPLY_ID); + }); + + it('[NEGATIVE] Should not create voucherID for Buyer when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not create voucher supply when contract is paused', async () => { + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should create voucher supply when contract is unpaused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + assert.isNotEmpty(TOKEN_SUPPLY_ID); + }); + + it('[NEGATIVE] Should not create voucherID for Buyer when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + tokensToMint = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_10) + ); + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + }); + + it('[NEGATIVE] Should not create voucher supply when contract is paused', async () => { + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ), + truffleAssert.ErrorType.REVERT + ); + }); + + it('Should create voucher supply when contract is unpaused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + assert.isNotEmpty(TOKEN_SUPPLY_ID); + }); + + it('[NEGATIVE] Should not create voucherID for Buyer when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.commitToBuy(users.buyer, users.seller, TOKEN_SUPPLY_ID), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + describe('VOUCHER KERNEL', () => { + describe('COMMON PAUSING', () => { + before(async () => { + await deployContracts(); + }); + + it('Should not be paused on deployment', async () => { + const isPaused = await contractVoucherKernel.paused(); + assert.isFalse(isPaused); + }); + + it('Should be paused from BR', async () => { + await contractBosonRouter.pause(); + + const isPaused = await contractVoucherKernel.paused(); + assert.isTrue(isPaused); + }); + + it('Should be unpaused from BR', async () => { + await contractBosonRouter.pause(); + await contractBosonRouter.unpause(); + + const isPaused = await contractVoucherKernel.paused(); + assert.isFalse(isPaused); + }); + + it('[NEGATIVE] Pause should not be called directly', async () => { + await truffleAssert.reverts( + contractVoucherKernel.pause(), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Unpause should not be called directly', async () => { + await truffleAssert.reverts( + contractVoucherKernel.unpause(), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('ETHETH', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + + const timestamp = await Utils.getCurrTimestamp(); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not process refund when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.refund(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process complain when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.complain(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process redeem when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.redeem(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process cancel when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.cancel(VOUCHER_ID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + before(async () => { + await deployContracts(); + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not process refund when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.refund(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process complain when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.complain(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process redeem when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.redeem(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process cancel when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.cancel(VOUCHER_ID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not process refund when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.refund(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process complain when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.complain(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process redeem when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.redeem(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process cancel when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.cancel(VOUCHER_ID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not process refund when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.refund(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process complain when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.complain(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process redeem when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.redeem(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process cancel when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.cancel(VOUCHER_ID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN Same', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKNSame() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + const timestamp = await Utils.getCurrTimestamp(); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenSame', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenSame', + users.buyer.address, + tokensToMint + ); + + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_10 + ); + }); + + it('[NEGATIVE] Should not process refund when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.refund(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process complain when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await utils.refund(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.complain(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process redeem when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.redeem(VOUCHER_ID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Should not process cancel when paused', async () => { + VOUCHER_ID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.redeem(VOUCHER_ID, users.buyer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.cancel(VOUCHER_ID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + describe('CASHIER', () => { + describe('COMMON PAUSING', () => { + before(async () => { + await deployContracts(); + }); + + it('Should not be paused on deployment', async () => { + const isPaused = await contractCashier.paused(); + assert.isFalse(isPaused); + }); + + it('Should be paused from BR', async () => { + await contractBosonRouter.pause(); + + const isPaused = await contractCashier.paused(); + assert.isTrue(isPaused); + }); + + it('Should be unpaused from BR', async () => { + await contractBosonRouter.pause(); + await contractBosonRouter.unpause(); + + const isPaused = await contractCashier.paused(); + assert.isFalse(isPaused); + }); + + it('[NEGATIVE] Pause should not be called directly', async () => { + await truffleAssert.reverts( + contractCashier.pause(), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] Unpause should not be called directly', async () => { + await truffleAssert.reverts( + contractCashier.unpause(), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('ETHETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ETHETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter + ); + }); + + it('[NEGATIVE] Should not process withdrawals when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdraw(voucherID, users.deployer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Buyer should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.buyer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Seller should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.seller.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('[WITH PERMIT]', () => { + describe('ETHTKN', () => { + before(async () => { + await deployContracts(); + + utils = UtilsBuilder.create() + .ERC20withPermit() + .ETHTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + }); + + it('[NEGATIVE] Should not process withdrawals when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdraw(voucherID, users.deployer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Buyer should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.buyer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Seller should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.seller.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNETH', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNETH() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + '' + ); + + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + }); + + it('[NEGATIVE] Should not process withdrawals when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdraw(voucherID, users.deployer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Buyer should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.buyer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Seller should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.seller.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('TKNTKN', () => { + before(async () => { + await deployContracts(); + utils = UtilsBuilder.create() + .ERC20withPermit() + .TKNTKN() + .build( + contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractBSNTokenDeposit + ); + + tokensToMint = new BN(constants.seller_deposit).mul( + new BN(constants.QTY_10) + ); + tokensToMint = new BN(constants.product_price).mul( + new BN(constants.QTY_10) + ); + + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.seller.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenPrice', + users.buyer.address, + tokensToMint + ); + await utils.mintTokens( + 'contractBSNTokenDeposit', + users.buyer.address, + tokensToMint + ); + }); + + it('[NEGATIVE] Should not process withdrawals when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdraw(voucherID, users.deployer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Buyer should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.buyer.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Buyer should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.buyer.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('withdrawWhenPaused - Seller should be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + const withdrawTx = await utils.withdrawWhenPaused( + voucherID, + users.seller.address + ); + + truffleAssert.eventEmitted( + withdrawTx, + 'LogAmountDistribution', + () => { + return true; + }, + 'Amounts not distributed successfully' + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Seller should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.seller.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await contractBosonRouter.pause(); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + + it('[NEGATIVE] withdrawWhenPaused - Attacker should not be able to withdraw funds when not paused', async () => { + TOKEN_SUPPLY_ID = await utils.createOrder( + users.seller, + timestamp, + timestamp + constants.SECONDS_IN_DAY, + constants.seller_deposit, + constants.QTY_1 + ); + + const voucherID = await utils.commitToBuy( + users.buyer, + users.seller, + TOKEN_SUPPLY_ID + ); + await utils.refund(voucherID, users.buyer.address); + + await timemachine.advanceTimeSeconds(60); + await utils.finalize(voucherID, users.deployer.address); + + await truffleAssert.reverts( + utils.withdrawWhenPaused(voucherID, users.attacker.address), + truffleAssert.ErrorType.REVERT + ); + }); + }); + }); + }); + + afterEach(async () => { + const isPaused = await contractBosonRouter.paused(); + if (isPaused) { + await contractBosonRouter.unpause(); + } + }); + }); +}); diff --git a/test/6_fundLimits.js b/test/6_fundLimits.js index d58d6561..71bd1797 100644 --- a/test/6_fundLimits.js +++ b/test/6_fundLimits.js @@ -1,135 +1,176 @@ -const helpers = require("../testHelpers/constants"); +const {assert} = require('chai'); const truffleAssert = require('truffle-assertions'); -const ERC1155ERC721 = artifacts.require("ERC1155ERC721"); -const VoucherKernel = artifacts.require("VoucherKernel"); -const Cashier = artifacts.require("Cashier"); -const BosonRouter = artifacts.require("BosonRouter") -const BosonToken = artifacts.require("BosonTokenPrice"); -const FundLimitsOracle = artifacts.require('FundLimitsOracle'); - -const BN = web3.utils.BN - -const UtilsBuilder = require('../testHelpers/utilsBuilder'); +const constants = require('../testHelpers/constants'); +const Users = require('../testHelpers/users'); const Utils = require('../testHelpers/utils'); -let utils; -const config = require('../testHelpers/config.json'); -const { assert } = require("chai"); - -contract("FundLimitsOracle", async accounts => { - let Deployer = config.accounts.deployer - let Attacker = config.accounts.attacker - - let contractERC1155ERC721, - contractVoucherKernel, - contractCashier, - contractBosonRouter, - contractBSNTokenPrice, - contractBSNTokenDeposit, - contractFundLimitsOracle - - let expectedLimit - const FIVE_ETHERS = (5 * 10 ** 18).toString() - const FIVE_TOKENS = (5 * 10 ** 16).toString() - - async function deployContracts() { - const timestamp = await Utils.getCurrTimestamp() - helpers.PROMISE_VALID_FROM = timestamp - helpers.PROMISE_VALID_TO = timestamp + 2 * helpers.SECONDS_IN_DAY; - - contractFundLimitsOracle = await FundLimitsOracle.new(); - - contractERC1155ERC721 = await ERC1155ERC721.new(); - contractVoucherKernel = await VoucherKernel.new(contractERC1155ERC721.address); - contractCashier = await Cashier.new(contractVoucherKernel.address) - contractBosonRouter = await BosonRouter.new(contractVoucherKernel.address, contractERC1155ERC721.address, contractFundLimitsOracle.address, contractCashier.address); - - contractBSNTokenPrice = await BosonToken.new("BosonTokenPrice", "BPRC"); - contractBSNTokenDeposit = await BosonToken.new("BosonTokenDeposit", "BDEP"); - - await contractERC1155ERC721.setApprovalForAll(contractVoucherKernel.address, 'true') - await contractERC1155ERC721.setVoucherKernelAddress(contractVoucherKernel.address) - await contractERC1155ERC721.setBosonRouterAddress(contractBosonRouter.address); - - await contractVoucherKernel.setBosonRouterAddress(contractBosonRouter.address); - await contractVoucherKernel.setCashierAddress(contractCashier.address) - - await contractCashier.setBosonRouterAddress(contractBosonRouter.address); - } - - describe('FundLimitsOracle interaction', function() { - - before(async () => { - await deployContracts() - }) - - describe("ETH", () => { - it("Should have set ETH Limit initially to 1 ETH", async () => { - const ONE_ETH = (1 * 10 ** 18).toString() - - const ethLimit = await contractFundLimitsOracle.getETHLimit() - - assert.equal(ethLimit.toString(), ONE_ETH, "ETH Limit not set properly") - }) - - it("Owner should change ETH Limit", async () => { - - await contractFundLimitsOracle.setETHLimit(FIVE_ETHERS); - - expectedLimit = await contractFundLimitsOracle.getETHLimit() - - assert.equal(expectedLimit.toString(), FIVE_ETHERS, "ETH Limit not correctly set") - }) - - it("Should emit LogETHLimitChanged", async () => { - - setLimitTx = await contractFundLimitsOracle.setETHLimit(FIVE_ETHERS); - - truffleAssert.eventEmitted(setLimitTx, 'LogETHLimitChanged', (ev) => { - return ev._triggeredBy == Deployer.address - }, - "LogETHLimitChanged was not emitted" - ) - }) - - it("[NEGATIVE] Should revert if attacker tries to change ETH Limit", async () => { - await truffleAssert.reverts( - contractFundLimitsOracle.setETHLimit(FIVE_ETHERS, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - describe("Token", () => { - - it("Owner should set Token Limit", async () => { - - await contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, FIVE_TOKENS); - - expectedLimit = await contractFundLimitsOracle.getTokenLimit(contractBSNTokenPrice.address) - - assert.equal(expectedLimit.toString(), FIVE_TOKENS, "ETH Limit not correctly set") - }) - - it("Should emit LogTokenLimitChanged", async () => { - - setLimitTx = await contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, FIVE_TOKENS); - - truffleAssert.eventEmitted(setLimitTx, 'LogTokenLimitChanged', (ev) => { - return ev._triggeredBy == Deployer.address - }, - "LogETHLimitChanged was not emitted" - ) - }) - - it("[NEGATIVE] Should revert if attacker tries to change Token Limit", async () => { - await truffleAssert.reverts( - contractFundLimitsOracle.setTokenLimit(contractBSNTokenPrice.address, FIVE_TOKENS, {from: Attacker.address}), - truffleAssert.ErrorType.REVERT - ) - }) - }) - - }) - -}); \ No newline at end of file + +const ERC1155ERC721 = artifacts.require('ERC1155ERC721'); +const VoucherKernel = artifacts.require('VoucherKernel'); +const Cashier = artifacts.require('Cashier'); +const BosonRouter = artifacts.require('BosonRouter'); +const BosonToken = artifacts.require('BosonTokenPrice'); +const FundLimitsOracle = artifacts.require('FundLimitsOracle'); + +contract('FundLimitsOracle', async (addresses) => { + const users = new Users(addresses); + + let contractERC1155ERC721, + contractVoucherKernel, + contractCashier, + contractBosonRouter, + contractBSNTokenPrice, + contractFundLimitsOracle; + let expectedLimit; + + const FIVE_ETHERS = (5 * 10 ** 18).toString(); + const FIVE_TOKENS = (5 * 10 ** 16).toString(); + + async function deployContracts() { + const timestamp = await Utils.getCurrTimestamp(); + + constants.PROMISE_VALID_FROM = timestamp; + constants.PROMISE_VALID_TO = timestamp + 2 * constants.SECONDS_IN_DAY; + + contractFundLimitsOracle = await FundLimitsOracle.new(); + + contractERC1155ERC721 = await ERC1155ERC721.new(); + contractVoucherKernel = await VoucherKernel.new( + contractERC1155ERC721.address + ); + contractCashier = await Cashier.new(contractVoucherKernel.address); + contractBosonRouter = await BosonRouter.new( + contractVoucherKernel.address, + contractERC1155ERC721.address, + contractFundLimitsOracle.address, + contractCashier.address + ); + + contractBSNTokenPrice = await BosonToken.new('BosonTokenPrice', 'BPRC'); + + await contractERC1155ERC721.setApprovalForAll( + contractVoucherKernel.address, + 'true' + ); + await contractERC1155ERC721.setVoucherKernelAddress( + contractVoucherKernel.address + ); + await contractERC1155ERC721.setBosonRouterAddress( + contractBosonRouter.address + ); + + await contractVoucherKernel.setBosonRouterAddress( + contractBosonRouter.address + ); + await contractVoucherKernel.setCashierAddress(contractCashier.address); + + await contractCashier.setBosonRouterAddress(contractBosonRouter.address); + } + + describe('FundLimitsOracle interaction', () => { + before(async () => { + await deployContracts(); + }); + + describe('ETH', () => { + it('Should have set ETH Limit initially to 1 ETH', async () => { + const ONE_ETH = (10 ** 18).toString(); + + const ethLimit = await contractFundLimitsOracle.getETHLimit(); + + assert.equal( + ethLimit.toString(), + ONE_ETH, + 'ETH Limit not set properly' + ); + }); + + it('Owner should change ETH Limit', async () => { + await contractFundLimitsOracle.setETHLimit(FIVE_ETHERS); + + expectedLimit = await contractFundLimitsOracle.getETHLimit(); + + assert.equal( + expectedLimit.toString(), + FIVE_ETHERS, + 'ETH Limit not correctly set' + ); + }); + + it('Should emit LogETHLimitChanged', async () => { + const setLimitTx = await contractFundLimitsOracle.setETHLimit( + FIVE_ETHERS + ); + + truffleAssert.eventEmitted( + setLimitTx, + 'LogETHLimitChanged', + (ev) => { + return ev._triggeredBy === users.deployer.address; + }, + 'LogETHLimitChanged was not emitted' + ); + }); + + it('[NEGATIVE] Should revert if attacker tries to change ETH Limit', async () => { + await truffleAssert.reverts( + contractFundLimitsOracle.setETHLimit(FIVE_ETHERS, { + from: users.attacker.address, + }), + truffleAssert.ErrorType.REVERT + ); + }); + }); + + describe('Token', () => { + it('Owner should set Token Limit', async () => { + await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + FIVE_TOKENS + ); + + expectedLimit = await contractFundLimitsOracle.getTokenLimit( + contractBSNTokenPrice.address + ); + + assert.equal( + expectedLimit.toString(), + FIVE_TOKENS, + 'ETH Limit not correctly set' + ); + }); + + it('Should emit LogTokenLimitChanged', async () => { + const setLimitTx = await contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + FIVE_TOKENS + ); + + truffleAssert.eventEmitted( + setLimitTx, + 'LogTokenLimitChanged', + (ev) => { + return ev._triggeredBy === users.deployer.address; + }, + 'LogETHLimitChanged was not emitted' + ); + }); + + it( + '[NEGATIVE] Should revert if attacker tries to change ' + 'Token Limit', + async () => { + await truffleAssert.reverts( + contractFundLimitsOracle.setTokenLimit( + contractBSNTokenPrice.address, + FIVE_TOKENS, + { + from: users.attacker.address, + } + ), + truffleAssert.ErrorType.REVERT + ); + } + ); + }); + }); +}); diff --git a/testHelpers/config.json b/testHelpers/config.json deleted file mode 100644 index 6c098e21..00000000 --- a/testHelpers/config.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "defaultGasPrice": 50000000000, - "defaultGasLimit": 4700000, - "defaultChainId": 0, - "nodeUrl": "http://localhost:8545/", - "ganacheCliPort": 8545, - "accounts": { - "deployer": { - "address": "0xD9995BAE12FEe327256FFec1e3184d492bD94C31", - "pk": "0x7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8" - }, - "seller": { - "address": "0xd4Fa489Eacc52BA59438993f37Be9fcC20090E39", - "pk": "0x2030b463177db2da82908ef90fa55ddfcef56e8183caf60db464bc398e736e6f" - }, - "buyer": { - "address": "0x760bf27cd45036a6C486802D30B5D90CfFBE31FE", - "pk": "0x62ecd49c4ccb41a70ad46532aed63cf815de15864bc415c87d507afd6a5e8da2" - }, - "attacker": { - "address":"0x56A32fFf5E5A8B40d6A21538579fB8922DF5258c", - "pk": "0xf473040b1a83739a9c7cc1f5719fab0f5bf178f83314d98557c58aae1910e03a" - }, - "randomUser": { - "address": "0xf0508F89e26Bd6b00f66a9D467678C7ED16a3C5A", - "pk": "0x6ca40ba4cca775643398385022264c0c414da1abd21d08d9e7136796a520a543" - }, - "randomUser2": { - "address": "0x8199de05654e9afa5C081BcE38F140082C9a7733", - "pk": "0x187bb12e927c1652377405f81d93ce948a593f7d66cfba383ee761858b05921a" - } - } -} \ No newline at end of file diff --git a/testHelpers/constants.js b/testHelpers/constants.js index c51c8cf2..65453fc9 100644 --- a/testHelpers/constants.js +++ b/testHelpers/constants.js @@ -1,47 +1,46 @@ -//common +// common const SECONDS_IN_DAY = 86400; -const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; +const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; -//asset -const ASSET_VERSION = "0x3132"; -const ASSET_TITLE = "Dragon wizard hat"; -const ASSET_TITLE2 = "T-shirt dragons"; -const ASSET_TITLE3 = "T-shirt goblins"; -const ASSET_PIN1 = "I3DESK"; -const ASSET_PIN2 = "QBSOS"; -const ASSET_QR1 = "XYZ12"; -const ASSET_QR2 = "QWY43"; -const ASSET_DESCRIPTION = "mighty wizard hat, universal size"; -const CATEGORY1 = "entertainment.games.swag"; -const CATEGORY2 = "entertainment.games.shield"; +// asset +const ASSET_VERSION = '0x3132'; +const ASSET_TITLE = 'Dragon wizard hat'; +const ASSET_TITLE2 = 'T-shirt dragons'; +const ASSET_TITLE3 = 'T-shirt goblins'; +const ASSET_PIN1 = 'I3DESK'; +const ASSET_PIN2 = 'QBSOS'; +const ASSET_QR1 = 'XYZ12'; +const ASSET_QR2 = 'QWY43'; +const ASSET_DESCRIPTION = 'mighty wizard hat, universal size'; +const CATEGORY1 = 'entertainment.games.swag'; +const CATEGORY2 = 'entertainment.games.shield'; -//promise -const PROMISE_VALID_FROM = ''; // evaluated based on the current block timestamp +// promise +const PROMISE_VALID_FROM = ''; // evaluated based on the current block timestamp const PROMISE_VALID_TO = ''; // evaluated based on the PROMISE_VALID_FROM + 2 * SECONDS_IN_DAY -const PROMISE_PRICE1 = 10; -const PROMISE_PRICE2 = 21; -const PROMISE_DEPOSITSE1 = 1; -const PROMISE_DEPOSITSE2 = 5; -const PROMISE_DEPOSITBU1 = 1; -const PROMISE_DEPOSITBU2 = 2; +const PROMISE_PRICE1 = 10; +const PROMISE_PRICE2 = 21; +const PROMISE_DEPOSITSE1 = 1; +const PROMISE_DEPOSITSE2 = 5; +const PROMISE_DEPOSITBU1 = 1; +const PROMISE_DEPOSITBU2 = 2; const PROMISE_CHALLENGE_PERIOD = 8; const PROMISE_CANCELORFAULT_PERIOD = 8; -//order +// order const ORDER_QUANTITY1 = 1; const ORDER_QUANTITY2 = 1; - const buyer_deposit = '40000000000000000'; // 0.04 const buyer_incorrect_deposit = '4000000000000000'; // 0.004 const seller_deposit = '50000000000000000'; // 0.05 const product_price = '300000000000000000'; // 0.3 const incorrect_product_price = '30000000000000000'; // 0.03 -const QTY_10 = 10 -const QTY_20 = 20 -const QTY_1 = 1 +const QTY_10 = 10; +const QTY_20 = 20; +const QTY_1 = 1; -//fund limits +// fund limits const ETHER_LIMIT = (5 * 10 ** 18).toString(); const ABOVE_ETH_LIMIT = (10 * 10 ** 18).toString(); @@ -49,42 +48,41 @@ const TOKEN_LIMIT = (5 * 10 ** 18).toString(); const ABOVE_TOKEN_LIMIT = (10 * 10 ** 18).toString(); module.exports = { - ASSET_VERSION, - ASSET_TITLE, - ASSET_TITLE2, - ASSET_TITLE3, - ASSET_PIN1, - ASSET_PIN2, - ASSET_QR1, - ASSET_QR2, - ASSET_DESCRIPTION, - CATEGORY1, - CATEGORY2, - PROMISE_VALID_FROM, - PROMISE_VALID_TO, - PROMISE_PRICE1, - PROMISE_PRICE2, - PROMISE_DEPOSITSE1, - PROMISE_DEPOSITSE2, - PROMISE_DEPOSITBU1, - PROMISE_DEPOSITBU2, - PROMISE_CHALLENGE_PERIOD, - PROMISE_CANCELORFAULT_PERIOD, - ORDER_QUANTITY1, - ORDER_QUANTITY2, - SECONDS_IN_DAY, - ZERO_ADDRESS, - buyer_deposit, - buyer_incorrect_deposit, - seller_deposit, - product_price, - incorrect_product_price, - QTY_1, - QTY_10, - QTY_1, - QTY_20, - ETHER_LIMIT, - ABOVE_ETH_LIMIT, - TOKEN_LIMIT, - ABOVE_TOKEN_LIMIT -} \ No newline at end of file + ASSET_VERSION, + ASSET_TITLE, + ASSET_TITLE2, + ASSET_TITLE3, + ASSET_PIN1, + ASSET_PIN2, + ASSET_QR1, + ASSET_QR2, + ASSET_DESCRIPTION, + CATEGORY1, + CATEGORY2, + PROMISE_VALID_FROM, + PROMISE_VALID_TO, + PROMISE_PRICE1, + PROMISE_PRICE2, + PROMISE_DEPOSITSE1, + PROMISE_DEPOSITSE2, + PROMISE_DEPOSITBU1, + PROMISE_DEPOSITBU2, + PROMISE_CHALLENGE_PERIOD, + PROMISE_CANCELORFAULT_PERIOD, + ORDER_QUANTITY1, + ORDER_QUANTITY2, + SECONDS_IN_DAY, + ZERO_ADDRESS, + buyer_deposit, + buyer_incorrect_deposit, + seller_deposit, + product_price, + incorrect_product_price, + QTY_1, + QTY_10, + QTY_20, + ETHER_LIMIT, + ABOVE_ETH_LIMIT, + TOKEN_LIMIT, + ABOVE_TOKEN_LIMIT, +}; diff --git a/testHelpers/permitUtils.js b/testHelpers/permitUtils.js index 448c747f..0072c54a 100644 --- a/testHelpers/permitUtils.js +++ b/testHelpers/permitUtils.js @@ -1,106 +1,122 @@ - const { - hexlify, - getAddress, - keccak256, - defaultAbiCoder, - toUtf8Bytes, - solidityPack, - AbiCoder, - Interface, + keccak256, + defaultAbiCoder, + toUtf8Bytes, + solidityPack, + AbiCoder, + Interface, } = require('ethers').utils; - const PERMIT_TYPEHASH = keccak256( - toUtf8Bytes('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)') + toUtf8Bytes( + 'Permit(' + + 'address owner,' + + 'address spender,' + + 'uint256 value,' + + 'uint256 nonce,' + + 'uint256 deadline)' + ) ); const toWei = (value) => { - return value + '0'.repeat(18); + return value + '0'.repeat(18); }; async function getApprovalDigest( - token, - owner, - spender, - value, - nonce, - deadline + token, + owner, + spender, + value, + nonce, + deadline ) { - - const name = await token.name(); - const DOMAIN_SEPARATOR = getDomainSeparator(name, token.address); - - return keccak256( - solidityPack( - ['bytes1', 'bytes1', 'bytes32', 'bytes32'], + const name = await token.name(); + const DOMAIN_SEPARATOR = getDomainSeparator(name, token.address); + + return keccak256( + solidityPack( + ['bytes1', 'bytes1', 'bytes32', 'bytes32'], + [ + '0x19', + '0x01', + DOMAIN_SEPARATOR, + keccak256( + defaultAbiCoder.encode( + ['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'], [ - '0x19', - '0x01', - DOMAIN_SEPARATOR, - keccak256( - defaultAbiCoder.encode( - ['bytes32', 'address', 'address', 'uint256', 'uint256', 'uint256'], - [PERMIT_TYPEHASH, owner, spender, value.toString(), nonce.toString(), deadline] - ) - ) + PERMIT_TYPEHASH, + owner, + spender, + value.toString(), + nonce.toString(), + deadline, ] - ) + ) + ), + ] ) + ); } function getDomainSeparator(name, tokenAddress) { - return keccak256( - defaultAbiCoder.encode( - ['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'], - [ - keccak256(toUtf8Bytes('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')), - keccak256(toUtf8Bytes(name)), - keccak256(toUtf8Bytes('1')), - 1, - tokenAddress - ] - ) + return keccak256( + defaultAbiCoder.encode( + ['bytes32', 'bytes32', 'bytes32', 'uint256', 'address'], + [ + keccak256( + toUtf8Bytes( + 'EIP712Domain(' + + 'string name,' + + 'string version,' + + 'uint256 chainId,' + + 'address verifyingContract)' + ) + ), + keccak256(toUtf8Bytes(name)), + keccak256(toUtf8Bytes('1')), + 1, + tokenAddress, + ] ) + ); } async function getEncodedTopic(receipt, abi, eventName) { - const interface = new Interface(abi) - for (const log in receipt.logs) { - const topics = receipt.logs[log].topics; - for (const index in topics) { - - const encodedTopic = topics[index]; - - try { - // CHECK IF TOPIC CORRESPONDS TO THE EVENT GIVEN TO FN - let event = await interface.getEvent(encodedTopic); - - if (event.name == eventName) return encodedTopic - } catch (error) { - // breaks silently as we do not need to do anything if the there is not such an event - } - - } + const interface = new Interface(abi); + for (const log in receipt.logs) { + const topics = receipt.logs[log].topics; + for (const index in topics) { + const encodedTopic = topics[index]; + + try { + // CHECK IF TOPIC CORRESPONDS TO THE EVENT GIVEN TO FN + let event = await interface.getEvent(encodedTopic); + + if (event.name === eventName) return encodedTopic; + } catch (error) { + // breaks silently as we do not need to do anything if the there is not + // such an event + } } + } - - return '' + return ''; } async function decodeData(receipt, encodedTopic, paramsArr) { - const decoder = new AbiCoder(); + const decoder = new AbiCoder(); - const encodedData = receipt.logs.filter(e => e.topics.includes(encodedTopic))[0].data - return decoder.decode(paramsArr, encodedData) + const encodedData = receipt.logs.filter((e) => + e.topics.includes(encodedTopic) + )[0].data; + return decoder.decode(paramsArr, encodedData); } - module.exports = { - PERMIT_TYPEHASH, - toWei, - getApprovalDigest, - getEncodedTopic, - decodeData -} \ No newline at end of file + PERMIT_TYPEHASH, + toWei, + getApprovalDigest, + getEncodedTopic, + decodeData, +}; diff --git a/testHelpers/timemachine.js b/testHelpers/timemachine.js index faa7a289..5642812e 100644 --- a/testHelpers/timemachine.js +++ b/testHelpers/timemachine.js @@ -1,56 +1,71 @@ function advanceTimeBlocks(_blocks) { - return new Promise(function(resolve) { - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "evm_mine", - params: [_blocks], - id: new Date().getTime() - }, resolve); - }); -}; + return new Promise(function (resolve) { + web3.currentProvider.send( + { + jsonrpc: '2.0', + method: 'evm_mine', + params: [_blocks], + id: new Date().getTime(), + }, + resolve + ); + }); +} function advanceTimeSeconds(_seconds) { - return new Promise(function(resolve) { - web3.currentProvider.send({ - jsonrpc: "2.0", - method: "evm_increaseTime", - params: [_seconds], - id: new Date().getTime() - }, resolve); - }); -}; - -function takeSnapshot () { - return new Promise((resolve, reject) => { - web3.currentProvider.send({ - jsonrpc: '2.0', - method: 'evm_snapshot', - id: new Date().getTime() - }, (err, snapshotId) => { - if (err) { return reject(err) } - return resolve(snapshotId) - }) - }) + return new Promise(function (resolve) { + web3.currentProvider.send( + { + jsonrpc: '2.0', + method: 'evm_increaseTime', + params: [_seconds], + id: new Date().getTime(), + }, + resolve + ); + }); } -function revertToSnapShot (id) { - return new Promise((resolve, reject) => { - web3.currentProvider.send({ - jsonrpc: '2.0', - method: 'evm_revert', - params: [id], - id: new Date().getTime() - }, (err, result) => { - if (err) { return reject(err) } - return resolve(result) - }) - }) +function takeSnapshot() { + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: '2.0', + method: 'evm_snapshot', + id: new Date().getTime(), + }, + (err, snapshotId) => { + if (err) { + return reject(err); + } + return resolve(snapshotId); + } + ); + }); } +function revertToSnapShot(id) { + return new Promise((resolve, reject) => { + web3.currentProvider.send( + { + jsonrpc: '2.0', + method: 'evm_revert', + params: [id], + id: new Date().getTime(), + }, + (err, result) => { + if (err) { + return reject(err); + } + return resolve(result); + } + ); + }); +} Object.assign(exports, { - advanceTimeBlocks, - advanceTimeSeconds, - takeSnapshot, - revertToSnapShot -}); \ No newline at end of file + advanceTimeBlocks, + advanceTimeSeconds, + takeSnapshot, + revertToSnapShot, +}); diff --git a/testHelpers/users.js b/testHelpers/users.js new file mode 100644 index 00000000..1fcca59e --- /dev/null +++ b/testHelpers/users.js @@ -0,0 +1,64 @@ +const fs = require('fs'); + +const userIndices = { + deployer: 0, + seller: 1, + buyer: 2, + attacker: 3, + other1: 4, + other2: 5, +}; + +const loadPrivateKeys = (accountKeysFile) => { + const accountKeysRaw = fs.readFileSync(accountKeysFile); + const accountKeysJs = JSON.parse(accountKeysRaw); + + return Object.fromEntries( + Object.entries(accountKeysJs['private_keys']).map((entry) => [ + entry[0], + `0x${entry[1]}`, + ]) + ); +}; + +class Users { + constructor(addresses) { + this.addresses = addresses; + this.privateKeys = loadPrivateKeys( + process.env.ACCOUNT_KEYS_FILE || 'config/accounts.json' + ); + } + + getAccountAtIndex(index) { + const address = this.addresses[index]; + const privateKey = this.privateKeys[address.toLowerCase()]; + + return {address, privateKey}; + } + + get deployer() { + return this.getAccountAtIndex(userIndices.deployer); + } + + get seller() { + return this.getAccountAtIndex(userIndices.seller); + } + + get buyer() { + return this.getAccountAtIndex(userIndices.buyer); + } + + get attacker() { + return this.getAccountAtIndex(userIndices.attacker); + } + + get other1() { + return this.getAccountAtIndex(userIndices.other1); + } + + get other2() { + return this.getAccountAtIndex(userIndices.other2); + } +} + +module.exports = Users; diff --git a/testHelpers/utils.js b/testHelpers/utils.js index e658663b..f0dec7c0 100644 --- a/testHelpers/utils.js +++ b/testHelpers/utils.js @@ -1,439 +1,606 @@ +const constants = require('./constants'); +const BN = web3.utils.BN; +const truffleAssert = require('truffle-assertions'); -const helpers = require('./constants') -const config = require('./config.json') -const BN = web3.utils.BN -const truffleAssert = require('truffle-assertions') +const {ecsign} = require('ethereumjs-util'); -const { ecsign } = require('ethereumjs-util'); - -const { - PERMIT_TYPEHASH, - toWei, - getApprovalDigest -} = require('../testHelpers/permitUtils'); +const {toWei, getApprovalDigest} = require('../testHelpers/permitUtils'); class Utils { - - constructor() { - this.createOrder = '' - this.commitToBuy = '' - this.deadline = toWei(1) - } - - setContracts(erc1155721, voucherKernel, cashier, bsnRouter, bsnTokenPrice, bsnTokenDeposit) { - this.contractERC1155ERC721 = erc1155721 - this.contractVoucherKernel = voucherKernel - this.contractCashier = cashier - this.contractBSNRouter = bsnRouter - this.contractBSNTokenPrice = bsnTokenPrice - this.contractBSNTokenDeposit = bsnTokenDeposit - this.contractBSNTokenSAME = bsnTokenPrice - } - - async requestCreateOrder_ETH_ETH(seller, from, to, sellerDeposit, qty, returnTx = false) { - const txValue = new BN(sellerDeposit).mul(new BN(qty)) - - let txOrder = await this.contractBSNRouter.requestCreateOrder_ETH_ETH( - [from, - to, - helpers.product_price, - sellerDeposit, - helpers.buyer_deposit, - qty], - { - from: seller.address, - value: txValue - } - ); - - return returnTx ? txOrder: (txOrder.logs[0].args._tokenIdSupply).toString() - } - - async requestCreateOrder_TKN_TKN_Same_WithPermit(seller, from, to, sellerDeposit, qty) { - const txValue = new BN(sellerDeposit).mul(new BN(qty)) - - const nonce = await this.contractBSNTokenSAME.nonces(seller.address); - - const digest = await getApprovalDigest( - this.contractBSNTokenSAME, - seller.address, - this.contractBSNRouter.address, - txValue, - nonce, - this.deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(seller.pk.slice(2), 'hex')); - - let txOrder = await this.contractBSNRouter.requestCreateOrder_TKN_TKN_WithPermit( - this.contractBSNTokenSAME.address, - this.contractBSNTokenSAME.address, - txValue, - this.deadline, - v,r,s, - [ - from, - to, - helpers.product_price, - sellerDeposit, - helpers.buyer_deposit, - qty - ], - { - from: seller.address - } - ); - - return (txOrder.logs[0].args._tokenIdSupply).toString() - } - - - async requestCreateOrder_TKN_TKN_WithPermit(seller, from, to, sellerDeposit, qty) { - const txValue = new BN(sellerDeposit).mul(new BN(qty)) - - const nonce = await this.contractBSNTokenDeposit.nonces(seller.address); - - const digest = await getApprovalDigest( - this.contractBSNTokenDeposit, - seller.address, - this.contractBSNRouter.address, - txValue, - nonce, - this.deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(seller.pk.slice(2), 'hex')); - - let txOrder = await this.contractBSNRouter.requestCreateOrder_TKN_TKN_WithPermit( - this.contractBSNTokenPrice.address, - this.contractBSNTokenDeposit.address, - txValue, - this.deadline, - v,r,s, - [ - from, - to, - helpers.product_price, - sellerDeposit, - helpers.buyer_deposit, - qty - ], - { - from: seller.address - } - ); - - return (txOrder.logs[0].args._tokenIdSupply).toString() - } - - async requestCreateOrder_ETH_TKN_WithPermit(seller, from, to, sellerDeposit, qty, returnTx = false) { - const txValue = new BN(sellerDeposit).mul(new BN(qty)); - const nonce = await this.contractBSNTokenDeposit.nonces(seller.address); - - const digest = await getApprovalDigest( - this.contractBSNTokenDeposit, - seller.address, - this.contractBSNRouter.address, - txValue, - nonce, - this.deadline - ) - - const { v, r, s } = ecsign( - Buffer.from(digest.slice(2), 'hex'), - Buffer.from(seller.pk.slice(2), 'hex')); - - - let txOrder = await this.contractBSNRouter.requestCreateOrder_ETH_TKN_WithPermit( - this.contractBSNTokenDeposit.address, - txValue, - this.deadline, - v, r, s, - [ - from, - to, - helpers.product_price, - sellerDeposit, - helpers.buyer_deposit, - qty - ], - { - from: seller.address - } - ); - - return returnTx ? txOrder : (txOrder.logs[0].args._tokenIdSupply).toString() - } - - async requestCreateOrder_TKN_ETH(seller, from, to, sellerDeposit, qty) { - const txValue = new BN(sellerDeposit).mul(new BN(qty)); - - let txOrder = await this.contractBSNRouter.requestCreateOrder_TKN_ETH( - this.contractBSNTokenPrice.address, - [ - from, - to, - helpers.product_price, - sellerDeposit, - helpers.buyer_deposit, - qty - ], - { - from: seller.address, - value: txValue - } - ); - - return (txOrder.logs[0].args._tokenIdSupply).toString() - } - - async commitToBuy_TKN_TKN_WithPermit(buyer, seller, tokenSupplyId) { - const txValue = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)) - const nonce1 = await this.contractBSNTokenDeposit.nonces(buyer.address); - - const digestDeposit = await getApprovalDigest( - this.contractBSNTokenDeposit, - buyer.address, - this.contractBSNRouter.address, - helpers.buyer_deposit, - nonce1, - this.deadline - ) - - let VRS_DEPOSIT = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(buyer.pk.slice(2), 'hex')); - - let vDeposit = VRS_DEPOSIT.v - let rDeposit = VRS_DEPOSIT.r - let sDeposit = VRS_DEPOSIT.s - - const nonce2 = await this.contractBSNTokenPrice.nonces(buyer.address); - - const digestPrice = await getApprovalDigest( - this.contractBSNTokenPrice, - buyer.address, - this.contractBSNRouter.address, - helpers.product_price, - nonce2, - this.deadline - ) - - let VRS_PRICE = ecsign( - Buffer.from(digestPrice.slice(2), 'hex'), - Buffer.from(buyer.pk.slice(2), 'hex')); - - let vPrice = VRS_PRICE.v - let rPrice = VRS_PRICE.r - let sPrice = VRS_PRICE.s - - let CommitTx = await this.contractBSNRouter.requestVoucher_TKN_TKN_WithPermit( - tokenSupplyId, - seller.address, - txValue, - this.deadline, - vPrice, rPrice, sPrice, - vDeposit, rDeposit, sDeposit, - { from: buyer.address }); - - let nestedValue = (await truffleAssert.createTransactionResult(this.contractVoucherKernel, CommitTx.tx)).logs - - let filtered = nestedValue.filter(e => e.event == 'LogVoucherDelivered')[0] - return filtered.returnValues['_tokenIdVoucher'] + constructor() { + this.createOrder = ''; + this.commitToBuy = ''; + this.deadline = toWei(1); + } + + setContracts( + erc1155721, + voucherKernel, + cashier, + bsnRouter, + bsnTokenPrice, + bsnTokenDeposit + ) { + this.contractERC1155ERC721 = erc1155721; + this.contractVoucherKernel = voucherKernel; + this.contractCashier = cashier; + this.contractBSNRouter = bsnRouter; + this.contractBSNTokenPrice = bsnTokenPrice; + this.contractBSNTokenDeposit = bsnTokenDeposit; + this.contractBSNTokenSame = bsnTokenPrice; + } + + async requestCreateOrderETHETH( + seller, + from, + to, + sellerDeposit, + qty, + returnTx = false + ) { + const txValue = new BN(sellerDeposit).mul(new BN(qty)); + + let txOrder = await this.contractBSNRouter.requestCreateOrderETHETH( + [ + from, + to, + constants.product_price, + sellerDeposit, + constants.buyer_deposit, + qty, + ], + { + from: seller.address, + value: txValue, + } + ); + + return returnTx ? txOrder : txOrder.logs[0].args._tokenIdSupply.toString(); + } + + async requestCreateOrderETHTKNSameWithPermit( + seller, + from, + to, + sellerDeposit, + qty + ) { + const txValue = new BN(sellerDeposit).mul(new BN(qty)); + + const nonce = await this.contractBSNTokenSame.nonces(seller.address); + + const digest = await getApprovalDigest( + this.contractBSNTokenSame, + seller.address, + this.contractBSNRouter.address, + txValue, + nonce, + this.deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(seller.privateKey.slice(2), 'hex') + ); + + let txOrder = await this.contractBSNRouter.requestCreateOrderTKNTKNWithPermit( + this.contractBSNTokenSame.address, + this.contractBSNTokenSame.address, + txValue, + this.deadline, + v, + r, + s, + [ + from, + to, + constants.product_price, + sellerDeposit, + constants.buyer_deposit, + qty, + ], + { + from: seller.address, + } + ); + + return txOrder.logs[0].args._tokenIdSupply.toString(); + } + + async requestCreateOrderTKNTKNWithPermit( + seller, + from, + to, + sellerDeposit, + qty + ) { + const txValue = new BN(sellerDeposit).mul(new BN(qty)); + + const nonce = await this.contractBSNTokenDeposit.nonces(seller.address); + + const digest = await getApprovalDigest( + this.contractBSNTokenDeposit, + seller.address, + this.contractBSNRouter.address, + txValue, + nonce, + this.deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(seller.privateKey.slice(2), 'hex') + ); + + let txOrder = await this.contractBSNRouter.requestCreateOrderTKNTKNWithPermit( + this.contractBSNTokenPrice.address, + this.contractBSNTokenDeposit.address, + txValue, + this.deadline, + v, + r, + s, + [ + from, + to, + constants.product_price, + sellerDeposit, + constants.buyer_deposit, + qty, + ], + { + from: seller.address, + } + ); + + return txOrder.logs[0].args._tokenIdSupply.toString(); + } + + async requestCreateOrderETHTKNWithPermit( + seller, + from, + to, + sellerDeposit, + qty, + returnTx = false + ) { + const txValue = new BN(sellerDeposit).mul(new BN(qty)); + const nonce = await this.contractBSNTokenDeposit.nonces(seller.address); + + const digest = await getApprovalDigest( + this.contractBSNTokenDeposit, + seller.address, + this.contractBSNRouter.address, + txValue, + nonce, + this.deadline + ); + + const {v, r, s} = ecsign( + Buffer.from(digest.slice(2), 'hex'), + Buffer.from(seller.privateKey.slice(2), 'hex') + ); + + let txOrder = await this.contractBSNRouter.requestCreateOrderETHTKNWithPermit( + this.contractBSNTokenDeposit.address, + txValue, + this.deadline, + v, + r, + s, + [ + from, + to, + constants.product_price, + sellerDeposit, + constants.buyer_deposit, + qty, + ], + { + from: seller.address, + } + ); + + return returnTx ? txOrder : txOrder.logs[0].args._tokenIdSupply.toString(); + } + + async requestCreateOrderTKNETH(seller, from, to, sellerDeposit, qty) { + const txValue = new BN(sellerDeposit).mul(new BN(qty)); + + let txOrder = await this.contractBSNRouter.requestCreateOrderTKNETH( + this.contractBSNTokenPrice.address, + [ + from, + to, + constants.product_price, + sellerDeposit, + constants.buyer_deposit, + qty, + ], + { + from: seller.address, + value: txValue, + } + ); + + return txOrder.logs[0].args._tokenIdSupply.toString(); + } + + async commitToBuyTKNTKNWithPermit(buyer, seller, tokenSupplyId) { + const txValue = new BN(constants.buyer_deposit).add( + new BN(constants.product_price) + ); + const nonce1 = await this.contractBSNTokenDeposit.nonces(buyer.address); + + const digestDeposit = await getApprovalDigest( + this.contractBSNTokenDeposit, + buyer.address, + this.contractBSNRouter.address, + constants.buyer_deposit, + nonce1, + this.deadline + ); + + let VRS_DEPOSIT = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(buyer.privateKey.slice(2), 'hex') + ); + + let vDeposit = VRS_DEPOSIT.v; + let rDeposit = VRS_DEPOSIT.r; + let sDeposit = VRS_DEPOSIT.s; + + const nonce2 = await this.contractBSNTokenPrice.nonces(buyer.address); + + const digestPrice = await getApprovalDigest( + this.contractBSNTokenPrice, + buyer.address, + this.contractBSNRouter.address, + constants.product_price, + nonce2, + this.deadline + ); + + let VRS_PRICE = ecsign( + Buffer.from(digestPrice.slice(2), 'hex'), + Buffer.from(buyer.privateKey.slice(2), 'hex') + ); + + let vPrice = VRS_PRICE.v; + let rPrice = VRS_PRICE.r; + let sPrice = VRS_PRICE.s; + + let CommitTx = await this.contractBSNRouter.requestVoucherTKNTKNWithPermit( + tokenSupplyId, + seller.address, + txValue, + this.deadline, + vPrice, + rPrice, + sPrice, + vDeposit, + rDeposit, + sDeposit, + {from: buyer.address} + ); + + let nestedValue = ( + await truffleAssert.createTransactionResult( + this.contractVoucherKernel, + CommitTx.tx + ) + ).logs; + + let filtered = nestedValue.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + return filtered.returnValues['_tokenIdVoucher']; + } + + async commitToBuyTKNTKNSameWithPermit(buyer, seller, tokenSupplyId) { + const txValue = new BN(constants.buyer_deposit).add( + new BN(constants.product_price) + ); + const nonce = await this.contractBSNTokenSame.nonces(buyer.address); + + const digestTxValue = await getApprovalDigest( + this.contractBSNTokenSame, + buyer.address, + this.contractBSNRouter.address, + txValue, + nonce, + this.deadline + ); + + let VRS_TX_VALUE = ecsign( + Buffer.from(digestTxValue.slice(2), 'hex'), + Buffer.from(buyer.privateKey.slice(2), 'hex') + ); + + let v = VRS_TX_VALUE.v; + let r = VRS_TX_VALUE.r; + let s = VRS_TX_VALUE.s; + + let CommitTx = await this.contractBSNRouter.requestVoucherTKNTKNSameWithPermit( + tokenSupplyId, + seller.address, + txValue, + this.deadline, + v, + r, + s, + {from: buyer.address} + ); + + let nestedValue = ( + await truffleAssert.createTransactionResult( + this.contractVoucherKernel, + CommitTx.tx + ) + ).logs; + + let filtered = nestedValue.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + return filtered.returnValues['_tokenIdVoucher']; + } + + async commitToBuyETHTKNWithPermit(buyer, seller, tokenSupplyId) { + const nonce1 = await this.contractBSNTokenDeposit.nonces(buyer.address); + + const digestDeposit = await getApprovalDigest( + this.contractBSNTokenDeposit, + buyer.address, + this.contractBSNRouter.address, + constants.buyer_deposit, + nonce1, + this.deadline + ); + + let {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(buyer.privateKey.slice(2), 'hex') + ); + + let txOrder = await this.contractBSNRouter.requestVoucherETHTKNWithPermit( + tokenSupplyId, + seller.address, + constants.buyer_deposit, + this.deadline, + v, + r, + s, + {from: buyer.address, value: constants.product_price.toString()} + ); + + let nestedValue = ( + await truffleAssert.createTransactionResult( + this.contractVoucherKernel, + txOrder.tx + ) + ).logs; + + let filtered = nestedValue.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + return filtered.returnValues['_tokenIdVoucher']; + } + + async commitToBuyETHETH(buyer, seller, tokenSupplyId) { + const txValue = new BN(constants.buyer_deposit).add( + new BN(constants.product_price) + ); + + let CommitTx = await this.contractBSNRouter.requestVoucherETHETH( + tokenSupplyId, + seller.address, + { + from: buyer.address, + value: txValue.toString(), + } + ); + + let nestedValue = ( + await truffleAssert.createTransactionResult( + this.contractVoucherKernel, + CommitTx.tx + ) + ).logs; + + let filtered = nestedValue.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + return filtered.returnValues['_tokenIdVoucher']; + } + + async commitToBuyTKNETHWithPermit(buyer, seller, tokenSupplyId) { + const nonce1 = await this.contractBSNTokenPrice.nonces(buyer.address); + + const digestDeposit = await getApprovalDigest( + this.contractBSNTokenPrice, + buyer.address, + this.contractBSNRouter.address, + constants.product_price, + nonce1, + this.deadline + ); + + let {v, r, s} = ecsign( + Buffer.from(digestDeposit.slice(2), 'hex'), + Buffer.from(buyer.privateKey.slice(2), 'hex') + ); + + let txOrder = await this.contractBSNRouter.requestVoucherTKNETHWithPermit( + tokenSupplyId, + seller.address, + constants.product_price, + this.deadline, + v, + r, + s, + {from: buyer.address, value: constants.buyer_deposit} + ); + + let nestedValue = ( + await truffleAssert.createTransactionResult( + this.contractVoucherKernel, + txOrder.tx + ) + ).logs; + + let filtered = nestedValue.filter( + (e) => e.event === 'LogVoucherDelivered' + )[0]; + + return filtered.returnValues['_tokenIdVoucher']; + } + + async refund(voucherID, buyer) { + await this.contractBSNRouter.refund(voucherID, {from: buyer}); + } + + async redeem(voucherID, buyer) { + await this.contractBSNRouter.redeem(voucherID, {from: buyer}); + } + + async complain(voucherID, buyer) { + await this.contractBSNRouter.complain(voucherID, {from: buyer}); + } + + async cancel(voucherID, seller) { + await this.contractBSNRouter.cancelOrFault(voucherID, {from: seller}); + } + + async finalize(voucherID, deployer) { + await this.contractVoucherKernel.triggerFinalizeVoucher(voucherID, { + from: deployer, + }); + } + + async withdraw(voucherID, deployer) { + const tx = await this.contractCashier.withdraw(voucherID, {from: deployer}); + + console.log('GAS USED: ', tx.receipt.gasUsed); + + return tx; + } + + async withdrawWhenPaused(voucherID, executor) { + const tx = await this.contractCashier.withdrawWhenPaused(voucherID, { + from: executor, + }); + + console.log('GAS USED: ', tx.receipt.gasUsed); + + return tx; + } + + async pause(deployer) { + await this.contractBSNRouter.pause({from: deployer}); + } + + async safeTransfer721(oldVoucherOwner, newVoucherOwner, voucherID, from) { + const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0'); + + const methodSignature = + 'safeTransferFrom(' + 'address,' + 'address,' + 'uint256,' + 'bytes)'; + const method = this.contractERC1155ERC721.methods[methodSignature]; + + return await method( + oldVoucherOwner, + newVoucherOwner, + voucherID, + arbitraryBytes, + from + ); + } + + async safeTransfer1155(oldSupplyOwner, newSupplyOwner, supplyID, qty, from) { + const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0'); + + const methodSignature = + 'safeTransferFrom(' + + 'address,' + + 'address,' + + 'uint256,' + + 'uint256,' + + 'bytes)'; + const method = this.contractERC1155ERC721.methods[methodSignature]; + + return await method( + oldSupplyOwner, + newSupplyOwner, + supplyID, + qty, + arbitraryBytes, + from + ); + } + + async safeBatchTransfer1155( + oldSupplyOwner, + newSupplyOwner, + supplyIDs, + values, + from + ) { + const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0'); + + const methodSignature = + 'safeBatchTransferFrom(' + + 'address,' + + 'address,' + + 'uint256[],' + + 'uint256[],' + + 'bytes)'; + const method = this.contractERC1155ERC721.methods[methodSignature]; + + return await method( + oldSupplyOwner, + newSupplyOwner, + supplyIDs, + values, + arbitraryBytes, + from + ); + } + + calcTotalAmountToRecipients( + event, + distributionAmounts, + recipient, + buyer, + seller + ) { + if (event[recipient] === buyer) { + distributionAmounts.buyerAmount = new BN( + distributionAmounts.buyerAmount.toString() + ).add(new BN(event._payment.toString())); + } else if (event[recipient] === seller) { + distributionAmounts.sellerAmount = new BN( + distributionAmounts.sellerAmount.toString() + ).add(new BN(event._payment.toString())); + } else { + distributionAmounts.escrowAmount = new BN( + distributionAmounts.escrowAmount.toString() + ).add(new BN(event._payment.toString())); } + } - async commitToBuy_TKN_TKN_Same_WithPermit(buyer, seller, tokenSupplyId) { - const txValue = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)) - const nonce = await this.contractBSNTokenSAME.nonces(buyer.address); - - const digestTxValue = await getApprovalDigest( - this.contractBSNTokenSAME, - buyer.address, - this.contractBSNRouter.address, - txValue, - nonce, - this.deadline - ) - - let VRS_TX_VALUE = ecsign( - Buffer.from(digestTxValue.slice(2), 'hex'), - Buffer.from(buyer.pk.slice(2), 'hex')); - - let v = VRS_TX_VALUE.v - let r = VRS_TX_VALUE.r - let s = VRS_TX_VALUE.s - - let CommitTx = await this.contractBSNRouter.requestVoucher_TKN_TKN_Same_WithPermit( - tokenSupplyId, - seller.address, - txValue, - this.deadline, - v, r, s, - { from: buyer.address }); - - let nestedValue = (await truffleAssert.createTransactionResult(this.contractVoucherKernel, CommitTx.tx)).logs - - let filtered = nestedValue.filter(e => e.event == 'LogVoucherDelivered')[0] - return filtered.returnValues['_tokenIdVoucher'] - } - - async commitToBuy_ETH_TKN_WithPermit(buyer, seller, tokenSupplyId) { - const nonce1 = await this.contractBSNTokenDeposit.nonces(buyer.address); - - const digestDeposit = await getApprovalDigest( - this.contractBSNTokenDeposit, - buyer.address, - this.contractBSNRouter.address, - helpers.buyer_deposit, - nonce1, - this.deadline - ) - - let { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(buyer.pk.slice(2), 'hex')); - - - let txOrder = await this.contractBSNRouter.requestVoucher_ETH_TKN_WithPermit( - tokenSupplyId, - seller.address, - helpers.buyer_deposit, - this.deadline, - v, r, s, - { from: buyer.address, value: helpers.product_price.toString() } - ); - - let nestedValue = (await truffleAssert.createTransactionResult(this.contractVoucherKernel, txOrder.tx)).logs - - let filtered = nestedValue.filter(e => e.event == 'LogVoucherDelivered')[0] - return filtered.returnValues['_tokenIdVoucher'] - } - - async commitToBuy_ETH_ETH(buyer, seller, tokenSupplyId) { - const txValue = new BN(helpers.buyer_deposit).add(new BN(helpers.product_price)) - - let CommitTx = await this.contractBSNRouter.requestVoucher_ETH_ETH(tokenSupplyId, seller.address, { from: buyer.address, value: txValue.toString() }); - - let nestedValue = (await truffleAssert.createTransactionResult(this.contractVoucherKernel, CommitTx.tx)).logs - - let filtered = nestedValue.filter(e => e.event == 'LogVoucherDelivered')[0] - return filtered.returnValues['_tokenIdVoucher'] - } - - async commitToBuy_TKN_ETH_WithPermit(buyer, seller, tokenSupplyId) { - const nonce1 = await this.contractBSNTokenPrice.nonces(buyer.address); - - const digestDeposit = await getApprovalDigest( - this.contractBSNTokenPrice, - buyer.address, - this.contractBSNRouter.address, - helpers.product_price, - nonce1, - this.deadline - ) - - let { v, r, s } = ecsign( - Buffer.from(digestDeposit.slice(2), 'hex'), - Buffer.from(buyer.pk.slice(2), 'hex')); + async mintTokens(tokenContract, to, value) { + await this[tokenContract].mint(to, value); + } + static async getCurrTimestamp() { + let blockNumber = await web3.eth.getBlockNumber(); + let block = await web3.eth.getBlock(blockNumber); - let txOrder = await this.contractBSNRouter.requestVoucher_TKN_ETH_WithPermit( - tokenSupplyId, - seller.address, - helpers.product_price, - this.deadline, - v, r, s, - { from: buyer.address, value: helpers.buyer_deposit } - ); - - let nestedValue = (await truffleAssert.createTransactionResult(this.contractVoucherKernel, txOrder.tx)).logs - - let filtered = nestedValue.filter(e => e.event == 'LogVoucherDelivered')[0] - return filtered.returnValues['_tokenIdVoucher'] - } - - async refund(voucherID, buyer) { - await this.contractBSNRouter.refund(voucherID, { from: buyer }); - } - - async redeem(voucherID, buyer) { - await this.contractBSNRouter.redeem(voucherID, { from: buyer }); - } - - async complain(voucherID, buyer) { - await this.contractBSNRouter.complain(voucherID, { from: buyer }); - } - - async cancel(voucherID, seller) { - await this.contractBSNRouter.cancelOrFault(voucherID, { from: seller }); - } - - async finalize(voucherID, deployer) { - await this.contractVoucherKernel.triggerFinalizeVoucher(voucherID, {from: deployer}) - } - - async withdraw(voucherID, deployer) { - const tx = await this.contractCashier.withdraw(voucherID, {from: deployer}); - console.log('GAS USED: ', tx.receipt.gasUsed); - return tx - } - - async withdrawWhenPaused(voucherID, executor) { - const tx = await this.contractCashier.withdrawWhenPaused(voucherID, {from: executor}); - console.log('GAS USED: ', tx.receipt.gasUsed); - return tx - } - - async pause(deployer) { - await this.contractBSNRouter.pause({from: deployer}) - } - - async safeTransfer721(oldVoucherOwner, newVoucherOwner, voucherID, from) { - const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0') - return await this.contractERC1155ERC721 - .methods['safeTransferFrom(address,address,uint256,bytes)'] - (oldVoucherOwner, newVoucherOwner, voucherID, arbitraryBytes, from); - } - - async safeTransfer1155(oldSupplyOwner, newSupplyOwner, supplyID, qty, from) { - const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0') - return await this.contractERC1155ERC721 - .methods['safeTransferFrom(address,address,uint256,uint256,bytes)'] - (oldSupplyOwner, newSupplyOwner, supplyID, qty, arbitraryBytes, from); - } - - async safeBatchTransfer1155(oldSupplyOwner, newSupplyOwner, supplyIDs, values, from) { - const arbitraryBytes = web3.utils.fromAscii('0x0').padEnd(66, '0') - return await this.contractERC1155ERC721 - .methods['safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)'] - (oldSupplyOwner, newSupplyOwner, supplyIDs, values, arbitraryBytes, from); - } - - calcTotalAmountToRecipients(event, distributionAmounts, recipient, buyer, seller) { - if (event[recipient] == buyer) { - distributionAmounts.buyerAmount = new BN(distributionAmounts.buyerAmount.toString()).add(new BN(event._payment.toString())) - } else if (event[recipient] == seller) { - distributionAmounts.sellerAmount = new BN(distributionAmounts.sellerAmount.toString()).add(new BN(event._payment.toString())) - } else { - distributionAmounts.escrowAmount = new BN(distributionAmounts.escrowAmount.toString()).add(new BN(event._payment.toString())) - } - } - - async mintTokens(tokenContract, to, value) { - - await this[tokenContract].mint(to, value); - } - - static async getCurrTimestamp() { - let blockNumber = await web3.eth.getBlockNumber() - let block = await web3.eth.getBlock(blockNumber) - - return block.timestamp - } + return block.timestamp; + } } -module.exports = Utils \ No newline at end of file +module.exports = Utils; diff --git a/testHelpers/utilsBuilder.js b/testHelpers/utilsBuilder.js index 1cae6010..c9238bf2 100644 --- a/testHelpers/utilsBuilder.js +++ b/testHelpers/utilsBuilder.js @@ -1,67 +1,78 @@ - // @ts-nocheck -const Utils = require('./utils') +const Utils = require('./utils'); class UtilsBuilder { - - constructor() { - this.utils = new Utils() - } - - static NEW () { - return new UtilsBuilder() - }; - - ETH_ETH () { - this.utils.createOrder = this.utils.requestCreateOrder_ETH_ETH - this.utils.commitToBuy = this.utils.commitToBuy_ETH_ETH - - return this - } - - ERC20withPermit () { - this.ETH_TKN = this.ETH_TKN_WithPermit - this.TKN_TKN = this.TKN_TKN_WithPermit - this.TKN_ETH = this.TKN_ETH_WithPermit - this.TKN_TKN_SAME = this.TKN_TKN_SameWithPermit - - return this - } - - build(erc1155721, voucherKernel, cashier, bsnRouter, bsnTokenPrice, bsnTokenDeposit) { - this.utils.setContracts(erc1155721, voucherKernel, cashier, bsnRouter, bsnTokenPrice, bsnTokenDeposit); - return this.utils; - } - - ETH_TKN_WithPermit() { - this.utils.createOrder = this.utils.requestCreateOrder_ETH_TKN_WithPermit - this.utils.commitToBuy = this.utils.commitToBuy_ETH_TKN_WithPermit - - return this - } - - TKN_TKN_WithPermit() { - this.utils.createOrder = this.utils.requestCreateOrder_TKN_TKN_WithPermit - this.utils.commitToBuy = this.utils.commitToBuy_TKN_TKN_WithPermit - - return this - } - - TKN_TKN_SameWithPermit() { - this.utils.createOrder = this.utils.requestCreateOrder_TKN_TKN_Same_WithPermit - this.utils.commitToBuy = this.utils.commitToBuy_TKN_TKN_Same_WithPermit - - return this - } - - TKN_ETH_WithPermit() { - this.utils.createOrder = this.utils.requestCreateOrder_TKN_ETH - this.utils.commitToBuy = this.utils.commitToBuy_TKN_ETH_WithPermit - - return this - } - - + constructor() { + this.utils = new Utils(); + } + + static create() { + return new UtilsBuilder(); + } + + ETHETH() { + this.utils.createOrder = this.utils.requestCreateOrderETHETH; + this.utils.commitToBuy = this.utils.commitToBuyETHETH; + + return this; + } + + ERC20withPermit() { + this.ETHTKN = this.ETHTKNWithPermit; + this.TKNTKN = this.TKNTKNWithPermit; + this.TKNETH = this.TKNETHWithPermit; + this.TKNTKNSame = this.TKNTKNSameWithPermit; + + return this; + } + + build( + erc1155721, + voucherKernel, + cashier, + bsnRouter, + bsnTokenPrice, + bsnTokenDeposit + ) { + this.utils.setContracts( + erc1155721, + voucherKernel, + cashier, + bsnRouter, + bsnTokenPrice, + bsnTokenDeposit + ); + + return this.utils; + } + + ETHTKNWithPermit() { + this.utils.createOrder = this.utils.requestCreateOrderETHTKNWithPermit; + this.utils.commitToBuy = this.utils.commitToBuyETHTKNWithPermit; + + return this; + } + + TKNTKNWithPermit() { + this.utils.createOrder = this.utils.requestCreateOrderTKNTKNWithPermit; + this.utils.commitToBuy = this.utils.commitToBuyTKNTKNWithPermit; + + return this; + } + + TKNTKNSameWithPermit() { + this.utils.createOrder = this.utils.requestCreateOrderETHTKNSameWithPermit; + this.utils.commitToBuy = this.utils.commitToBuyTKNTKNSameWithPermit; + + return this; + } + + TKNETHWithPermit() { + this.utils.createOrder = this.utils.requestCreateOrderTKNETH; + this.utils.commitToBuy = this.utils.commitToBuyTKNETHWithPermit; + + return this; + } } -module.exports = UtilsBuilder; \ No newline at end of file +module.exports = UtilsBuilder; diff --git a/testUserInteractions/buyer_complain.js b/testUserInteractions/buyer_complain.js index c47855b5..bf2f4d5d 100644 --- a/testUserInteractions/buyer_complain.js +++ b/testUserInteractions/buyer_complain.js @@ -1,42 +1,51 @@ -const VoucherKernel = require("../build/VoucherKernel.json"); +const VoucherKernel = require('../build/VoucherKernel.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { VOUCHER_ID, BUYER_SECRET, contracts } = require('./config'); -const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); - -(async() => { - let voucherKernelContract_Buyer = new ethers.Contract(contracts.VoucherKernelContractAddress, VoucherKernel.abi, accountBuyer) - - const tokenIdVoucher = VOUCHER_ID - - let txOrder = await voucherKernelContract_Buyer.complain( - tokenIdVoucher, {gasLimit: '4000000'}); - - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogVoucherComplain', '_tokenIdVoucher') - console.log('parsedEvent'); - console.log(parsedEvent); - +const {VOUCHER_ID, BUYER_SECRET, contracts} = require('./config'); +const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); + +(async () => { + let voucherKernelContract_Buyer = new ethers.Contract( + contracts.VoucherKernelContractAddress, + VoucherKernel.abi, + accountBuyer + ); + + const tokenIdVoucher = VOUCHER_ID; + + let txOrder = await voucherKernelContract_Buyer.complain(tokenIdVoucher, { + gasLimit: '4000000', + }); + + const receipt = await txOrder.wait(); + + let parsedEvent = await findEventByName( + receipt, + 'LogVoucherComplain', + '_tokenIdVoucher' + ); + console.log('parsedEvent'); + console.log(parsedEvent); })(); async function findEventByName(txReceipt, eventName, ...eventFields) { + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } + const resultObj = { + txHash: txReceipt.transactionHash, + }; - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } /** @@ -45,4 +54,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { '0xa00ae1284ad381e1aa2e172be82ca1c16968ea3cb25dec0ab67abd4cac7311c8', _tokenIdVoucher: '57896044618658097711785492504343953957600687722625682194895881280247472062467' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/buyer_redeem.js b/testUserInteractions/buyer_redeem.js index d84dce56..118fe5a8 100644 --- a/testUserInteractions/buyer_redeem.js +++ b/testUserInteractions/buyer_redeem.js @@ -1,42 +1,53 @@ -const VoucherKernel = require("../build/VoucherKernel.json"); +const VoucherKernel = require('../build/VoucherKernel.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { VOUCHER_ID, BUYER_SECRET, contracts } = require('./config'); -const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); - -(async() => { - let voucherKernelContract_Buyer = new ethers.Contract(contracts.VoucherKernelContractAddress, VoucherKernel.abi, accountBuyer) - - const tokenIdVoucher = VOUCHER_ID - - let txOrder = await voucherKernelContract_Buyer.redeem( - tokenIdVoucher, {gasLimit: '4000000'}); - - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogVoucherRedeemed', '_tokenIdVoucher', '_holder', '_promiseId') - console.log('parsedEvent'); - console.log(parsedEvent); - +const {VOUCHER_ID, BUYER_SECRET, contracts} = require('./config'); +const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); + +(async () => { + let voucherKernelContract_Buyer = new ethers.Contract( + contracts.VoucherKernelContractAddress, + VoucherKernel.abi, + accountBuyer + ); + + const tokenIdVoucher = VOUCHER_ID; + + let txOrder = await voucherKernelContract_Buyer.redeem(tokenIdVoucher, { + gasLimit: '4000000', + }); + + const receipt = await txOrder.wait(); + + let parsedEvent = await findEventByName( + receipt, + 'LogVoucherRedeemed', + '_tokenIdVoucher', + '_holder', + '_promiseId' + ); + console.log('parsedEvent'); + console.log(parsedEvent); })(); async function findEventByName(txReceipt, eventName, ...eventFields) { + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } + const resultObj = { + txHash: txReceipt.transactionHash, + }; - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } /** @@ -48,4 +59,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { _holder: '0xd4Fa489Eacc52BA59438993f37Be9fcC20090E39', _promiseId: '0x201fb46fee4d1db3d3256ffd44a7be8d4035bbf504cb8413393d3bc891e849d4' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/buyer_refund.js b/testUserInteractions/buyer_refund.js index 0a897632..95cc7ca2 100644 --- a/testUserInteractions/buyer_refund.js +++ b/testUserInteractions/buyer_refund.js @@ -1,41 +1,49 @@ -const VoucherKernel = require("../build/VoucherKernel.json"); +const VoucherKernel = require('../build/VoucherKernel.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { VOUCHER_ID, BUYER_SECRET, contracts } = require('./config'); +const {VOUCHER_ID, BUYER_SECRET, contracts} = require('./config'); const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); - -(async() => { - let voucherKernelContract_Buyer = new ethers.Contract(contracts.VoucherKernelContractAddress, VoucherKernel.abi, accountBuyer) - - let txOrder = await voucherKernelContract_Buyer.refund( - VOUCHER_ID, {gasLimit: '4000000'}); - - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogVoucherRefunded', '_tokenIdVoucher') - console.log('parsedEvent'); - console.log(parsedEvent); - +(async () => { + let voucherKernelContract_Buyer = new ethers.Contract( + contracts.VoucherKernelContractAddress, + VoucherKernel.abi, + accountBuyer + ); + + let txOrder = await voucherKernelContract_Buyer.refund(VOUCHER_ID, { + gasLimit: '4000000', + }); + + const receipt = await txOrder.wait(); + + let parsedEvent = await findEventByName( + receipt, + 'LogVoucherRefunded', + '_tokenIdVoucher' + ); + console.log('parsedEvent'); + console.log(parsedEvent); })(); async function findEventByName(txReceipt, eventName, ...eventFields) { - - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } - - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; + + const resultObj = { + txHash: txReceipt.transactionHash, + }; + + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } /** @@ -43,4 +51,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { '0x8cd2840d6a2e2b9cf7995380256bb28606cd520aa345a1a61359ace0a31e1d5c', _tokenIdVoucher: '57896044618658097711785492504343953957600687722625682194895881280247472062467' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/buyer_requestVoucher.js b/testUserInteractions/buyer_requestVoucher.js index 20c77795..5d55730d 100644 --- a/testUserInteractions/buyer_requestVoucher.js +++ b/testUserInteractions/buyer_requestVoucher.js @@ -1,53 +1,69 @@ -const Cashier = require("../build/Cashier.json"); -const helpers = require('../testHelpers/constants') +const Cashier = require('../build/Cashier.json'); +const helpers = require('../testHelpers/constants'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { SELLER_PUBLIC, BUYER_SECRET, contracts, TOKEN_SUPPLY_ID } = require('./config'); -const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); - +const { + SELLER_PUBLIC, + BUYER_SECRET, + contracts, + TOKEN_SUPPLY_ID, +} = require('./config'); +const accountBuyer = new ethers.Wallet(BUYER_SECRET, provider); (async () => { + let cashierContract_Buyer = new ethers.Contract( + contracts.CashierContractAddress, + Cashier.abi, + accountBuyer + ); - let cashierContract_Buyer = new ethers.Contract(contracts.CashierContractAddress, Cashier.abi, accountBuyer) - - const tokenSupplyKey = TOKEN_SUPPLY_ID - - const buyerDeposit = helpers.buyer_deposit; - const price = helpers.product_price; - const txValue = ethers.BigNumber.from(buyerDeposit).add(ethers.BigNumber.from(price)) + const tokenSupplyKey = TOKEN_SUPPLY_ID; + const buyerDeposit = helpers.buyer_deposit; + const price = helpers.product_price; + const txValue = ethers.BigNumber.from(buyerDeposit).add( + ethers.BigNumber.from(price) + ); - let txOrder = await cashierContract_Buyer.requestVoucher( - tokenSupplyKey, - SELLER_PUBLIC, - { value: txValue.toString()} - ); + let txOrder = await cashierContract_Buyer.requestVoucher( + tokenSupplyKey, + SELLER_PUBLIC, + {value: txValue.toString()} + ); - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogVoucherDelivered', '_tokenIdSupply', '_tokenIdVoucher', '_issuer', '_holder', '_promiseId') - console.log('parsedEvent'); - console.log(parsedEvent); + const receipt = await txOrder.wait(); + let parsedEvent = await findEventByName( + receipt, + 'LogVoucherDelivered', + '_tokenIdSupply', + '_tokenIdVoucher', + '_issuer', + '_holder', + '_promiseId' + ); + console.log('parsedEvent'); + console.log(parsedEvent); })(); async function findEventByName(txReceipt, eventName, ...eventFields) { + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } + const resultObj = { + txHash: txReceipt.transactionHash, + }; - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } /** @@ -61,4 +77,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { '0x3c654b884252d1ea1fa50c47718de4a4868587631708d184b5f157da15ed2889', txHash: '0xa2acb1af433d4a4bde65e84e69c92817b3d8c37c81b19f7e1b42c3025b31d20b' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/config.js b/testUserInteractions/config.js index f95066e6..393e071c 100644 --- a/testUserInteractions/config.js +++ b/testUserInteractions/config.js @@ -1,19 +1,17 @@ module.exports = { - TOKEN_SUPPLY_ID: "token supply id", - VOUCHER_ID: "voucher id", - contracts: { - TokenContractAddress: 'token contract address', - VoucherKernelContractAddress: 'voucher kernel contract address', - CashierContractAddress: 'cashier contract address' - }, - DEPLOYER_PUBLIC: 'deployer public key', - DEPLOYER_SECRET: 'deployer secret key', - BUYER_PUBLIC: 'buyer public key', - BUYER_SECRET: 'buyer secret key', - SELLER_PUBLIC: 'seller public key', - SELLER_SECRET: 'seller secret key', - DB_VOUCHER_TO_MODIFY: "", // this is if you would like to manipulate some record in a local DB. The voucher you are editing must be with the same price, buyer deposit and seller deposit! - SEND_TO_DB: false -} - - + TOKEN_SUPPLY_ID: 'token supply id', + VOUCHER_ID: 'voucher id', + contracts: { + TokenContractAddress: 'token contract address', + VoucherKernelContractAddress: 'voucher kernel contract address', + CashierContractAddress: 'cashier contract address', + }, + DEPLOYER_PUBLIC: 'deployer public key', + DEPLOYER_SECRET: 'deployer secret key', + BUYER_PUBLIC: 'buyer public key', + BUYER_SECRET: 'buyer secret key', + SELLER_PUBLIC: 'seller public key', + SELLER_SECRET: 'seller secret key', + DB_VOUCHER_TO_MODIFY: '', // this is if you would like to manipulate some record in a local DB. The voucher you are editing must be with the same price, buyer deposit and seller deposit! + SEND_TO_DB: false, +}; diff --git a/testUserInteractions/deploy.js b/testUserInteractions/deploy.js index 01a0abf0..aa9302a4 100644 --- a/testUserInteractions/deploy.js +++ b/testUserInteractions/deploy.js @@ -1,31 +1,56 @@ -const ERC1155ERC721 = require("../build/ERC1155ERC721.json"); -const VoucherKernel = require("../build/VoucherKernel.json"); -const Cashier = require("../build/Cashier.json"); +const ERC1155ERC721 = require('../build/ERC1155ERC721.json'); +const VoucherKernel = require('../build/VoucherKernel.json'); +const Cashier = require('../build/Cashier.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { DEPLOYER_SECRET, SELLER_SECRET} = require('./config') -const deployer = new ethers.Wallet(DEPLOYER_SECRET, provider); -const accountSeller = new ethers.Wallet(SELLER_SECRET, provider); +const {DEPLOYER_SECRET, SELLER_SECRET} = require('./config'); +const deployer = new ethers.Wallet(DEPLOYER_SECRET, provider); +const accountSeller = new ethers.Wallet(SELLER_SECRET, provider); (async () => { - const ERC1155_Factory = new ethers.ContractFactory(ERC1155ERC721.abi, ERC1155ERC721.bytecode, deployer) - const VoucherKernel_Factory = new ethers.ContractFactory(VoucherKernel.abi, VoucherKernel.bytecode, deployer) - const Cashier_Factory = new ethers.ContractFactory(Cashier.abi, Cashier.bytecode, deployer) - - const TokenContract = await ERC1155_Factory.deploy(); - const TokenContractSeller = await new ethers.Contract(TokenContract.address, ERC1155ERC721.abi, accountSeller); - const VoucherKernelContract = await VoucherKernel_Factory.deploy(TokenContract.address); - const CashierContract = await Cashier_Factory.deploy(VoucherKernelContract.address); + const ERC1155_Factory = new ethers.ContractFactory( + ERC1155ERC721.abi, + ERC1155ERC721.bytecode, + deployer + ); + const VoucherKernel_Factory = new ethers.ContractFactory( + VoucherKernel.abi, + VoucherKernel.bytecode, + deployer + ); + const Cashier_Factory = new ethers.ContractFactory( + Cashier.abi, + Cashier.bytecode, + deployer + ); - await TokenContract.setApprovalForAll(VoucherKernelContract.address, 'true'); - await TokenContractSeller.setApprovalForAll(VoucherKernelContract.address, 'true'); - await TokenContract.setVoucherKernelAddress(VoucherKernelContract.address); - await VoucherKernelContract.setCashierAddress(CashierContract.address); + const TokenContract = await ERC1155_Factory.deploy(); + const TokenContractSeller = await new ethers.Contract( + TokenContract.address, + ERC1155ERC721.abi, + accountSeller + ); + const VoucherKernelContract = await VoucherKernel_Factory.deploy( + TokenContract.address + ); + const CashierContract = await Cashier_Factory.deploy( + VoucherKernelContract.address + ); + await TokenContract.setApprovalForAll(VoucherKernelContract.address, 'true'); + await TokenContractSeller.setApprovalForAll( + VoucherKernelContract.address, + 'true' + ); + await TokenContract.setVoucherKernelAddress(VoucherKernelContract.address); + await VoucherKernelContract.setCashierAddress(CashierContract.address); - console.log('Token Contract Address: ', TokenContract.address); - console.log('Voucher Kernel Contract Address: ', VoucherKernelContract.address); - console.log('Cashier Contract Address: ', CashierContract.address); -})() + console.log('Token Contract Address: ', TokenContract.address); + console.log( + 'Voucher Kernel Contract Address: ', + VoucherKernelContract.address + ); + console.log('Cashier Contract Address: ', CashierContract.address); +})(); diff --git a/testUserInteractions/finalize.js b/testUserInteractions/finalize.js index bc5a5388..ea3171c1 100644 --- a/testUserInteractions/finalize.js +++ b/testUserInteractions/finalize.js @@ -1,64 +1,85 @@ -const VoucherKernel = require("../build/VoucherKernel.json"); +const VoucherKernel = require('../build/VoucherKernel.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { SELLER_SECRET, VOUCHER_ID, - DB_VOUCHER_TO_MODIFY, contracts, SEND_TO_DB } = require('./config'); +const { + SELLER_SECRET, + VOUCHER_ID, + DB_VOUCHER_TO_MODIFY, + contracts, + SEND_TO_DB, +} = require('./config'); -const seller = new ethers.Wallet(SELLER_SECRET, provider); +const seller = new ethers.Wallet(SELLER_SECRET, provider); const axios = require('axios').default; -(async() => { - let voucherKernelContract_Buyer = new ethers.Contract(contracts.VoucherKernelContractAddress, VoucherKernel.abi, seller) - const tokenIdVoucher = VOUCHER_ID - - let txOrder = await voucherKernelContract_Buyer.triggerFinalizeVoucher( - tokenIdVoucher, {gasLimit: '4000000'}); - - const receipt = await txOrder.wait() - let parsedEvent = await findEventByName(receipt, 'LogFinalizeVoucher', '_tokenIdVoucher', '_triggeredBy') - - - if(parsedEvent) { - parsedEvent[0]._tokenIdVoucher = DB_VOUCHER_TO_MODIFY - const payload = [{ - ...parsedEvent[0], - status: "FINALIZED" - }] - console.log('Payload!'); - console.log(payload); - - if(!SEND_TO_DB) return - - try { - await axios.patch(`http://localhost:3000/user-vouchers/finalize`, payload) - } catch (error) { - console.log(error); - } +(async () => { + let voucherKernelContract_Buyer = new ethers.Contract( + contracts.VoucherKernelContractAddress, + VoucherKernel.abi, + seller + ); + const tokenIdVoucher = VOUCHER_ID; + + let txOrder = await voucherKernelContract_Buyer.triggerFinalizeVoucher( + tokenIdVoucher, + {gasLimit: '4000000'} + ); + + const receipt = await txOrder.wait(); + let parsedEvent = await findEventByName( + receipt, + 'LogFinalizeVoucher', + '_tokenIdVoucher', + '_triggeredBy' + ); + + if (parsedEvent) { + parsedEvent[0]._tokenIdVoucher = DB_VOUCHER_TO_MODIFY; + const payload = [ + { + ...parsedEvent[0], + status: 'FINALIZED', + }, + ]; + console.log('Payload!'); + console.log(payload); + + if (!SEND_TO_DB) return; + + try { + await axios.patch( + `http://localhost:3000/user-vouchers/finalize`, + payload + ); + } catch (error) { + console.log(error); } - + } })(); async function findEventByName(txReceipt, eventName, ...eventFields) { - let eventsArr = []; + let eventsArr = []; - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; - const resultObj = { - txHash: txReceipt.transactionHash - } + const resultObj = { + txHash: txReceipt.transactionHash, + }; - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - eventsArr.push(resultObj) - } + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + eventsArr.push(resultObj); } + } - return eventsArr + return eventsArr; } /** @@ -69,11 +90,11 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { _triggeredBy: '0x5aF2b312eC207D78C4de4E078270F0d8700C01e2' } */ - //should be like this - /** +//should be like this +/** { "txHash":"0xa96d9f92e73f1aa2a489a492c0cecb6d799b3cac807a93a298a84662c078b574", "_tokenIdVoucher":"57896044618658097711785492504343953926975274699741220483192166611388333031426", "_triggeredBy": "0x5aF2b312eC207D78C4de4E078270F0d8700C01e2", "status": "FINALIZED" } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/fundWallets.js b/testUserInteractions/fundWallets.js index 4f070e89..b2eb9d72 100644 --- a/testUserInteractions/fundWallets.js +++ b/testUserInteractions/fundWallets.js @@ -1,32 +1,34 @@ const ethers = require('ethers'); -const provider = new ethers.providers.JsonRpcProvider() -const {DEPLOYER_PUBLIC, BUYER_PUBLIC, SELLER_PUBLIC} = require('./config') -let wallet = new ethers.Wallet('0x7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8', provider); // account 0 from local etherlime ganache +const provider = new ethers.providers.JsonRpcProvider(); +const {DEPLOYER_PUBLIC, BUYER_PUBLIC, SELLER_PUBLIC} = require('./config'); +let wallet = new ethers.Wallet( + '0x7ab741b57e8d94dd7e1a29055646bafde7010f38a900f55bbd7647880faa6ee8', + provider +); // account 0 from local etherlime ganache (async () => { - await fundWallets(); -})() + await fundWallets(); +})(); async function fundWallets() { + const fundAmount = ethers.utils.parseEther('5'); - const fundAmount = ethers.utils.parseEther('5'); + let transactionSeller = { + to: SELLER_PUBLIC, + value: fundAmount, + }; - let transactionSeller = { - to: SELLER_PUBLIC, - value: fundAmount, - }; + let transactionBuyer = { + to: BUYER_PUBLIC, + value: fundAmount, + }; - let transactionBuyer = { - to: BUYER_PUBLIC, - value: fundAmount, - }; + let transactionDeployer = { + to: DEPLOYER_PUBLIC, + value: fundAmount, + }; - let transactionDeployer = { - to: DEPLOYER_PUBLIC, - value: fundAmount, - }; - - await wallet.sendTransaction(transactionSeller); - await wallet.sendTransaction(transactionBuyer); - await wallet.sendTransaction(transactionDeployer); -} \ No newline at end of file + await wallet.sendTransaction(transactionSeller); + await wallet.sendTransaction(transactionBuyer); + await wallet.sendTransaction(transactionDeployer); +} diff --git a/testUserInteractions/seller_cancelOrFault.js b/testUserInteractions/seller_cancelOrFault.js index 542ca44c..fecd4193 100644 --- a/testUserInteractions/seller_cancelOrFault.js +++ b/testUserInteractions/seller_cancelOrFault.js @@ -1,41 +1,48 @@ - -const VoucherKernel = require("../build/VoucherKernel.json"); +const VoucherKernel = require('../build/VoucherKernel.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { SELLER_SECRET, VOUCHER_ID, contracts } = require('./config'); +const {SELLER_SECRET, VOUCHER_ID, contracts} = require('./config'); const seller = new ethers.Wallet(SELLER_SECRET, provider); -(async() => { - let voucherKernelContract_Seller = new ethers.Contract(contracts.VoucherKernelContractAddress, VoucherKernel.abi, seller) - - let txOrder = await voucherKernelContract_Seller.cancelOrFault(VOUCHER_ID) - - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogVoucherFaultCancel', '_tokenIdVoucher') - console.log('parsedEvent'); - console.log(parsedEvent); - +(async () => { + let voucherKernelContract_Seller = new ethers.Contract( + contracts.VoucherKernelContractAddress, + VoucherKernel.abi, + seller + ); + + let txOrder = await voucherKernelContract_Seller.cancelOrFault(VOUCHER_ID); + + const receipt = await txOrder.wait(); + + let parsedEvent = await findEventByName( + receipt, + 'LogVoucherFaultCancel', + '_tokenIdVoucher' + ); + console.log('parsedEvent'); + console.log(parsedEvent); })(); async function findEventByName(txReceipt, eventName, ...eventFields) { - - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } - - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; + + const resultObj = { + txHash: txReceipt.transactionHash, + }; + + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } //EXAMPLE @@ -48,4 +55,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { qty: '10', txHash: '0x8cfa03728d03dfb868e01caf3081f29f5f30d0173fbc191166ac9289275ff804' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/seller_requestCreateOrder.js b/testUserInteractions/seller_requestCreateOrder.js index 7d906dc2..3a3b5a86 100644 --- a/testUserInteractions/seller_requestCreateOrder.js +++ b/testUserInteractions/seller_requestCreateOrder.js @@ -1,53 +1,64 @@ - -const Cashier = require("../build/Cashier.json"); -const helpers = require('../testHelpers/constants') +const Cashier = require('../build/Cashier.json'); +const helpers = require('../testHelpers/constants'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { SELLER_SECRET, contracts } = require('./config'); - -const seller = new ethers.Wallet(SELLER_SECRET, provider); - -(async() => { - let cashierContractSeller = new ethers.Contract(contracts.CashierContractAddress, Cashier.abi, seller) - const sellerDepoist = helpers.seller_deposit; - const qty = 50 - const txValue = ethers.BigNumber.from(sellerDepoist.toString()).mul(qty) - - let txOrder = await cashierContractSeller.requestCreateOrder( - helpers.ASSET_TITLE, - helpers.PROMISE_VALID_FROM, - helpers.PROMISE_VALID_TO, - helpers.product_price, - sellerDepoist, - helpers.buyer_deposit, - qty, - { value: txValue.toString(), gasLimit: 4600000 }); - - const receipt = await txOrder.wait() - - let parsedEvent = await findEventByName(receipt, 'LogOrderCreated', '_tokenIdSupply', '_seller', '_promiseId', '_quantity') - console.log('parsedEvent'); - console.log(parsedEvent); -})(); +const {SELLER_SECRET, contracts} = require('./config'); + +const seller = new ethers.Wallet(SELLER_SECRET, provider); + +(async () => { + let cashierContractSeller = new ethers.Contract( + contracts.CashierContractAddress, + Cashier.abi, + seller + ); + const sellerDepoist = helpers.seller_deposit; + const qty = 50; + const txValue = ethers.BigNumber.from(sellerDepoist.toString()).mul(qty); + let txOrder = await cashierContractSeller.requestCreateOrder( + helpers.ASSET_TITLE, + helpers.PROMISE_VALID_FROM, + helpers.PROMISE_VALID_TO, + helpers.product_price, + sellerDepoist, + helpers.buyer_deposit, + qty, + {value: txValue.toString(), gasLimit: 4600000} + ); + + const receipt = await txOrder.wait(); + + let parsedEvent = await findEventByName( + receipt, + 'LogOrderCreated', + '_tokenIdSupply', + '_seller', + '_promiseId', + '_quantity' + ); + console.log('parsedEvent'); + console.log(parsedEvent); +})(); async function findEventByName(txReceipt, eventName, ...eventFields) { + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; + + const resultObj = { + txHash: txReceipt.transactionHash, + }; - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } - - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - return resultObj - } + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + return resultObj; } + } } //EXAMPLE @@ -60,4 +71,4 @@ async function findEventByName(txReceipt, eventName, ...eventFields) { qty: '10', txHash: '0x8cfa03728d03dfb868e01caf3081f29f5f30d0173fbc191166ac9289275ff804' } - */ \ No newline at end of file + */ diff --git a/testUserInteractions/withdraw.js b/testUserInteractions/withdraw.js index 112ee13e..2f6736d7 100644 --- a/testUserInteractions/withdraw.js +++ b/testUserInteractions/withdraw.js @@ -1,70 +1,89 @@ const axios = require('axios').default; const process = { - env: { - API_URL: 'http://localhost:3000' - } + env: { + API_URL: 'http://localhost:3000', + }, }; const endpoints = { - finalize: '/user-vouchers/finalize', - createPayment: '/payments/create-payment' + finalize: '/user-vouchers/finalize', + createPayment: '/payments/create-payment', }; -const Cashier = require("../build/Cashier.json"); +const Cashier = require('../build/Cashier.json'); const ethers = require('ethers'); const provider = new ethers.providers.JsonRpcProvider(); -const { DEPLOYER_SECRET, contracts, VOUCHER_ID, DB_VOUCHER_TO_MODIFY, SEND_TO_DB} = require('./config'); -const deployer = new ethers.Wallet(DEPLOYER_SECRET, provider); - +const { + DEPLOYER_SECRET, + contracts, + VOUCHER_ID, + DB_VOUCHER_TO_MODIFY, + SEND_TO_DB, +} = require('./config'); +const deployer = new ethers.Wallet(DEPLOYER_SECRET, provider); (async () => { - let cashierContractDeployer = new ethers.Contract(contracts.CashierContractAddress, Cashier.abi, deployer) - - const txOrder = await cashierContractDeployer.withdraw([VOUCHER_ID]); - const receipt = await txOrder.wait() - - let events = await findEventByName(receipt, 'LogWithdrawal', '_caller', '_payee', '_payment') - - for (const key in events) { - events[key]._tokenIdVoucher = DB_VOUCHER_TO_MODIFY; - } - console.log('events'); - console.log(events); - - if (!SEND_TO_DB) return - await sendPayments(events) - -})() + let cashierContractDeployer = new ethers.Contract( + contracts.CashierContractAddress, + Cashier.abi, + deployer + ); + + const txOrder = await cashierContractDeployer.withdraw([VOUCHER_ID]); + const receipt = await txOrder.wait(); + + let events = await findEventByName( + receipt, + 'LogWithdrawal', + '_caller', + '_payee', + '_payment' + ); + + for (const key in events) { + events[key]._tokenIdVoucher = DB_VOUCHER_TO_MODIFY; + } + console.log('events'); + console.log(events); + + if (!SEND_TO_DB) return; + await sendPayments(events); +})(); async function findEventByName(txReceipt, eventName, ...eventFields) { - let eventsArr = []; - - for (const key in txReceipt.events) { - if (txReceipt.events[key].event == eventName) { - const event = txReceipt.events[key] - - const resultObj = { - txHash: txReceipt.transactionHash - } - - for (let index = 0; index < eventFields.length; index++) { - resultObj[eventFields[index]] = event.args[eventFields[index]].toString(); - } - eventsArr.push(resultObj) - } + let eventsArr = []; + + for (const key in txReceipt.events) { + if (txReceipt.events[key].event == eventName) { + const event = txReceipt.events[key]; + + const resultObj = { + txHash: txReceipt.transactionHash, + }; + + for (let index = 0; index < eventFields.length; index++) { + resultObj[eventFields[index]] = event.args[ + eventFields[index] + ].toString(); + } + eventsArr.push(resultObj); } + } - return eventsArr + return eventsArr; } async function sendPayments(events) { - try { - await axios.post(`${process.env.API_URL}${endpoints.createPayment}`, events) - } catch (error) { - console.log(error.response.data); - } + try { + await axios.post( + `${process.env.API_URL}${endpoints.createPayment}`, + events + ); + } catch (error) { + console.log(error.response.data); + } } /** Example events arr @@ -83,4 +102,3 @@ async function sendPayments(events) { _payment: '11000000000000000' }] */ - diff --git a/truffle-config.js b/truffle-config.js index 5911cb4c..eeae6bfa 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -8,143 +8,146 @@ * * truffleframework.com/docs/advanced/configuration * - * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) - * to sign your transactions before they're sent to a remote public node. Infura accounts - * are available for free at: infura.io/register. + * To deploy via Infura you'll need a wallet provider (like + * truffle-hdwallet-provider) to sign your transactions before they're sent to + * a remote public node. Infura accounts are available for free at: + * infura.io/register. * - * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate - * public/private key pairs. If you're publishing your code to GitHub make sure you load this - * phrase from a file you've .gitignored so it doesn't accidentally become public. + * You'll also need a mnemonic - the twelve word phrase the wallet uses to + * generate public/private key pairs. If you're publishing your code to GitHub + * make sure you load this phrase from a file you've .gitignored so it doesn't + * accidentally become public. * */ -const HDWalletProvider = require('@truffle/hdwallet-provider'); -const fs = require('fs'); -const pk = fs.readFileSync(".secret").toString().trim(); +const HDWalletProvider = require('@truffle/hdwallet-provider') +const fs = require('fs') -require('dotenv').config(); - -// const config = require('./common/config'); -// const config_networks = config("networks"); - -// const options = { -// contracts_build_directory: './drizzle/app/src/contracts', +require('dotenv').config() module.exports = { - /** - * Networks define how you connect to your ethereum client and let you set the - * defaults web3 uses to send transactions. If you don't specify one truffle - * will spin up a development blockchain for you on port 9545 when you - * run `develop` or `test`. You can ask a truffle command to use a specific - * network from the command line, e.g - * - * $ truffle test --network - */ - - networks: { - // Useful for testing. The `development` name is special - truffle uses it by default - // if it's defined here and no other network is specified at the command line. - // You should run a client (like ganache-cli, geth or parity) in a separate terminal - // tab if you use this network and you must also set the `host`, `port` and `network_id` - // options below to some value. - // - development: { - host: '127.0.0.1', // Localhost (default: none) - port: 8545, // Standard Ethereum port (default: none) - network_id: '*', // Any network (default: none) - }, - - coverage: { - host: '127.0.0.1', // Localhost (default: none) - port: 8555, // Test Coverage Port - network_id: '*', // Any network (default: none) - }, - - ropsten: { - provider: () => new HDWalletProvider(pk, "http://localhost:8545"), - network_id: 3, - gas: 8000000, - }, - - rinkeby: { - provider: function() { - return new HDWalletProvider( - `${process.env.PK}`, - `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}` - ) - }, - network_id: 4 - }, - - // extend options with JSON config settings - // this is a complete list of config files in /common/json/config-*.json - //...config_networks, - - // host: "100.115.92.198", // Local IP for costini - // port: 8545, // Standard Ethereum port (default: none) - // network_id: "*", // Any network (default: none) - // }, - - - // Another network with more advanced options... - // advanced: { - // port: 8777, // Custom port - // network_id: 1342, // Custom network - // gas: 8500000, // Gas sent with each transaction (default: ~6700000) - // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) - // from:
, // Account to send txs from (default: accounts[0]) - // websockets: true // Enable EventEmitter interface for web3 (default: false) - // }, - - // Useful for deploying to a public network. - // NB: It's important to wrap the provider as a function. - // ropsten: { - // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), - // network_id: 3, // Ropsten's id - // gas: 5500000, // Ropsten has a lower block limit than mainnet - // confirmations: 2, // # of confs to wait between deployments. (default: 0) - // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) - // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) - // }, - - // Useful for private networks - // private: { - // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), - // network_id: 2111, // This network is yours, in the cloud. - // production: true // Treats this network as if it was a public net. (default: false) - // } + /** + * Networks define how you connect to your ethereum client and let you set + * the defaults web3 uses to send transactions. If you don't specify one + * truffle will spin up a development blockchain for you on port 9545 when + * you run `develop` or `test`. You can ask a truffle command to use a + * specific network from the command line, e.g + * + * $ truffle test --network + */ + + networks: { + // Useful for testing. The `development` name is special - truffle uses + // it by default if it's defined here and no other network is specified + // at the command line. + // + // You should run a client (like ganache-cli, geth or parity) in a + // separate terminal tab if you use this network and you must also set + // the `host`, `port` and `network_id` + // options below to some value. + // + development: { + host: '127.0.0.1', // Localhost (default: none) + port: 8545, // Standard Ethereum port (default: none) + network_id: '*' // Any network (default: none) }, - plugins: [ - "solidity-coverage", - "truffle-plugin-verify" - ], + test: { + host: process.env.HOST, // Localhost (default: none) + port: process.env.PORT, // Standard Ethereum port (default: none) + network_id: '*' // Any network (default: none) + }, - api_keys: { - etherscan: process.env.ETHERSCAN_API_KEY + coverage: { + host: '127.0.0.1', // Localhost (default: none) + port: 8555, // Test Coverage Port + network_id: '*' // Any network (default: none) }, - // Set default mocha options here, use special reporters etc. - mocha: { - timeout: 120000 + ropsten: { + provider: () => { + return new HDWalletProvider( + fs.readFileSync(".secret").toString().trim(), + "http://localhost:8545") + }, + network_id: 3, + gas: 8000000 }, - // Configure your compilers - compilers: { - solc: { - version: '0.6.6', // Fetch exact version from solc-bin (default: truffle's version) - // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) - settings: { // See the solidity docs for advice about optimization and evmVersion - optimizer: { - enabled: true, - runs: 200 - }, - // evmVersion: "byzantium" - // } - - }, - - }, + rinkeby: { + provider: () => { + return new HDWalletProvider( + process.env.PK, + `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}` + ) + }, + network_id: 4 } -} -//module.exports = options; // + // Another network with more advanced options... + // advanced: { + // port: 8777, // Custom port + // network_id: 1342, // Custom network + // gas: 8500000, // Gas sent with each transaction + // // (default: ~6700000) + // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) + // from:
, // Account to send txs from + // // (default: accounts[0]) + // websockets: true // Enable EventEmitter interface for web3 + // // (default: false) + // }, + + // Useful for deploying to a public network. + // NB: It's important to wrap the provider as a function. + // ropsten: { + // provider: () => { + // return new HDWalletProvider( + // mnemonic, + // `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`) + // }, + // network_id: 3, // Ropsten's id + // gas: 5500000, // Ropsten has a lower block limit than mainnet + // confirmations: 2, // # of confs to wait between deployments. + // // (default: 0) + // timeoutBlocks: 200, // # of blocks before a deployment times out + // // (minimum/default: 50) + // skipDryRun: true // Skip dry run before migrations? + // // (default: false for public nets ) + // }, + + // Useful for private networks + // private: { + // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), + // network_id: 2111, // This network is yours, in the cloud. + // production: true // Treats this network as if it was a public net. + // // (default: false) + // } + }, + + plugins: [ + "solidity-coverage", + "truffle-plugin-verify" + ], + + api_keys: { + etherscan: process.env.ETHERSCAN_API_KEY + }, + + mocha: { + timeout: 120000 + }, + + compilers: { + solc: { + // Fetch exact version from solc-bin (default: truffle's version) + version: '0.6.6', + + // See the solidity docs for advice about optimization and evmVersion + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } + } +}