diff --git a/.dockerignore b/.dockerignore index 067d643e..73b2734c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,16 +1,16 @@ -node_modules -deploy/node_modules +**/node_modules .git .gitignore .dockerignore -deploy/.env deploy/*.config -deploy/*.env +deploy/*.env* +!deploy/.env.example docker-compose.yml Dockerfile *.log flats contracts.sublime-project contracts.sublime-workspace -upgrade/.env* +upgrade/*.env* !upgrade/.env.example +build/ diff --git a/.editorconfig b/.editorconfig index 5d196c7c..d808e42d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,6 +10,6 @@ insert_final_newline = true [*.ts] indent_style = tab -[{package.json,.travis.yml}] +[{package.json}] indent_style = space indent_size = 4 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..2f72b1aa --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,92 @@ +name: tokenbridge-contracts + +on: [push] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + id: npm-cache + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} + - run: npm install + if: ${{ !steps.npm-cache.outputs.cache-hit }} + - run: npm run lint + test: + runs-on: ubuntu-latest + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + id: npm-cache + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} + - run: npm install + if: ${{ !steps.npm-cache.outputs.cache-hit }} + - run: npm run test + gasreport: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + id: npm-cache + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} + - run: npm install + if: ${{ !steps.npm-cache.outputs.cache-hit }} + - run: npm run test:gasreport:ci + env: + CC_SECRET: ${{ secrets.CC_SECRET }} + coverage: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/setup-node@v1 + with: + node-version: 10 + - uses: actions/checkout@v2 + - uses: actions/cache@v2 + id: npm-cache + with: + path: node_modules + key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }} + - run: npm install + if: ${{ !steps.npm-cache.outputs.cache-hit }} + - run: npm run coverage + - name: Coveralls + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + publish: + runs-on: ubuntu-latest + needs: + - lint + - test + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop' || startsWith(github.ref, 'refs/tags') + steps: + - uses: actions/checkout@v2 + - if: startsWith(github.ref, 'refs/tags') + run: echo "::set-env name=DOCKER_TAGS::${GITHUB_REF#refs/tags/},latest" + - if: startsWith(github.ref, 'refs/heads') + run: echo "::set-env name=DOCKER_TAGS::${GITHUB_REF#refs/heads/}-${GITHUB_SHA::8}" + - uses: docker/build-push-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + repository: poanetwork/tokenbridge-contracts + always_pull: true + tags: ${{ env.DOCKER_TAGS }} diff --git a/.gitignore b/.gitignore index 96eb2e0e..3cfab76d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,8 @@ flats coverage *.sublime-* .0x-artifacts -upgrade/.env* -deploy/.env deploy/*.config -deploy/*.env +deploy/*.env* +!deploy/.env.example +upgrade/*.env* +!upgrade/.env.example diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7e08c5b6..00000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -dist: trusty -sudo: required -group: beta -language: node_js -node_js: - - "10" -cache: - yarn: true -env: - - $TASK=lint - - $TASK=test - - $TASK=coverage - - $TASK=test:gasreport:ci -script: "npm run $TASK" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c67c40f..3079b1f5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Thank your for contributing to this project! We welcome collaborators and expect users to follow our [code of conduct](CODE_OF_CONDUCT.md) when submitting code or comments. -1. Fork the repo ( https://github.com/poanetwork/poa-bridge-contracts/fork ). +1. Fork the repo ( https://github.com/poanetwork/tokenbridge-contracts/fork ). 2. Create your feature branch (`git checkout -b my-new-feature`). 3. Write tests that cover your work. 4. Commit your changes (`git commit -am 'Add some feature'`). @@ -19,7 +19,7 @@ Thank your for contributing to this project! We welcome collaborators and expect In either case, try to write a regression test that fails because of the bug but passes with your fix. ### Issues -Creating and discussing [Issues](https://github.com/poanetwork/poa-bridge-contracts/issues) provides significant value to the project. If you find a bug you can report it in an Issue. +Creating and discussing [Issues](https://github.com/poanetwork/tokenbridge-contracts/issues) provides significant value to the project. If you find a bug you can report it in an Issue. ### Pull Requests All pull requests should include: diff --git a/Dockerfile b/Dockerfile index 5d0ceee3..03b098db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,10 @@ -FROM node:10 - -RUN apt-get update -RUN apt-get install -y netcat -RUN apt-get clean +FROM node:10 as contracts WORKDIR /contracts COPY package.json . COPY package-lock.json . -RUN npm install - -COPY ./deploy/package.json ./deploy/ -COPY ./deploy/package-lock.json ./deploy/ -RUN cd ./deploy; npm install; cd .. - -COPY ./upgrade/package.json ./upgrade/ -COPY ./upgrade/package-lock.json ./upgrade/ -RUN cd ./upgrade; npm install; cd .. - -COPY ./scripts ./scripts +RUN npm install --only=prod COPY truffle-config.js truffle-config.js COPY ./contracts ./contracts @@ -27,16 +13,23 @@ RUN npm run compile COPY flatten.sh flatten.sh RUN bash flatten.sh -COPY .eslintignore .eslintignore -COPY .eslintrc .eslintrc -COPY .prettierrc .prettierrc +FROM node:10 + +WORKDIR /contracts +COPY --from=contracts /contracts/build ./build +COPY --from=contracts /contracts/flats ./flats + +COPY ./deploy/package.json ./deploy/ +COPY ./deploy/package-lock.json ./deploy/ +RUN cd ./deploy; npm install --only=prod; cd .. + +COPY ./upgrade/package.json ./upgrade/ +COPY ./upgrade/package-lock.json ./upgrade/ +RUN cd ./upgrade; npm install --only=prod; cd .. COPY ./upgrade ./upgrade COPY deploy.sh deploy.sh COPY ./deploy ./deploy -COPY .solhint.json .solhint.json -COPY codechecks.yml codechecks.yml -COPY ./test ./test ENV PATH="/contracts/:${PATH}" ENV NOFLAT=true diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..5d0ceee3 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,42 @@ +FROM node:10 + +RUN apt-get update +RUN apt-get install -y netcat +RUN apt-get clean + +WORKDIR /contracts + +COPY package.json . +COPY package-lock.json . +RUN npm install + +COPY ./deploy/package.json ./deploy/ +COPY ./deploy/package-lock.json ./deploy/ +RUN cd ./deploy; npm install; cd .. + +COPY ./upgrade/package.json ./upgrade/ +COPY ./upgrade/package-lock.json ./upgrade/ +RUN cd ./upgrade; npm install; cd .. + +COPY ./scripts ./scripts + +COPY truffle-config.js truffle-config.js +COPY ./contracts ./contracts +RUN npm run compile + +COPY flatten.sh flatten.sh +RUN bash flatten.sh + +COPY .eslintignore .eslintignore +COPY .eslintrc .eslintrc +COPY .prettierrc .prettierrc + +COPY ./upgrade ./upgrade +COPY deploy.sh deploy.sh +COPY ./deploy ./deploy +COPY .solhint.json .solhint.json +COPY codechecks.yml codechecks.yml +COPY ./test ./test + +ENV PATH="/contracts/:${PATH}" +ENV NOFLAT=true diff --git a/README.md b/README.md index a84c76cf..b40e5f9a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![Join the chat at https://gitter.im/poanetwork/poa-bridge](https://badges.gitter.im/poanetwork/poa-bridge.svg)](https://gitter.im/poanetwork/poa-bridge?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://api.travis-ci.org/poanetwork/tokenbridge-contracts.svg?branch=master)](https://travis-ci.org/poanetwork/tokenbridge-contracts) +[![Build Status](https://github.com/poanetwork/tokenbridge-contracts/workflows/tokenbridge-contracts/badge.svg?branch=master)](https://github.com/poanetwork/tokenbridge-contracts/workflows/tokenbridge-contracts/badge.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/github/poanetwork/tokenbridge-contracts/badge.svg?branch=master)](https://coveralls.io/github/poanetwork/tokenbridge-contracts?branch=master) # POA Bridge Smart Contracts diff --git a/contracts/interfaces/ERC677.sol b/contracts/interfaces/ERC677.sol index 06f2ef3a..388801a5 100644 --- a/contracts/interfaces/ERC677.sol +++ b/contracts/interfaces/ERC677.sol @@ -9,3 +9,8 @@ contract ERC677 is ERC20 { function increaseAllowance(address spender, uint256 addedValue) public returns (bool); function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool); } + +contract LegacyERC20 { + function transfer(address _spender, uint256 _value) public; // returns (bool); + function transferFrom(address _owner, address _spender, uint256 _value) public; // returns (bool); +} diff --git a/contracts/upgradeable_contracts/BasicAMBMediator.sol b/contracts/upgradeable_contracts/BasicAMBMediator.sol index cece0d33..62bba538 100644 --- a/contracts/upgradeable_contracts/BasicAMBMediator.sol +++ b/contracts/upgradeable_contracts/BasicAMBMediator.sol @@ -15,7 +15,7 @@ contract BasicAMBMediator is Ownable { bytes32 internal constant REQUEST_GAS_LIMIT = 0x2dfd6c9f781bb6bbb5369c114e949b69ebb440ef3d4dd6b2836225eb1dc3a2be; // keccak256(abi.encodePacked("requestGasLimit")) /** - * @dev Throws if caller on the other side if not an associated mediator. + * @dev Throws if caller on the other side is not an associated mediator. */ modifier onlyMediator { require(msg.sender == address(bridgeContract())); diff --git a/contracts/upgradeable_contracts/ERC20Bridge.sol b/contracts/upgradeable_contracts/ERC20Bridge.sol index e69b8377..bf2005a1 100644 --- a/contracts/upgradeable_contracts/ERC20Bridge.sol +++ b/contracts/upgradeable_contracts/ERC20Bridge.sol @@ -16,23 +16,14 @@ contract ERC20Bridge is BasicForeignBridge { addressStorage[ERC20_TOKEN] = _token; } - function _relayTokens(address _sender, address _receiver, uint256 _amount) internal { + function relayTokens(address _receiver, uint256 _amount) external { require(_receiver != address(0)); require(_receiver != address(this)); require(_amount > 0); require(withinLimit(_amount)); addTotalSpentPerDay(getCurrentDay(), _amount); - erc20token().transferFrom(_sender, address(this), _amount); + erc20token().transferFrom(msg.sender, address(this), _amount); emit UserRequestForAffirmation(_receiver, _amount); } - - function relayTokens(address _from, address _receiver, uint256 _amount) external { - require(_from == msg.sender || _from == _receiver); - _relayTokens(_from, _receiver, _amount); - } - - function relayTokens(address _receiver, uint256 _amount) external { - _relayTokens(msg.sender, _receiver, _amount); - } } diff --git a/contracts/upgradeable_contracts/MediatorMessagesGuard.sol b/contracts/upgradeable_contracts/MediatorMessagesGuard.sol deleted file mode 100644 index 3d4892b8..00000000 --- a/contracts/upgradeable_contracts/MediatorMessagesGuard.sol +++ /dev/null @@ -1,68 +0,0 @@ -pragma solidity 0.4.24; - -import "../upgradeability/EternalStorage.sol"; - -/** -* @title MediatorMessagesGuard -* @dev AMB bridge supports one message per transaction. This contract provides functionality to limit the number of -* messages that a mediator can send to the bridge on a single transaction. -*/ -contract MediatorMessagesGuard is EternalStorage { - bytes32 private constant MESSAGES_CONTROL_BITMAP = 0x3caea4a73ee3aee2c0babf273b625b68b12a4f38d694d7cb051cb4b944e5e802; // keccak256(abi.encodePacked("messagesControlBitmap")) - - /** - * @dev Tells the status of the lock. - * @return the status of the lock. - */ - function getMessagesControlBitmap() private view returns (uint256) { - return uintStorage[MESSAGES_CONTROL_BITMAP]; - } - - /** - * @dev Sets the status of the lock. - * @param _bitmap the new status for the lock - */ - function setMessagesControlBitmap(uint256 _bitmap) private { - uintStorage[MESSAGES_CONTROL_BITMAP] = _bitmap; - } - - /** - * @dev Tells if messages are restricted and the limit was reached. - * @param _bitmap the status of the lock - */ - function messagesRestrictedAndLimitReached(uint256 _bitmap) private pure returns (bool) { - return (_bitmap == ((2**255) | 1)); - } - - /** - * @dev Tells if messages are restricted. - * @param _bitmap the status of the lock - */ - function messagesRestricted(uint256 _bitmap) private pure returns (bool) { - return (_bitmap == 2**255); - } - - /** - * @dev Enable the lock to limit the number of messages to send to the AMB bridge - */ - function enableMessagesRestriction() internal { - setMessagesControlBitmap(2**255); - } - - /** - * @dev Disable the lock to limit the number of messages to send to the AMB bridge - */ - function disableMessagesRestriction() internal { - setMessagesControlBitmap(0); - } - - modifier bridgeMessageAllowed { - uint256 bm = getMessagesControlBitmap(); - require(!messagesRestrictedAndLimitReached(bm)); - if (messagesRestricted(bm)) { - setMessagesControlBitmap(bm | 1); - } - /* solcov ignore next */ - _; - } -} diff --git a/contracts/upgradeable_contracts/VersionableBridge.sol b/contracts/upgradeable_contracts/VersionableBridge.sol index f0dc6048..75f61937 100644 --- a/contracts/upgradeable_contracts/VersionableBridge.sol +++ b/contracts/upgradeable_contracts/VersionableBridge.sol @@ -2,7 +2,7 @@ pragma solidity 0.4.24; contract VersionableBridge { function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (5, 0, 0); + return (5, 1, 0); } /* solcov ignore next */ diff --git a/contracts/upgradeable_contracts/amb_erc20_to_native/BasicAMBErc20ToNative.sol b/contracts/upgradeable_contracts/amb_erc20_to_native/BasicAMBErc20ToNative.sol index f581d330..b256d30e 100644 --- a/contracts/upgradeable_contracts/amb_erc20_to_native/BasicAMBErc20ToNative.sol +++ b/contracts/upgradeable_contracts/amb_erc20_to_native/BasicAMBErc20ToNative.sol @@ -51,7 +51,7 @@ contract BasicAMBErc20ToNative is Initializable, Upgradeable, Claimable, Version * @return patch value of the version */ function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (1, 0, 0); + return (1, 1, 0); } /** diff --git a/contracts/upgradeable_contracts/amb_erc20_to_native/ForeignAMBErc20ToNative.sol b/contracts/upgradeable_contracts/amb_erc20_to_native/ForeignAMBErc20ToNative.sol index 5293335c..152914f8 100644 --- a/contracts/upgradeable_contracts/amb_erc20_to_native/ForeignAMBErc20ToNative.sol +++ b/contracts/upgradeable_contracts/amb_erc20_to_native/ForeignAMBErc20ToNative.sol @@ -58,18 +58,6 @@ contract ForeignAMBErc20ToNative is BasicAMBErc20ToNative, ReentrancyGuard, Base return _erc677token(); } - /** - * @dev It will initiate the bridge operation that will lock the amount of tokens transferred and mint the native tokens on - * the other network. The user should first call Approve method of the ERC677 token. - * @param _from address that will transfer the tokens to be locked. - * @param _receiver address that will receive the native tokens on the other network. - * @param _value amount of tokens to be transferred to the other network. - */ - function relayTokens(address _from, address _receiver, uint256 _value) external { - require(_from == msg.sender || _from == _receiver); - _relayTokens(_from, _receiver, _value); - } - /** * @dev It will initiate the bridge operation that will lock the amount of tokens transferred and mint the native tokens on * the other network. The user should first call Approve method of the ERC677 token. @@ -77,7 +65,20 @@ contract ForeignAMBErc20ToNative is BasicAMBErc20ToNative, ReentrancyGuard, Base * @param _value amount of tokens to be transferred to the other network. */ function relayTokens(address _receiver, uint256 _value) external { - _relayTokens(msg.sender, _receiver, _value); + // This lock is to prevent calling passMessage twice. + // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract + // which will call passMessage. + require(!lock()); + ERC677 token = _erc677token(); + address to = address(this); + require(withinLimit(_value)); + addTotalSpentPerDay(getCurrentDay(), _value); + _setMediatorBalance(mediatorBalance().add(_value)); + + setLock(true); + token.transferFrom(msg.sender, to, _value); + setLock(false); + bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver)); } /** @@ -181,31 +182,6 @@ contract ForeignAMBErc20ToNative is BasicAMBErc20ToNative, ReentrancyGuard, Base } } - /** - * @dev Validates that the token amount is inside the limits, calls transferFrom to transfer the tokens to the contract - * and invokes the method to lock the tokens and mint the native tokens on the other network. - * The user should first call Approve method of the ERC677 token. - * @param _from address that will transfer the tokens to be locked. - * @param _receiver address that will receive the native tokens on the other network. - * @param _value amount of tokens to be transferred to the other network. - */ - function _relayTokens(address _from, address _receiver, uint256 _value) internal { - // This lock is to prevent calling passMessage twice. - // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract - // which will call passMessage. - require(!lock()); - ERC677 token = _erc677token(); - address to = address(this); - require(withinLimit(_value)); - addTotalSpentPerDay(getCurrentDay(), _value); - _setMediatorBalance(mediatorBalance().add(_value)); - - setLock(true); - token.transferFrom(_from, to, _value); - setLock(false); - bridgeSpecificActionsOnTokenTransfer(token, _from, _value, abi.encodePacked(_receiver)); - } - /** * @dev Tells the address of the mediator contract on the other side, used by chooseReceiver method * to avoid sending the native tokens to that address. diff --git a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol index c1b5ed0a..9b657fc7 100644 --- a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol +++ b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicAMBErc677ToErc677.sol @@ -62,12 +62,7 @@ contract BasicAMBErc677ToErc677 is return mediatorContractOnOtherSide(); } - function relayTokens(address _from, address _receiver, uint256 _value) external { - require(_from == msg.sender || _from == _receiver); - _relayTokens(_from, _receiver, _value); - } - - function _relayTokens(address _from, address _receiver, uint256 _value) internal { + function relayTokens(address _receiver, uint256 _value) external { // This lock is to prevent calling passMessage twice if a ERC677 token is used. // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract // which will call passMessage. @@ -78,13 +73,9 @@ contract BasicAMBErc677ToErc677 is addTotalSpentPerDay(getCurrentDay(), _value); setLock(true); - token.transferFrom(_from, to, _value); + token.transferFrom(msg.sender, to, _value); setLock(false); - bridgeSpecificActionsOnTokenTransfer(token, _from, _value, abi.encodePacked(_receiver)); - } - - function relayTokens(address _receiver, uint256 _value) external { - _relayTokens(msg.sender, _receiver, _value); + bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver)); } function onTokenTransfer(address _from, uint256 _value, bytes _data) external returns (bool) { @@ -99,7 +90,7 @@ contract BasicAMBErc677ToErc677 is } function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (1, 1, 0); + return (1, 2, 0); } function getBridgeMode() external pure returns (bytes4 _data) { diff --git a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicStakeTokenMediator.sol b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicStakeTokenMediator.sol index 926f2292..d069a95a 100644 --- a/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicStakeTokenMediator.sol +++ b/contracts/upgradeable_contracts/amb_erc677_to_erc677/BasicStakeTokenMediator.sol @@ -4,7 +4,7 @@ import "./BasicAMBErc677ToErc677.sol"; contract BasicStakeTokenMediator is BasicAMBErc677ToErc677 { function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (1, 0, 0); + return (1, 1, 0); } function getBridgeMode() external pure returns (bytes4 _data) { diff --git a/contracts/upgradeable_contracts/amb_erc677_to_erc677/callflows.md b/contracts/upgradeable_contracts/amb_erc677_to_erc677/callflows.md index a772d352..cd3903b4 100644 --- a/contracts/upgradeable_contracts/amb_erc677_to_erc677/callflows.md +++ b/contracts/upgradeable_contracts/amb_erc677_to_erc677/callflows.md @@ -321,25 +321,24 @@ This will allow to the mediator contract to call the `transferFrom` method from ```= >>Mediator BasicAMBErc677ToErc677::relayTokens -..BasicAMBErc677ToErc677::_relayTokens >>Token -....ERC677BridgeToken::transferFrom -......ERC677BridgeToken::_superTransferFrom -........ERC20Permittable::transferFrom -..........ERC20::_transfer -............emit Transfer -......ERC677BridgeToken::_callAfterTransfer -........ERC677BridgeToken::_contractFallback +..ERC677BridgeToken::transferFrom +....ERC677BridgeToken::_superTransferFrom +......ERC20Permittable::transferFrom +........ERC20::_transfer +..........emit Transfer +....ERC677BridgeToken::_callAfterTransfer +......ERC677BridgeToken::_contractFallback >>Mediator -..........BasicAMBErc677ToErc677::onTokenTransfer -............ForeignStakeTokenMediator::bridgeSpecificActionsOnTokenTransfer -..............TokenBridgeMediator::passMessage -................TokenBridgeMediator::setMessageHashValue -................TokenBridgeMediator::setMessageHashRecipient +........BasicAMBErc677ToErc677::onTokenTransfer +..........ForeignStakeTokenMediator::bridgeSpecificActionsOnTokenTransfer +............TokenBridgeMediator::passMessage +..............TokenBridgeMediator::setMessageHashValue +..............TokenBridgeMediator::setMessageHashRecipient >>Bridge -................MessageDelivery::requireToPassMessage -..................ForeignAMB::emitEventOnMessageRequest -....................emit UserRequestForAffirmation +..............MessageDelivery::requireToPassMessage +................ForeignAMB::emitEventOnMessageRequest +..................emit UserRequestForAffirmation ``` #### Execution @@ -355,30 +354,29 @@ The mediator on the Home side also provides the `relayTokens` method. Prior to i ```= >>Mediator BasicAMBErc677ToErc677::relayTokens -..BasicAMBErc677ToErc677::_relayTokens >>Token -....ERC677BridgeTokenRewardable::transferFrom -......PermittableToken::transferFrom -........emit Transfer -........ERC677BridgeToken::callAfterTransfer -..........ERC677BridgeToken::contractFallback +..ERC677BridgeTokenRewardable::transferFrom +....PermittableToken::transferFrom +......emit Transfer +......ERC677BridgeToken::callAfterTransfer +........ERC677BridgeToken::contractFallback >>Mediator -............BasicAMBErc677ToErc677::onTokenTransfer -..............HomeStakeTokenMediator::bridgeSpecificActionsOnTokenTransfer +..........BasicAMBErc677ToErc677::onTokenTransfer +............HomeStakeTokenMediator::bridgeSpecificActionsOnTokenTransfer >>Token -................BurnableToken::burn -..................BurnableToken::_burn +..............BurnableToken::burn +................BurnableToken::_burn >>Mediator -................TokenBridgeMediator::passMessage -..................TokenBridgeMediator::setMessageHashValue -..................TokenBridgeMediator::setMessageHashRecipient +..............TokenBridgeMediator::passMessage +................TokenBridgeMediator::setMessageHashValue +................TokenBridgeMediator::setMessageHashRecipient >>Bridge -..................MessageDelivery::requireToPassMessage -....................ForeignAMB::emitEventOnMessageRequest -......................emit UserRequestForSignature +................MessageDelivery::requireToPassMessage +..................ForeignAMB::emitEventOnMessageRequest +....................emit UserRequestForSignature >>BlockReward -................HomeStakeTokenFeeManager::_distributeFee -..................BlockRewardAuRaTokens::addBridgeTokenRewardReceivers +..............HomeStakeTokenFeeManager::_distributeFee +................BlockRewardAuRaTokens::addBridgeTokenRewardReceivers ``` #### Execution diff --git a/contracts/upgradeable_contracts/amb_native_to_erc20/BasicAMBNativeToErc20.sol b/contracts/upgradeable_contracts/amb_native_to_erc20/BasicAMBNativeToErc20.sol index 2a422fd0..e7e67bb8 100644 --- a/contracts/upgradeable_contracts/amb_native_to_erc20/BasicAMBNativeToErc20.sol +++ b/contracts/upgradeable_contracts/amb_native_to_erc20/BasicAMBNativeToErc20.sol @@ -62,7 +62,7 @@ contract BasicAMBNativeToErc20 is * @return patch value of the version */ function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (1, 0, 1); + return (1, 1, 0); } /** diff --git a/contracts/upgradeable_contracts/amb_native_to_erc20/ForeignAMBNativeToErc20.sol b/contracts/upgradeable_contracts/amb_native_to_erc20/ForeignAMBNativeToErc20.sol index 9f60c152..63a64b5f 100644 --- a/contracts/upgradeable_contracts/amb_native_to_erc20/ForeignAMBNativeToErc20.sol +++ b/contracts/upgradeable_contracts/amb_native_to_erc20/ForeignAMBNativeToErc20.sol @@ -4,14 +4,13 @@ import "./BasicAMBNativeToErc20.sol"; import "../BaseERC677Bridge.sol"; import "../../interfaces/IBurnableMintableERC677Token.sol"; import "../ReentrancyGuard.sol"; -import "../MediatorMessagesGuard.sol"; /** * @title ForeignAMBNativeToErc20 * @dev Foreign mediator implementation for native-to-erc20 bridge intended to work on top of AMB bridge. * It is design to be used as implementation contract of EternalStorageProxy contract. */ -contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, BaseERC677Bridge, MediatorMessagesGuard { +contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, BaseERC677Bridge { /** * @dev Stores the initial parameters of the mediator. * @param _bridgeContract the address of the AMB bridge contract. @@ -95,24 +94,10 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base /** * @dev It will initiate the bridge operation that will burn the amount of tokens transferred and unlock the native tokens on * the other network. The user should first call Approve method of the ERC677 token. - * @param _from address that will transfer the tokens to be burned. * @param _receiver address that will receive the native tokens on the other network. * @param _value amount of tokens to be transferred to the other network. */ - function relayTokens(address _from, address _receiver, uint256 _value) external { - require(_from == msg.sender || _from == _receiver); - _relayTokens(_from, _receiver, _value); - } - - /** - * @dev Validates that the token amount is inside the limits, calls transferFrom to transfer the tokens to the contract - * and invokes the method to burn the tokens and unlock the native tokens on the other network. - * The user should first call Approve method of the ERC677 token. - * @param _from address that will transfer the tokens to be burned. - * @param _receiver address that will receive the native tokens on the other network. - * @param _value amount of tokens to be transferred to the other network. - */ - function _relayTokens(address _from, address _receiver, uint256 _value) internal { + function relayTokens(address _receiver, uint256 _value) external { // This lock is to prevent calling passMessage twice. // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract // which will call passMessage. @@ -123,19 +108,9 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base addTotalSpentPerDay(getCurrentDay(), _value); setLock(true); - token.transferFrom(_from, to, _value); + token.transferFrom(msg.sender, to, _value); setLock(false); - bridgeSpecificActionsOnTokenTransfer(token, _from, _value, abi.encodePacked(_receiver)); - } - - /** - * @dev It will initiate the bridge operation that will burn the amount of tokens transferred and unlock the native tokens on - * the other network. The user should first call Approve method of the ERC677 token. - * @param _receiver address that will receive the native tokens on the other network. - * @param _value amount of tokens to be transferred to the other network. - */ - function relayTokens(address _receiver, uint256 _value) external { - _relayTokens(msg.sender, _receiver, _value); + bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver)); } /** @@ -147,7 +122,7 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base * @param _data this parameter could contain the address of an alternative receiver of the tokens on the other network, * otherwise it will be empty. */ - function onTokenTransfer(address _from, uint256 _value, bytes _data) external bridgeMessageAllowed returns (bool) { + function onTokenTransfer(address _from, uint256 _value, bytes _data) external returns (bool) { ERC677 token = erc677token(); require(msg.sender == address(token)); if (!lock()) { @@ -199,21 +174,4 @@ contract ForeignAMBNativeToErc20 is BasicAMBNativeToErc20, ReentrancyGuard, Base function bridgeContractOnOtherSide() internal view returns (address) { return mediatorContractOnOtherSide(); } - - /** - * @dev Distributes the provided amount of fees. - * @param _feeManager address of the fee manager contract - * @param _fee total amount to be distributed to the list of reward accounts. - * @param _messageId id of the message that generated fee distribution - */ - function distributeFee(IMediatorFeeManager _feeManager, uint256 _fee, bytes32 _messageId) internal { - // Right now, AMB bridge supports only one message per transaction. - // The receivers of the fee could try to send back the fees through the mediator, - // so here we add a lock to limit the number of messages that the mediator can send to the bridge, - // allowing a maximum of 1 message - enableMessagesRestriction(); - super.distributeFee(_feeManager, _fee, _messageId); - // remove the lock - disableMessagesRestriction(); - } } diff --git a/contracts/upgradeable_contracts/amb_native_to_erc20/callflows.md b/contracts/upgradeable_contracts/amb_native_to_erc20/callflows.md index f942786c..7d4b0753 100644 --- a/contracts/upgradeable_contracts/amb_native_to_erc20/callflows.md +++ b/contracts/upgradeable_contracts/amb_native_to_erc20/callflows.md @@ -49,26 +49,22 @@ BasicForeignAMB::executeSignatures >>Mediator ........TokenBridgeMediator::handleBridgedTokens ..........ForeignAMBNativeToErc20::executeActionOnBridgedTokens -............ForeignAMBNativeToErc20::distributeFee -..............MediatorMessagesGuard::enableMessagesRestriction -..............RewardableMediator::distributeFee -................ForeignAMBNativeToErc20::onFeeDistribution +............RewardableMediator::distributeFee +..............ForeignAMBNativeToErc20::onFeeDistribution >>Token -..................MintableToken::mint +................MintableToken::mint >>Fee Manager -................BaseMediatorFeeManager::onTokenTransfer -..................BaseMediatorFeeManager::distributeFee -....................ForeignFeeManagerAMBNativeToErc20::onFeeDistribution +..............BaseMediatorFeeManager::onTokenTransfer +................BaseMediatorFeeManager::distributeFee +..................ForeignFeeManagerAMBNativeToErc20::onFeeDistribution >>Token -......................ERC677BridgeToken::transfer -........................ERC677BridgeToken::superTransfer -..........................BasicToken::transfer -........................ERC677BridgeToken::callAfterTransfer -..........................ERC677BridgeToken::contractFallback -............................::onTokenTransfer -..............................<######> ->>Mediator -..............MediatorMessagesGuard::disableMessagesRestriction +....................ERC677BridgeToken::transfer +......................ERC677BridgeToken::superTransfer +........................BasicToken::transfer +......................ERC677BridgeToken::callAfterTransfer +........................ERC677BridgeToken::contractFallback +..........................::onTokenTransfer +............................<######> >>Token ............MintableToken::mint >>Mediator @@ -97,7 +93,6 @@ ERC677BridgeToken::transferAndCall ..ERC677BridgeToken::contractFallback >>Mediator ....ForeignAMBNativeToErc20::onTokenTransfer -......MediatorMessagesGuard::bridgeMessageAllowed ......ForeignAMBNativeToErc20::bridgeSpecificActionsOnTokenTransfer >>Token ........BurnableToken::burn @@ -339,28 +334,26 @@ This will allow to the mediator contract to call the `transferFrom` method from ```= >>Mediator ForeignAMBNativeToErc20::relayTokens -..ForeignAMBNativeToErc20::_relayTokens >>Token -....ERC677BridgeToken::transferFrom -......StandardToken::transferFrom -........emit Transfer -......ERC677BridgeToken::callAfterTransfer -........ERC677BridgeToken::contractFallback +..ERC677BridgeToken::transferFrom +....StandardToken::transferFrom +......emit Transfer +....ERC677BridgeToken::callAfterTransfer +......ERC677BridgeToken::contractFallback >>Mediator -..........ForeignAMBNativeToErc20::onTokenTransfer -............MediatorMessagesGuard::bridgeMessageAllowed -............ForeignAMBNativeToErc20::bridgeSpecificActionsOnTokenTransfer +........ForeignAMBNativeToErc20::onTokenTransfer +..........ForeignAMBNativeToErc20::bridgeSpecificActionsOnTokenTransfer >>Token -..............BurnableToken::burn -................BurnableToken::_burn +............BurnableToken::burn +..............BurnableToken::_burn >>Mediator -..............TokenBridgeMediator::passMessage -................TokenBridgeMediator::setMessageHashValue -................TokenBridgeMediator::setMessageHashRecipient +............TokenBridgeMediator::passMessage +..............TokenBridgeMediator::setMessageHashValue +..............TokenBridgeMediator::setMessageHashRecipient >>Bridge -................MessageDelivery::requireToPassMessage -..................ForeignAMB::emitEventOnMessageRequest -....................emit UserRequestForAffirmation +..............MessageDelivery::requireToPassMessage +................ForeignAMB::emitEventOnMessageRequest +..................emit UserRequestForAffirmation ``` #### Execution diff --git a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol index 0143c678..9a826211 100644 --- a/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol +++ b/contracts/upgradeable_contracts/erc20_to_native/ForeignBridgeErcToNative.sol @@ -80,41 +80,15 @@ contract ForeignBridgeErcToNative is BasicForeignBridge, ERC20Bridge, OtherSideB } function relayTokens(address _receiver, uint256 _amount) external { - _relayTokens(msg.sender, _receiver, _amount, erc20token()); - } - - function relayTokens(address _sender, address _receiver, uint256 _amount) external { - relayTokens(_sender, _receiver, _amount, erc20token()); - } - - function relayTokens(address _from, address _receiver, uint256 _amount, address _token) public { - require(_from == msg.sender || _from == _receiver); - _relayTokens(_from, _receiver, _amount, _token); - } - - function relayTokens(address _receiver, uint256 _amount, address _token) external { - _relayTokens(msg.sender, _receiver, _amount, _token); - } - - function _relayTokens(address _sender, address _receiver, uint256 _amount, address _token) internal { require(_receiver != bridgeContractOnOtherSide()); require(_receiver != address(0)); require(_receiver != address(this)); require(_amount > 0); require(withinLimit(_amount)); - ERC20 tokenToOperate = ERC20(_token); - ERC20 fdToken = erc20token(); - - if (tokenToOperate == ERC20(0x0)) { - tokenToOperate = fdToken; - } - - require(tokenToOperate == fdToken); - addTotalSpentPerDay(getCurrentDay(), _amount); - tokenToOperate.transferFrom(_sender, address(this), _amount); + erc20token().transferFrom(msg.sender, address(this), _amount); emit UserRequestForAffirmation(_receiver, _amount); if (isDaiNeedsToBeInvested()) { diff --git a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiAMBErc20ToErc677.sol b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiAMBErc20ToErc677.sol index 18d89738..7783e3af 100644 --- a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiAMBErc20ToErc677.sol +++ b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiAMBErc20ToErc677.sol @@ -30,19 +30,6 @@ contract BasicMultiAMBErc20ToErc677 is return mediatorContractOnOtherSide(); } - /** - * @dev Initiate the bridge operation for some amount of tokens. - * The user should first call Approve method of the ERC677 token. - * @param token bridged token contract address. - * @param _from address that will transfer the tokens to be locked. - * @param _receiver address that will receive the native tokens on the other network. - * @param _value amount of tokens to be transferred to the other network. - */ - function relayTokens(ERC677 token, address _from, address _receiver, uint256 _value) external { - require(_from == msg.sender || _from == _receiver); - _relayTokens(token, _from, _receiver, _value); - } - /** * @dev Initiate the bridge operation for some amount of tokens from msg.sender. * The user should first call Approve method of the ERC677 token. @@ -51,7 +38,7 @@ contract BasicMultiAMBErc20ToErc677 is * @param _value amount of tokens to be transferred to the other network. */ function relayTokens(ERC677 token, address _receiver, uint256 _value) external { - _relayTokens(token, msg.sender, _receiver, _value); + _relayTokens(token, _receiver, _value); } /** @@ -61,7 +48,7 @@ contract BasicMultiAMBErc20ToErc677 is * @param _value amount of tokens to be transferred to the other network. */ function relayTokens(ERC677 token, uint256 _value) external { - _relayTokens(token, msg.sender, msg.sender, _value); + _relayTokens(token, msg.sender, _value); } /** @@ -71,7 +58,7 @@ contract BasicMultiAMBErc20ToErc677 is * @return patch value of the version */ function getBridgeInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) { - return (1, 0, 1); + return (1, 1, 0); } /** @@ -97,7 +84,7 @@ contract BasicMultiAMBErc20ToErc677 is function onTokenTransfer(address _from, uint256 _value, bytes _data) public returns (bool); /* solcov ignore next */ - function _relayTokens(ERC677 token, address _from, address _receiver, uint256 _value) internal; + function _relayTokens(ERC677 token, address _receiver, uint256 _value) internal; /* solcov ignore next */ function bridgeSpecificActionsOnTokenTransfer(ERC677 _token, address _from, uint256 _value, bytes _data) internal; diff --git a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiTokenBridge.sol b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiTokenBridge.sol index a70eaabf..a051088d 100644 --- a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiTokenBridge.sol +++ b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/BasicMultiTokenBridge.sol @@ -93,7 +93,11 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function withinLimit(address _token, uint256 _amount) public view returns (bool) { uint256 nextLimit = totalSpentPerDay(_token, getCurrentDay()).add(_amount); - return dailyLimit(_token) >= nextLimit && _amount <= maxPerTx(_token) && _amount >= minPerTx(_token); + return + dailyLimit(address(0)) > 0 && + dailyLimit(_token) >= nextLimit && + _amount <= maxPerTx(_token) && + _amount >= minPerTx(_token); } /** @@ -104,7 +108,10 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function withinExecutionLimit(address _token, uint256 _amount) public view returns (bool) { uint256 nextLimit = totalExecutedPerDay(_token, getCurrentDay()).add(_amount); - return executionDailyLimit(_token) >= nextLimit && _amount <= executionMaxPerTx(_token); + return + executionDailyLimit(address(0)) > 0 && + executionDailyLimit(_token) >= nextLimit && + _amount <= executionMaxPerTx(_token); } /** @@ -124,7 +131,7 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function setDailyLimit(address _token, uint256 _dailyLimit) external onlyOwner { require(isTokenRegistered(_token)); - require(_dailyLimit > maxPerTx(_token) || (_dailyLimit == 0 && _token != address(0))); + require(_dailyLimit > maxPerTx(_token) || _dailyLimit == 0); uintStorage[keccak256(abi.encodePacked("dailyLimit", _token))] = _dailyLimit; emit DailyLimitChanged(_token, _dailyLimit); } @@ -137,7 +144,7 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function setExecutionDailyLimit(address _token, uint256 _dailyLimit) external onlyOwner { require(isTokenRegistered(_token)); - require(_dailyLimit > executionMaxPerTx(_token) || (_dailyLimit == 0 && _token != address(0))); + require(_dailyLimit > executionMaxPerTx(_token) || _dailyLimit == 0); uintStorage[keccak256(abi.encodePacked("executionDailyLimit", _token))] = _dailyLimit; emit ExecutionDailyLimitChanged(_token, _dailyLimit); } @@ -150,7 +157,7 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function setExecutionMaxPerTx(address _token, uint256 _maxPerTx) external onlyOwner { require(isTokenRegistered(_token)); - require((_token != address(0) && _maxPerTx == 0) || (_maxPerTx > 0 && _maxPerTx < executionDailyLimit(_token))); + require(_maxPerTx == 0 || (_maxPerTx > 0 && _maxPerTx < executionDailyLimit(_token))); uintStorage[keccak256(abi.encodePacked("executionMaxPerTx", _token))] = _maxPerTx; } @@ -162,9 +169,7 @@ contract BasicMultiTokenBridge is EternalStorage, Ownable { */ function setMaxPerTx(address _token, uint256 _maxPerTx) external onlyOwner { require(isTokenRegistered(_token)); - require( - (_token != address(0) && _maxPerTx == 0) || (_maxPerTx > minPerTx(_token) && _maxPerTx < dailyLimit(_token)) - ); + require(_maxPerTx == 0 || (_maxPerTx > minPerTx(_token) && _maxPerTx < dailyLimit(_token))); uintStorage[keccak256(abi.encodePacked("maxPerTx", _token))] = _maxPerTx; } diff --git a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/ForeignMultiAMBErc20ToErc677.sol b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/ForeignMultiAMBErc20ToErc677.sol index 8717ded3..3e7830d2 100644 --- a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/ForeignMultiAMBErc20ToErc677.sol +++ b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/ForeignMultiAMBErc20ToErc677.sol @@ -53,7 +53,7 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 { */ function executeActionOnBridgedTokens(address _token, address _recipient, uint256 _value) internal { bytes32 _messageId = messageId(); - ERC677(_token).transfer(_recipient, _value); + LegacyERC20(_token).transfer(_recipient, _value); _setMediatorBalance(_token, mediatorBalance(_token).sub(_value)); emit TokensBridged(_token, _recipient, _value, _messageId); } @@ -89,11 +89,10 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 { * and invokes the method to burn/lock the tokens and unlock/mint the tokens on the other network. * The user should first call Approve method of the ERC677 token. * @param token bridge token contract address. - * @param _from address that will transfer the tokens to be locked. * @param _receiver address that will receive the native tokens on the other network. * @param _value amount of tokens to be transferred to the other network. */ - function _relayTokens(ERC677 token, address _from, address _receiver, uint256 _value) internal { + function _relayTokens(ERC677 token, address _receiver, uint256 _value) internal { // This lock is to prevent calling passMessage twice if a ERC677 token is used. // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract // which will call passMessage. @@ -101,9 +100,9 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 { address to = address(this); setLock(true); - token.transferFrom(_from, to, _value); + LegacyERC20(token).transferFrom(msg.sender, to, _value); setLock(false); - bridgeSpecificActionsOnTokenTransfer(token, _from, _value, abi.encodePacked(_receiver)); + bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver)); } /** @@ -190,7 +189,7 @@ contract ForeignMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677 { */ function executeActionOnFixedTokens(address _token, address _recipient, uint256 _value) internal { _setMediatorBalance(_token, mediatorBalance(_token).sub(_value)); - ERC677(_token).transfer(_recipient, _value); + LegacyERC20(_token).transfer(_recipient, _value); } /** diff --git a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/HomeMultiAMBErc20ToErc677.sol b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/HomeMultiAMBErc20ToErc677.sol index d6a46237..163c745b 100644 --- a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/HomeMultiAMBErc20ToErc677.sol +++ b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/HomeMultiAMBErc20ToErc677.sol @@ -153,11 +153,10 @@ contract HomeMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677, HomeFeeManager * and invokes the method to burn/lock the tokens and unlock/mint the tokens on the other network. * The user should first call Approve method of the ERC677 token. * @param token bridge token contract address. - * @param _from address that will transfer the tokens to be locked. * @param _receiver address that will receive the native tokens on the other network. * @param _value amount of tokens to be transferred to the other network. */ - function _relayTokens(ERC677 token, address _from, address _receiver, uint256 _value) internal { + function _relayTokens(ERC677 token, address _receiver, uint256 _value) internal { // This lock is to prevent calling passMessage twice if a ERC677 token is used. // When transferFrom is called, after the transfer, the ERC677 token will call onTokenTransfer from this contract // which will call passMessage. @@ -170,9 +169,9 @@ contract HomeMultiAMBErc20ToErc677 is BasicMultiAMBErc20ToErc677, HomeFeeManager addTotalSpentPerDay(token, getCurrentDay(), _value); setLock(true); - token.transferFrom(_from, to, _value); + token.transferFrom(msg.sender, to, _value); setLock(false); - bridgeSpecificActionsOnTokenTransfer(token, _from, _value, abi.encodePacked(_receiver)); + bridgeSpecificActionsOnTokenTransfer(token, msg.sender, _value, abi.encodePacked(_receiver)); } /** diff --git a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/TokenProxy.sol b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/TokenProxy.sol index b09e8edd..5931dd6f 100644 --- a/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/TokenProxy.sol +++ b/contracts/upgradeable_contracts/multi_amb_erc20_to_erc677/TokenProxy.sol @@ -29,7 +29,7 @@ contract TokenProxy is Proxy { /** * @dev Creates a non-upgradeable token proxy for PermitableToken.sol, initializes its eternalStorage. - * @param _tokenImage address of the token image used for mirrowing all functions. + * @param _tokenImage address of the token image used for mirroring all functions. * @param _name token name. * @param _symbol token symbol. * @param _decimals token decimals. @@ -62,7 +62,7 @@ contract TokenProxy is Proxy { } /** - * @dev Retrieves the implementation contract address, mirrowed token image. + * @dev Retrieves the implementation contract address, mirrored token image. * @return token image address. */ function implementation() public view returns (address impl) { diff --git a/deploy/package-lock.json b/deploy/package-lock.json index 189a02ad..220382ff 100644 --- a/deploy/package-lock.json +++ b/deploy/package-lock.json @@ -27,12 +27,14 @@ "@babel/parser": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.5.tgz", - "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==" + "integrity": "sha512-9mUqkL1FF5T7f0WDFfAoDdiMVPWsdD1gZYzSnaXsxUCUqzuch/8of9G3VUSNiZmMBoRxT3neyVsqeiL/ZPcjew==", + "dev": true }, "@babel/runtime": { "version": "7.4.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.5.tgz", "integrity": "sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==", + "dev": true, "requires": { "regenerator-runtime": "^0.13.2" } @@ -199,6 +201,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, "requires": { "call-me-maybe": "^1.0.1", "glob-to-regexp": "^0.3.0" @@ -207,7 +210,8 @@ "@nodelib/fs.stat": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true }, "@sindresorhus/is": { "version": "0.14.0", @@ -233,12 +237,14 @@ "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true }, "@types/glob": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, "requires": { "@types/events": "*", "@types/minimatch": "*", @@ -248,7 +254,8 @@ "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true }, "@types/node": { "version": "12.0.2", @@ -319,17 +326,20 @@ "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true }, "array-flatten": { "version": "1.1.1", @@ -350,6 +360,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, "requires": { "array-uniq": "^1.0.1" } @@ -357,12 +368,14 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true }, "asn1": { "version": "0.2.4", @@ -390,7 +403,8 @@ "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true }, "astral-regex": { "version": "1.0.0", @@ -411,7 +425,8 @@ "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true }, "aws-sign2": { "version": "0.7.0", @@ -442,12 +457,14 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true }, "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, "requires": { "cache-base": "^1.0.1", "class-utils": "^0.3.5", @@ -462,6 +479,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -470,6 +488,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -478,6 +497,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -486,6 +506,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -574,6 +595,7 @@ "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" @@ -583,6 +605,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -600,6 +623,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -740,7 +764,8 @@ "byline": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" + "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", + "dev": true }, "bytes": { "version": "3.1.0", @@ -751,6 +776,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, "requires": { "collection-visit": "^1.0.0", "component-emitter": "^1.2.1", @@ -795,7 +821,8 @@ "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true }, "callsites": { "version": "3.1.0", @@ -870,6 +897,7 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "define-property": "^0.2.5", @@ -881,6 +909,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -914,6 +943,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, "requires": { "map-visit": "^1.0.0", "object-visit": "^1.0.0" @@ -943,12 +973,14 @@ "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "contains-path": { "version": "0.1.0", @@ -997,7 +1029,8 @@ "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -1127,7 +1160,8 @@ "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=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true }, "defer-to-connect": { "version": "1.1.3", @@ -1147,6 +1181,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, "requires": { "is-descriptor": "^1.0.2", "isobject": "^3.0.1" @@ -1156,6 +1191,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1164,6 +1200,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1172,6 +1209,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -1218,6 +1256,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, "requires": { "path-type": "^3.0.0" } @@ -1403,6 +1442,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.1.tgz", "integrity": "sha512-JwiqFD9KdGVVpeuRa68yU3zZnBEOcPs0nKW7wZzXky8Z7tffdYUHbe11bPCV5jYlK6DVdKLWLm0f5I/QlL0Kmw==", + "dev": true, "requires": { "esprima": "^3.1.3", "estraverse": "^4.2.0", @@ -1654,7 +1694,8 @@ "esprima": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true }, "esquery": { "version": "1.0.1", @@ -1677,12 +1718,14 @@ "estraverse": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true }, "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true }, "etag": { "version": "1.8.1", @@ -1802,6 +1845,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, "requires": { "debug": "^2.3.3", "define-property": "^0.2.5", @@ -1816,6 +1860,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -1824,6 +1869,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -1833,7 +1879,8 @@ "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true }, "express": { "version": "4.17.1", @@ -1903,6 +1950,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, "requires": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" @@ -1912,6 +1960,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -1933,6 +1982,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, "requires": { "array-unique": "^0.3.2", "define-property": "^1.0.0", @@ -1948,6 +1998,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -1956,6 +2007,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -1964,6 +2016,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1972,6 +2025,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -1980,6 +2034,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -2008,6 +2063,7 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, "requires": { "@mrmlnc/readdir-enhanced": "^2.2.1", "@nodelib/fs.stat": "^1.1.2", @@ -2025,7 +2081,8 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "figures": { "version": "2.0.0", @@ -2054,6 +2111,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", @@ -2065,6 +2123,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -2132,7 +2191,8 @@ "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true }, "forever-agent": { "version": "0.6.1", @@ -2158,6 +2218,7 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, "requires": { "map-cache": "^0.2.2" } @@ -2171,6 +2232,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" @@ -2180,6 +2242,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, "requires": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -2197,7 +2260,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -2228,7 +2292,8 @@ "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true }, "getpass": { "version": "0.1.7", @@ -2242,6 +2307,7 @@ "version": "7.1.4", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2255,6 +2321,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -2264,6 +2331,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, "requires": { "is-extglob": "^2.1.0" } @@ -2273,7 +2341,8 @@ "glob-to-regexp": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true }, "global": { "version": "4.3.2", @@ -2294,6 +2363,7 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, "requires": { "@types/glob": "^7.1.1", "array-union": "^1.0.2", @@ -2379,6 +2449,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, "requires": { "get-value": "^2.0.6", "has-values": "^1.0.0", @@ -2389,6 +2460,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, "requires": { "is-number": "^3.0.0", "kind-of": "^4.0.0" @@ -2398,6 +2470,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -2501,7 +2574,8 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true }, "import-fresh": { "version": "3.0.0", @@ -2523,6 +2597,7 @@ "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" @@ -2575,6 +2650,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-5.1.0.tgz", "integrity": "sha512-cbDhb8qlxKMxPBk/QxTtYg1DQ4CwXmadu7quG3B7nrJsgSncEreF2kwWKZFdnjc/lSNNIkFPsjI7SM0Cx/QXPw==", + "dev": true, "requires": { "from2": "^2.3.0", "p-is-promise": "^2.0.0" @@ -2589,6 +2665,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -2597,6 +2674,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -2612,7 +2690,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-callable": { "version": "1.1.4", @@ -2624,6 +2703,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -2632,6 +2712,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -2648,6 +2729,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, "requires": { "is-accessor-descriptor": "^0.1.6", "is-data-descriptor": "^0.1.4", @@ -2657,19 +2739,22 @@ "kind-of": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true } } }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -2686,6 +2771,7 @@ "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" } @@ -2699,6 +2785,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -2707,6 +2794,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -2727,6 +2815,7 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, "requires": { "isobject": "^3.0.1" } @@ -2773,12 +2862,14 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true }, "isexe": { "version": "2.0.0", @@ -2789,7 +2880,8 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -2912,12 +3004,14 @@ "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true }, "levn": { "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" @@ -2967,12 +3061,14 @@ "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, "requires": { "object-visit": "^1.0.0" } @@ -3005,7 +3101,8 @@ "merge2": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", - "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==" + "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", + "dev": true }, "methods": { "version": "1.1.2", @@ -3016,6 +3113,7 @@ "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -3092,6 +3190,7 @@ "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" } @@ -3099,7 +3198,8 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, "minipass": { "version": "2.9.0", @@ -3122,6 +3222,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, "requires": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" @@ -3131,6 +3232,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, "requires": { "is-plain-object": "^2.0.4" } @@ -3212,6 +3314,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/multistream/-/multistream-2.1.1.tgz", "integrity": "sha512-xasv76hl6nr1dEy3lPvy7Ej7K/Lx3O/FCvwge8PeVJpciPPoNCbaANcNiBug3IpdvTveZUcAV0DJzdnUDMesNQ==", + "dev": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.5" @@ -3237,6 +3340,7 @@ "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, "requires": { "arr-diff": "^4.0.0", "array-unique": "^0.3.2", @@ -3342,6 +3446,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, "requires": { "copy-descriptor": "^0.1.0", "define-property": "^0.2.5", @@ -3352,6 +3457,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -3360,6 +3466,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -3376,6 +3483,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, "requires": { "isobject": "^3.0.0" } @@ -3408,6 +3516,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, "requires": { "isobject": "^3.0.1" } @@ -3449,6 +3558,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, "requires": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.4", @@ -3461,7 +3571,8 @@ "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=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "p-cancelable": { "version": "1.1.0", @@ -3476,7 +3587,8 @@ "p-is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true }, "p-limit": { "version": "1.3.0", @@ -3554,12 +3666,14 @@ "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true }, "path-exists": { "version": "3.0.0", @@ -3570,7 +3684,8 @@ "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=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-is-inside": { "version": "1.0.2", @@ -3587,7 +3702,8 @@ "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -3598,6 +3714,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, "requires": { "pify": "^3.0.0" }, @@ -3605,7 +3722,8 @@ "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true } } }, @@ -3629,12 +3747,14 @@ "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true }, "pkg": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/pkg/-/pkg-4.4.0.tgz", "integrity": "sha512-bFNJ3v56QwqB6JtAl/YrczlmEKBPBVJ3n5nW905kgvG1ex9DajODpTs0kLAFxyLwoubDQux/RPJFL6WrnD/vpg==", + "dev": true, "requires": { "@babel/parser": "~7.4.4", "@babel/runtime": "~7.4.4", @@ -3664,6 +3784,7 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-2.6.2.tgz", "integrity": "sha512-7DN6YYP1Kct02mSkhfblK0HkunJ7BJjGBkSkFdIW/QKIovtAMaICidS7feX+mHfnZ98OP7xFJvBluVURlrHJxA==", + "dev": true, "requires": { "@babel/runtime": "~7.4.4", "byline": "~5.0.0", @@ -3681,12 +3802,14 @@ "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "prepend-http": { "version": "2.0.0", @@ -3707,12 +3830,14 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "promise-retry": { "version": "1.1.1", @@ -3859,6 +3984,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3872,12 +3998,14 @@ "regenerator-runtime": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz", - "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==" + "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==", + "dev": true }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, "requires": { "extend-shallow": "^3.0.2", "safe-regex": "^1.1.0" @@ -3892,12 +4020,14 @@ "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "request": { "version": "2.88.0", @@ -3930,6 +4060,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", "integrity": "sha1-TKdUCBx/7GP1BeT6qCWqBs1mnb4=", + "dev": true, "requires": { "throttleit": "^1.0.0" } @@ -3938,6 +4069,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.6.0.tgz", "integrity": "sha512-mw7JQNu5ExIkcw4LPih0owX/TZXjD/ZUF/ZQ/pDnkw3ZKhDcZZw5klmBlj6gVMwjQ3Pz5Jgu7F3d0jcDVuEWdw==", + "dev": true, "requires": { "path-parse": "^1.0.5" } @@ -3951,7 +4083,8 @@ "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true }, "responselike": { "version": "1.0.2", @@ -3974,7 +4107,8 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "retry": { "version": "0.10.1", @@ -4035,6 +4169,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, "requires": { "ret": "~0.1.10" } @@ -4067,7 +4202,8 @@ "semver": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" + "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==", + "dev": true }, "send": { "version": "0.17.1", @@ -4123,6 +4259,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, "requires": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", @@ -4134,6 +4271,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -4198,7 +4336,8 @@ "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true }, "slice-ansi": { "version": "2.1.0", @@ -4215,6 +4354,7 @@ "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, "requires": { "base": "^0.11.1", "debug": "^2.2.0", @@ -4230,6 +4370,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -4238,6 +4379,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, "requires": { "is-extendable": "^0.1.0" } @@ -4245,7 +4387,8 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true } } }, @@ -4253,6 +4396,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, "requires": { "define-property": "^1.0.0", "isobject": "^3.0.0", @@ -4263,6 +4407,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, "requires": { "is-descriptor": "^1.0.0" } @@ -4271,6 +4416,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4279,6 +4425,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, "requires": { "kind-of": "^6.0.0" } @@ -4287,6 +4434,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, "requires": { "is-accessor-descriptor": "^1.0.0", "is-data-descriptor": "^1.0.0", @@ -4299,6 +4447,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, "requires": { "kind-of": "^3.2.0" }, @@ -4307,6 +4456,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -4317,12 +4467,14 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "optional": true }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, "requires": { "atob": "^2.1.1", "decode-uri-component": "^0.2.0", @@ -4334,7 +4486,8 @@ "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, "spdx-correct": { "version": "3.1.0", @@ -4372,6 +4525,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, "requires": { "extend-shallow": "^3.0.0" } @@ -4402,6 +4556,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, "requires": { "define-property": "^0.2.5", "object-copy": "^0.1.0" @@ -4411,6 +4566,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, "requires": { "is-descriptor": "^0.1.0" } @@ -4426,6 +4582,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", "integrity": "sha1-Uq+Vql6nYKJJFxZwTb/5D3Ov3R0=", + "dev": true, "requires": { "readable-stream": "^2.1.4" } @@ -4627,7 +4784,8 @@ "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=" + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true }, "through": { "version": "2.3.8", @@ -4653,6 +4811,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, "requires": { "kind-of": "^3.0.2" }, @@ -4661,6 +4820,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -4676,6 +4836,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, "requires": { "define-property": "^2.0.2", "extend-shallow": "^3.0.2", @@ -4687,6 +4848,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -4741,6 +4903,7 @@ "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" } @@ -4765,7 +4928,8 @@ "uid2": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", - "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=", + "dev": true }, "ultron": { "version": "1.1.1", @@ -4781,6 +4945,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", @@ -4792,6 +4957,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz", "integrity": "sha1-bc6VsmgcoAPuv7MEpBX5y6vMU4U=", + "dev": true, "requires": { "mkdirp": "^0.5.1", "os-tmpdir": "^1.0.1", @@ -4812,6 +4978,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, "requires": { "has-value": "^0.3.1", "isobject": "^3.0.0" @@ -4821,6 +4988,7 @@ "version": "0.3.1", "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, "requires": { "get-value": "^2.0.3", "has-values": "^0.1.4", @@ -4831,6 +4999,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -4840,7 +5009,8 @@ "has-values": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true } } }, @@ -4855,7 +5025,8 @@ "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true }, "url-parse-lax": { "version": "3.0.0", @@ -4878,7 +5049,8 @@ "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true }, "utf8": { "version": "3.0.0", @@ -5320,7 +5492,8 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true }, "wrappy": { "version": "1.0.2", diff --git a/deploy/package.json b/deploy/package.json index 69fb6623..35bae4c5 100644 --- a/deploy/package.json +++ b/deploy/package.json @@ -17,7 +17,6 @@ "envalid": "^4.1.4", "ethereumjs-tx": "^1.3.4", "node-fetch": "^2.1.2", - "pkg": "^4.3.1", "promise-retry": "^1.1.1", "querystring": "^0.2.0", "web3": "^1.2.9" @@ -29,6 +28,7 @@ "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^7.0.1", "eslint-plugin-prettier": "^2.6.2", + "pkg": "^4.3.1", "prettier": "^1.14.3" }, "engines": { diff --git a/docker-compose.yml b/docker-compose.yml index 9c1e9ee1..c3941705 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,3 +4,9 @@ services: build: . command: "true" env_file: ./deploy/.env + dev: + build: + context: . + dockerfile: Dockerfile.dev + command: "true" + env_file: ./deploy/.env diff --git a/package-lock.json b/package-lock.json index 15d0f3a8..65f3f9c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "token-bridge-contracts", - "version": "5.3.1", + "name": "tokenbridge-contracts", + "version": "5.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -676,7 +676,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.2.1.tgz", "integrity": "sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A==", - "dev": true, "requires": { "debug": "^3.1.0", "request": "^2.85.0" @@ -686,7 +685,6 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/@resolver-engine/fs/-/fs-0.2.1.tgz", "integrity": "sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg==", - "dev": true, "requires": { "@resolver-engine/core": "^0.2.1", "debug": "^3.1.0" @@ -696,7 +694,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/@resolver-engine/imports/-/imports-0.2.2.tgz", "integrity": "sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg==", - "dev": true, "requires": { "@resolver-engine/core": "^0.2.1", "debug": "^3.1.0", @@ -707,7 +704,6 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz", "integrity": "sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ==", - "dev": true, "requires": { "@resolver-engine/fs": "^0.2.1", "@resolver-engine/imports": "^0.2.2", @@ -3377,28 +3373,6 @@ } } }, - "coveralls": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.0.6.tgz", - "integrity": "sha512-Pgh4v3gCI4T/9VijVrm8Ym5v0OgjvGLKj3zTUwkvsCiwqae/p6VLzpsFNjQS2i6ewV7ef+DjFJ5TSKxYt/mCrA==", - "dev": true, - "requires": { - "growl": "~> 1.10.0", - "js-yaml": "^3.13.1", - "lcov-parse": "^0.0.10", - "log-driver": "^1.2.7", - "minimist": "^1.2.0", - "request": "^2.86.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "create-error-class": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", @@ -4373,7 +4347,7 @@ "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", "requires": { - "ethereumjs-abi": "ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git#1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b", + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git", "ethereumjs-util": "^5.1.1" } }, @@ -20137,12 +20111,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, "handlebars": { "version": "4.5.3", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", @@ -21128,12 +21096,6 @@ "invert-kv": "^1.0.0" } }, - "lcov-parse": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, "level-codec": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", @@ -21355,12 +21317,6 @@ "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-4.3.0.tgz", "integrity": "sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=" }, - "log-driver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", - "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", - "dev": true - }, "loglevel": { "version": "1.6.8", "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", @@ -25075,7 +25031,6 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.4.2.tgz", "integrity": "sha512-7qUIzaW8a4vI4nui14wsytht2oaqvqnZ1Iet2wRq2T0bCJ0wb6HByMKQhZKpU46R+n5BMTY4K5n+0ITyeNlmuQ==", - "dev": true, "requires": { "@resolver-engine/imports-fs": "^0.2.2", "find-up": "^2.1.0", @@ -25088,7 +25043,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, "requires": { "locate-path": "^2.0.0" } @@ -25096,8 +25050,7 @@ "solidity-parser-antlr": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/solidity-parser-antlr/-/solidity-parser-antlr-0.4.11.tgz", - "integrity": "sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg==", - "dev": true + "integrity": "sha512-4jtxasNGmyC0midtjH/lTFPZYvTTUMy6agYcF+HoMnzW8+cqo3piFrINb4ZCzpPW+7tTVFCGa5ubP34zOzeuMg==" } } }, @@ -25136,8 +25089,7 @@ "tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=", - "dev": true + "integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=" }, "tunnel-agent": { "version": "0.6.0", diff --git a/package.json b/package.json index 40bd2122..e7d5e34e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "token-bridge-contracts", - "version": "5.3.1", + "name": "tokenbridge-contracts", + "version": "5.4.0", "description": "Bridge", "main": "index.js", "scripts": { @@ -24,14 +24,14 @@ "@0x/sol-trace": "^3.0.10", "@0x/subproviders": "^6.1.1", "openzeppelin-solidity": "1.12.0", - "truffle": "^5.0.35" + "truffle": "^5.0.35", + "truffle-flattener": "^1.4.2" }, "devDependencies": { "@codechecks/client": "^0.1.9", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "chai-bn": "^0.1.1", - "coveralls": "^3.0.6", "eslint": "^6.3.0", "eslint-config-airbnb-base": "^14.0.0", "eslint-config-prettier": "^6.2.0", @@ -47,7 +47,6 @@ "prettier": "^1.18.2", "prettier-plugin-solidity": "^1.0.0-alpha.32", "solhint": "^2.2.0", - "solhint-plugin-prettier": "0.0.3", - "truffle-flattener": "^1.4.2" + "solhint-plugin-prettier": "0.0.3" } } diff --git a/scripts/test.sh b/scripts/test.sh index 91e33a41..b99135d8 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -57,10 +57,6 @@ fi if [ "$SOLIDITY_COVERAGE" = true ]; then node --max-old-space-size=4096 node_modules/.bin/truffle test 2>/dev/null; istanbul report lcov - - if [ "$CONTINUOUS_INTEGRATION" = true ]; then - cat coverage/lcov.info | node_modules/.bin/coveralls - fi else node_modules/.bin/truffle test --network ganache "$@" fi diff --git a/test/amb_erc20_to_native/foreign_mediator.test.js b/test/amb_erc20_to_native/foreign_mediator.test.js index e66c3ca2..4ce57f50 100644 --- a/test/amb_erc20_to_native/foreign_mediator.test.js +++ b/test/amb_erc20_to_native/foreign_mediator.test.js @@ -336,7 +336,7 @@ contract('ForeignAMBErc20ToNative', async accounts => { expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) // When - await contract.methods['relayTokens(address,uint256)'](user, value, { from: user }).should.be.fulfilled + await contract.relayTokens(user, value, { from: user }).should.be.fulfilled // Then const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) @@ -344,45 +344,13 @@ contract('ForeignAMBErc20ToNative', async accounts => { expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) }) - it('should allow user to specify a itself as receiver', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) - - it('should allow to specify a different receiver', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) - it('should allow to specify a different receiver without specifying sender', async () => { // Given await token.approve(contract.address, value, { from: user }).should.be.fulfilled expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) // When - await contract.methods['relayTokens(address,uint256)'](user2, value, { from: user }).should.be.fulfilled + await contract.relayTokens(user2, value, { from: user }).should.be.fulfilled // Then const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) @@ -391,34 +359,15 @@ contract('ForeignAMBErc20ToNative', async accounts => { expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) }) - it('should allow to complete a transfer approved by other user', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { - from: user2 - }).should.be.rejected - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user2 }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) - it('should fail if user did not approve the transfer', async () => { - await contract.methods['relayTokens(address,uint256)'](user, value, { from: user }).should.be.rejected + await contract.relayTokens(user, value, { from: user }).should.be.rejected }) it('should fail if value is not within limits', async () => { await token.approve(contract.address, twoEthers, { from: user }).should.be.fulfilled expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(twoEthers) - await contract.methods['relayTokens(address,uint256)'](user, twoEthers, { from: user }).should.be.rejected + await contract.relayTokens(user, twoEthers, { from: user }).should.be.rejected }) }) diff --git a/test/amb_erc677_to_erc677/AMBErc677ToErc677Behavior.test.js b/test/amb_erc677_to_erc677/AMBErc677ToErc677Behavior.test.js index c3c6a139..b92290e9 100644 --- a/test/amb_erc677_to_erc677/AMBErc677ToErc677Behavior.test.js +++ b/test/amb_erc677_to_erc677/AMBErc677ToErc677Behavior.test.js @@ -548,66 +548,6 @@ function shouldBehaveLikeBasicAMBErc677ToErc677(otherSideMediatorContract, accou expect(events.length).to.be.equal(1) expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) }) - it('should allow user to specify a itself as receiver', async () => { - // Given - await contract.initialize( - bridgeContract.address, - mediatorContract.address, - erc20Token.address, - [dailyLimit, maxPerTx, minPerTx], - [executionDailyLimit, executionMaxPerTx], - maxGasPerTx, - decimalShiftZero, - owner - ).should.be.fulfilled - - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - const value = oneEther - await erc20Token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await erc20Token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(bridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) - it('should allow to specify a different receiver', async () => { - // Given - await contract.initialize( - bridgeContract.address, - mediatorContract.address, - erc20Token.address, - [dailyLimit, maxPerTx, minPerTx], - [executionDailyLimit, executionMaxPerTx], - maxGasPerTx, - decimalShiftZero, - owner - ).should.be.fulfilled - - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - const value = oneEther - await erc20Token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await erc20Token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(bridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) it('should allow to specify a different receiver without specifying sender', async () => { // Given await contract.initialize( @@ -637,39 +577,6 @@ function shouldBehaveLikeBasicAMBErc677ToErc677(otherSideMediatorContract, accou expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) }) - it('should allow to complete a transfer approved by other user', async () => { - // Given - await contract.initialize( - bridgeContract.address, - mediatorContract.address, - erc20Token.address, - [dailyLimit, maxPerTx, minPerTx], - [executionDailyLimit, executionMaxPerTx], - maxGasPerTx, - decimalShiftZero, - owner - ).should.be.fulfilled - - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - const value = oneEther - await erc20Token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await erc20Token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { - from: user2 - }).should.be.rejectedWith(ERROR_MSG) - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user2 }).should.be - .fulfilled - - // Then - const events = await getEvents(bridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - }) it('should fail if user did not approve the transfer', async () => { await contract.initialize( bridgeContract.address, diff --git a/test/amb_native_to_erc20/foreign_mediator.test.js b/test/amb_native_to_erc20/foreign_mediator.test.js index cc7bca2c..0641373d 100644 --- a/test/amb_native_to_erc20/foreign_mediator.test.js +++ b/test/amb_native_to_erc20/foreign_mediator.test.js @@ -855,50 +855,6 @@ contract('ForeignAMBNativeToErc20', async accounts => { // Tokens were burnt expect(await token.totalSupply()).to.be.bignumber.equal(oneEther) }) - it('should allow user to specify a itself as receiver', async () => { - // Given - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - expect(await token.totalSupply()).to.be.bignumber.equal(twoEthers) - - const value = oneEther - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - // Tokens were burnt - expect(await token.totalSupply()).to.be.bignumber.equal(oneEther) - }) - it('should allow to specify a different receiver', async () => { - // Given - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - expect(await token.totalSupply()).to.be.bignumber.equal(twoEthers) - - const value = oneEther - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { from: user }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - // Tokens were burnt - expect(await token.totalSupply()).to.be.bignumber.equal(oneEther) - }) it('should allow to specify a different receiver without specifying sender', async () => { // Given const currentDay = await contract.getCurrentDay() @@ -920,31 +876,6 @@ contract('ForeignAMBNativeToErc20', async accounts => { // Tokens were burnt expect(await token.totalSupply()).to.be.bignumber.equal(oneEther) }) - it('should allow to complete a transfer approved by other user', async () => { - // Given - const currentDay = await contract.getCurrentDay() - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - expect(await token.totalSupply()).to.be.bignumber.equal(twoEthers) - - const value = oneEther - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,uint256)'](user, user2, value, { - from: user2 - }).should.be.rejectedWith(ERROR_MSG) - await contract.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user2 }).should.be - .fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - // Tokens were burnt - expect(await token.totalSupply()).to.be.bignumber.equal(oneEther) - }) it('should fail if user did not approve the transfer', async () => { await contract.relayTokens(user, oneEther, { from: user }).should.be.rejectedWith(ERROR_MSG) }) @@ -1610,130 +1541,6 @@ contract('ForeignAMBNativeToErc20', async accounts => { expect(toBN(feeEvents[0].returnValues.feeAmount)).to.be.bignumber.equal(feeAmount) expect(feeEvents[0].returnValues.messageId).to.be.equal(exampleMessageId) - const event = await getEvents(contract, { event: 'TokensBridged' }) - expect(event.length).to.be.equal(1) - expect(event[0].returnValues.recipient).to.be.equal(user) - expect(event[0].returnValues.value).to.be.equal(finalUserValue.toString()) - expect(event[0].returnValues.messageId).to.be.equal(exampleMessageId) - }) - it('should prevent multiple fee receiver to bridge back the tokens', async () => { - // initialize - const feeReceiver = await FeeReceiverMock.new(contract.address, token.address) - const feeReceiver2 = await FeeReceiverMock.new(contract.address, token.address) - const feeReceiver3 = await FeeReceiverMock.new(contract.address, token.address) - rewardAccountList = [feeReceiver.address, feeReceiver2.address, feeReceiver3.address] - - const feeManager = await ForeignFeeManagerAMBNativeToErc20.new( - owner, - ether('0.001'), - rewardAccountList, - contract.address, - token.address - ) - - await token.transferOwnership(contract.address) - - await contract.initialize( - ambBridgeContract.address, - otherSideMediatorContract.address, - [dailyLimit, maxPerTx, 1], - [executionDailyLimit, executionMaxPerTx], - maxGasPerTx, - decimalShiftZero, - owner, - token.address, - feeManager.address - ).should.be.fulfilled - - // Given - const currentDay = await contract.getCurrentDay() - expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(ZERO) - const initialEvents = await getEvents(token, { event: 'Mint' }) - expect(initialEvents.length).to.be.equal(0) - expect(await token.totalSupply()).to.be.bignumber.equal(ZERO) - - const value = halfEther - const relativeValue = 0.5 - - // 0.1% fee - const fee = 0.001 - const feePerValidator = toBN(166666666666666) - const feePerValidatorPlusDiff = toBN(166666666666668) - const valueCalc = relativeValue * (1 - fee) - const finalUserValue = ether(valueCalc.toString()) - const feeAmountCalc = relativeValue * fee - const feeAmount = ether(feeAmountCalc.toString()) - - // can't be called by user - await contract.handleBridgedTokens(user, value, { from: user }).should.be.rejectedWith(ERROR_MSG) - // can't be called by owner - await contract.handleBridgedTokens(user, value, { from: owner }).should.be.rejectedWith(ERROR_MSG) - - const data = await contract.contract.methods.handleBridgedTokens(user, value.toString()).encodeABI() - - // message must be generated by mediator contract on the other network - await ambBridgeContract.executeMessageCall(contract.address, owner, data, failedMessageId, 1000000).should.be - .fulfilled - - expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false) - - const initialBalanceRewardAddress1 = await token.balanceOf(rewardAccountList[0]) - const initialBalanceRewardAddress2 = await token.balanceOf(rewardAccountList[1]) - const initialBalanceRewardAddress3 = await token.balanceOf(rewardAccountList[2]) - - await ambBridgeContract.executeMessageCall( - contract.address, - otherSideMediatorContract.address, - data, - exampleMessageId, - 1000000 - ).should.be.fulfilled - - expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(true) - - // Then - expect(await contract.totalExecutedPerDay(currentDay)).to.be.bignumber.equal(value) - const events = await getEvents(token, { event: 'Mint' }) - // 1 Mint to user, 1 Mint to fee manager - expect(events.length).to.be.equal(2) - // Use ERC20 contract so there is no conflict on getting the regular event Transfer and the generated by transferAndCall - const erc20Token = await ERC20Mock.at(token.address) - const transferEvents = await getEvents(erc20Token, { event: 'Transfer' }) - // 5 transfer events: 1 Mint to user, 1 Mint to fee manager, fee manager 1 transfer to each reward account, - // 1 feeReceiver contract transfer to mediator, 1 transfer to 0 to burn the tokens - expect(transferEvents.length).to.be.equal(5) - - const burnEvents = await getEvents(token, { event: 'Burn' }) - expect(burnEvents.length).to.be.equal(0) - - const totalSupply = await token.totalSupply() - - expect(totalSupply).to.be.bignumber.equal(value) - - expect(await token.balanceOf(user)).to.be.bignumber.equal(finalUserValue) - - const updatedBalanceRewardAddress1 = await token.balanceOf(rewardAccountList[0]) - const updatedBalanceRewardAddress2 = await token.balanceOf(rewardAccountList[1]) - const updatedBalanceRewardAddress3 = await token.balanceOf(rewardAccountList[2]) - - expect( - updatedBalanceRewardAddress1.eq(initialBalanceRewardAddress1.add(feePerValidator)) || - updatedBalanceRewardAddress1.eq(initialBalanceRewardAddress1.add(feePerValidatorPlusDiff)) - ).to.equal(true) - expect( - updatedBalanceRewardAddress2.eq(initialBalanceRewardAddress2.add(feePerValidator)) || - updatedBalanceRewardAddress2.eq(initialBalanceRewardAddress2.add(feePerValidatorPlusDiff)) - ).to.equal(true) - expect( - updatedBalanceRewardAddress3.eq(initialBalanceRewardAddress3.add(feePerValidator)) || - updatedBalanceRewardAddress3.eq(initialBalanceRewardAddress3.add(feePerValidatorPlusDiff)) - ).to.equal(true) - - const feeEvents = await getEvents(contract, { event: 'FeeDistributed' }) - expect(feeEvents.length).to.be.equal(1) - expect(toBN(feeEvents[0].returnValues.feeAmount)).to.be.bignumber.equal(feeAmount) - expect(feeEvents[0].returnValues.messageId).to.be.equal(exampleMessageId) - const event = await getEvents(contract, { event: 'TokensBridged' }) expect(event.length).to.be.equal(1) expect(event[0].returnValues.recipient).to.be.equal(user) diff --git a/test/erc_to_erc/foreign_bridge.test.js b/test/erc_to_erc/foreign_bridge.test.js index 56651a4b..487a77c3 100644 --- a/test/erc_to_erc/foreign_bridge.test.js +++ b/test/erc_to_erc/foreign_bridge.test.js @@ -934,25 +934,15 @@ contract('ForeignBridge_ERC20_to_ERC20', async accounts => { // Given const currentDay = await foreignBridge.getCurrentDay() expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.relayTokens(recipient, value, { from: user }).should.be.rejectedWith(ERROR_MSG) await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled // When - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.fulfilled + await foreignBridge.relayTokens(ZERO_ADDRESS, value, { from: user }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.relayTokens(foreignBridge.address, value, { from: user }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.relayTokens(recipient, 0, { from: user }).should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.relayTokens(recipient, value, { from: user }).should.be.fulfilled // Then expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) @@ -961,33 +951,6 @@ contract('ForeignBridge_ERC20_to_ERC20', async accounts => { value }) }) - it('should allow to call relayTokens without specifying the sender', async () => { - // Given - await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - - await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - await foreignBridge.methods['relayTokens(address,uint256)'](ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,uint256)'](foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,uint256)'](recipient, 0, { from: user }).should.be.rejectedWith( - ERROR_MSG - ) - const { logs } = await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { from: user }) - .should.be.fulfilled - - // Then - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - }) it('should not be able to transfer more than limit', async () => { // Given const userSupply = ether('2') @@ -1000,71 +963,17 @@ contract('ForeignBridge_ERC20_to_ERC20', async accounts => { // When // value < minPerTx - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, smallValue, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.relayTokens(recipient, smallValue, { from: user }).should.be.rejectedWith(ERROR_MSG) // value > maxPerTx - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, bigValue, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) - .should.be.fulfilled - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) - .should.be.fulfilled + await foreignBridge.relayTokens(recipient, bigValue, { from: user }).should.be.rejectedWith(ERROR_MSG) + + await foreignBridge.relayTokens(recipient, halfEther, { from: user }).should.be.fulfilled + await foreignBridge.relayTokens(recipient, halfEther, { from: user }).should.be.fulfilled // totalSpentPerDay > dailyLimit - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge.relayTokens(recipient, halfEther, { from: user }).should.be.rejectedWith(ERROR_MSG) // Then expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(oneEther) }) - it('should allow only sender to specify a different receiver', async () => { - // Given - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - - await token.approve(foreignBridge.address, oneEther, { from: user }).should.be.fulfilled - - // When - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: recipient - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, value, { from: user }).should.be - .fulfilled - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.fulfilled - const { logs: logsSecondTx } = await foreignBridge.methods['relayTokens(address,address,uint256)']( - user, - user, - value, - { from: recipient } - ).should.be.fulfilled - - // Then - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expectEventInLogs(logsSecondTx, 'UserRequestForAffirmation', { - recipient: user, - value - }) - }) }) }) diff --git a/test/erc_to_native/foreign_bridge.test.js b/test/erc_to_native/foreign_bridge.test.js index 84e2962a..a5b4f4df 100644 --- a/test/erc_to_native/foreign_bridge.test.js +++ b/test/erc_to_native/foreign_bridge.test.js @@ -31,7 +31,6 @@ const minDaiLimit = ether('100') const requireBlockConfirmations = 8 const gasPrice = web3.utils.toWei('1', 'gwei') const oneEther = ether('1') -const twoEthers = ether('2') const homeDailyLimit = oneEther const homeMaxPerTx = halfEther const dailyLimit = oneEther @@ -68,7 +67,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { let owner let token let otherSideBridge - let sai let dai const user = accounts[7] before(async () => { @@ -78,11 +76,7 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { await validatorContract.initialize(1, authorities, owner) otherSideBridge = await ForeignBridge.new() - // Used account 11 to deploy contracts. The contract addresses will be hardcoded in ForeignBridgeErcToNativeMock - const deployAccount = accounts[10] - sai = await ERC20Mock.new('sai', 'SAI', 18, { from: deployAccount }) dai = await ERC20Mock.new('dai', 'DAI', 18) - await sai.transferOwnership(accounts[0], { from: deployAccount }) await dai.mint(user, ether('100000')) }) @@ -907,23 +901,31 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { const currentDay = await foreignBridge.getCurrentDay() expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled // When - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, value, { + await foreignBridge + .relayTokens(ZERO_ADDRESS, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(foreignBridge.address, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(user, 0, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.relayTokens(user, value, { from: user }).should.be.fulfilled @@ -939,23 +941,20 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { const currentDay = await foreignBridge.getCurrentDay() expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - // When - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { + await foreignBridge + .relayTokens(recipient, 0, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.relayTokens(recipient, value, { from: user }).should.be.fulfilled @@ -966,50 +965,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { value }) }) - it('should allow only sender to specify a different receiver', async () => { - // Given - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - - await token.approve(foreignBridge.address, oneEther, { from: user }).should.be.fulfilled - - // When - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: recipient - }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.fulfilled - const { logs: logsSecondTx } = await foreignBridge.methods['relayTokens(address,address,uint256)']( - user, - user, - value, - { from: recipient } - ).should.be.fulfilled - - // Then - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expectEventInLogs(logsSecondTx, 'UserRequestForAffirmation', { - recipient: user, - value - }) - }) it('should not be able to transfer more than limit', async () => { // Given const userSupply = ether('2') @@ -1022,53 +977,30 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { // When // value < minPerTx - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, smallValue, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, smallValue, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) // value > maxPerTx - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, bigValue, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, bigValue, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) - .should.be.fulfilled - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { from: user }) - .should.be.fulfilled + await foreignBridge.relayTokens(recipient, halfEther, { from: user }).should.be.fulfilled + await foreignBridge.relayTokens(recipient, halfEther, { from: user }).should.be.fulfilled // totalSpentPerDay > dailyLimit - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, halfEther, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, halfEther, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) // Then expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(oneEther) }) - it('should allow to call relayTokens without specifying the sender', async () => { - // Given - await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - - await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - await foreignBridge.methods['relayTokens(address,uint256)'](ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,uint256)'](foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,uint256)'](recipient, 0, { from: user }).should.be.rejectedWith( - ERROR_MSG - ) - const { logs } = await foreignBridge.methods['relayTokens(address,uint256)'](recipient, value, { from: user }) - .should.be.fulfilled - - // Then - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - }) }) describe('#relayTokens with chai', async () => { const user = accounts[7] @@ -1101,22 +1033,30 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { const currentDay = await foreignBridge.getCurrentDay() expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, recipient, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(recipient, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, ZERO_ADDRESS, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, foreignBridge.address, value, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, 0, { - from: user - }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, value, { + await foreignBridge + .relayTokens(ZERO_ADDRESS, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(foreignBridge.address, value, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + await foreignBridge + .relayTokens(user, 0, { + from: user + }) + .should.be.rejectedWith(ERROR_MSG) + const { logs } = await foreignBridge.relayTokens(user, value, { from: user }).should.be.fulfilled @@ -1137,7 +1077,7 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { await token.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - const { logs } = await foreignBridge.methods['relayTokens(address,address,uint256)'](user, user, value, { + const { logs } = await foreignBridge.relayTokens(user, value, { from: user }).should.be.fulfilled @@ -1150,241 +1090,6 @@ contract('ForeignBridge_ERC20_to_Native', async accounts => { expect(await token.balanceOf(foreignBridge.address)).to.be.bignumber.equal(minDaiLimit) }) }) - describe('support two tokens', () => { - let foreignBridge - const recipient = accounts[8] - beforeEach(async () => { - foreignBridge = await ForeignBridgeErcToNativeMock.new() - - await foreignBridge.initialize( - validatorContract.address, - dai.address, - requireBlockConfirmations, - gasPrice, - [dailyLimit, maxPerTx, minPerTx], - [homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero, - otherSideBridge.address - ) - - // Mint sai tokens to a user - await sai.mint(user, twoEthers) - }) - describe('relayTokens', () => { - const value = ether('0.25') - it('should allow to bridge tokens specifying the token address', async () => { - // Given - const balance = await dai.balanceOf(user) - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await relayTokens(recipient, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - - await dai.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - await relayTokens(ZERO_ADDRESS, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(foreignBridge.address, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(otherSideBridge.address, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(recipient, 0, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await relayTokens(recipient, value, dai.address, { from: user }).should.be.fulfilled - - // Then - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expect(await dai.balanceOf(user)).to.be.bignumber.equal(balance.sub(value)) - }) - it('should use erc20Token if token address is zero', async () => { - // Given - const balance = await dai.balanceOf(user) - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await dai.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - const { logs } = await relayTokens(recipient, value, ZERO_ADDRESS, { from: user }).should.be.fulfilled - - // Then - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expect(await dai.balanceOf(user)).to.be.bignumber.equal(balance.sub(value)) - }) - it('should fail if token address is unknown', async () => { - const otherToken = await ERC20Mock.new('token', 'TOK', 18) - await otherToken.mint(user, twoEthers) - - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - await otherToken.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - await relayTokens(recipient, value, otherToken.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - }) - it('should allow specify the sender and a different receiver', async () => { - // Given - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - const userBalance = await dai.balanceOf(user) - - const relayTokens = foreignBridge.methods['relayTokens(address,address,uint256,address)'] - - await relayTokens(user, recipient, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - - await dai.approve(foreignBridge.address, halfEther, { from: user }).should.be.fulfilled - - // When - await relayTokens(user, ZERO_ADDRESS, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(user, foreignBridge.address, value, dai.address, { from: user }).should.be.rejectedWith( - ERROR_MSG - ) - await relayTokens(user, recipient, 0, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(user, recipient, value, dai.address, { from: recipient }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await relayTokens(user, recipient, value, dai.address, { from: user }).should.be.fulfilled - const { logs: logsSecondTx } = await relayTokens(user, user, value, dai.address, { from: recipient }).should.be - .fulfilled - - // Then - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expectEventInLogs(logsSecondTx, 'UserRequestForAffirmation', { - recipient: user, - value - }) - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(halfEther) - expect(await dai.balanceOf(user)).to.be.bignumber.equal(userBalance.sub(halfEther)) - expect(await dai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther) - }) - it('should not be able to transfer more than limit', async () => { - // Given - const userSupply = ether('2') - const bigValue = oneEther - const smallValue = ether('0.001') - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - await dai.approve(foreignBridge.address, userSupply, { from: user }).should.be.fulfilled - - // When - // value < minPerTx - await relayTokens(recipient, smallValue, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - // value > maxPerTx - await relayTokens(recipient, bigValue, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - - await relayTokens(recipient, halfEther, dai.address, { from: user }).should.be.fulfilled - await relayTokens(recipient, halfEther, dai.address, { from: user }).should.be.fulfilled - // totalSpentPerDay > dailyLimit - await relayTokens(recipient, halfEther, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - - // Then - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(oneEther) - }) - }) - describe('relayTokens with chai token', async () => { - let foreignBridge - let dai - const value = ether('0.25') - const recipient = accounts[8] - beforeEach(async () => { - dai = await DaiMock.new({ from: owner }) - foreignBridge = await ForeignBridgeErcToNativeMock.new() - - await foreignBridge.initialize( - validatorContract.address, - dai.address, - requireBlockConfirmations, - gasPrice, - [dailyLimit, maxPerTx, minPerTx], - [homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero, - otherSideBridge.address - ) - - await dai.mint(user, twoEthers) - }) - - it('should allow to bridge tokens specifying the token address with chai token enabled', async () => { - // Given - const { chaiToken } = await createChaiToken(dai, foreignBridge, owner) - await foreignBridge.methods['initializeChaiToken()']() - expect(await chaiToken.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - - const balance = await dai.balanceOf(user) - const relayTokens = foreignBridge.methods['relayTokens(address,uint256,address)'] - - const currentDay = await foreignBridge.getCurrentDay() - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(ZERO) - - await relayTokens(recipient, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - - await dai.approve(foreignBridge.address, value, { from: user }).should.be.fulfilled - - // When - await relayTokens(ZERO_ADDRESS, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(foreignBridge.address, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(otherSideBridge.address, value, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - await relayTokens(recipient, 0, dai.address, { from: user }).should.be.rejectedWith(ERROR_MSG) - const { logs } = await relayTokens(recipient, value, dai.address, { from: user }).should.be.fulfilled - - // Then - expect(await foreignBridge.totalSpentPerDay(currentDay)).to.be.bignumber.equal(value) - expectEventInLogs(logs, 'UserRequestForAffirmation', { - recipient, - value - }) - expect(await dai.balanceOf(user)).to.be.bignumber.equal(balance.sub(value)) - expect(await chaiToken.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - }) - }) - describe('claimTokens', async () => { - it('can send erc20', async () => { - const foreignBridgeImpl = await ForeignBridgeErcToNativeMock.new() - const storageProxy = await EternalStorageProxy.new().should.be.fulfilled - await storageProxy.upgradeTo('1', foreignBridgeImpl.address).should.be.fulfilled - const foreignBridge = await ForeignBridgeErcToNativeMock.at(storageProxy.address) - - await foreignBridge.initialize( - validatorContract.address, - dai.address, - requireBlockConfirmations, - gasPrice, - [dailyLimit, maxPerTx, minPerTx], - [homeDailyLimit, homeMaxPerTx], - owner, - decimalShiftZero, - otherSideBridge.address - ) - - // Mint sai tokens to the bridge - await sai.mint(foreignBridge.address, halfEther) - - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(halfEther) - expect(await sai.balanceOf(accounts[3])).to.be.bignumber.equal(ZERO) - - await foreignBridge - .claimTokens(sai.address, accounts[3], { from: accounts[3] }) - .should.be.rejectedWith(ERROR_MSG) - await foreignBridge.claimTokens(sai.address, accounts[3], { from: owner }) - expect(await sai.balanceOf(foreignBridge.address)).to.be.bignumber.equal(ZERO) - expect(await sai.balanceOf(accounts[3])).to.be.bignumber.equal(halfEther) - }) - }) - }) describe('chai token', async () => { let token diff --git a/test/multi_amb_erc20_to_erc677/foreign_mediator.test.js b/test/multi_amb_erc20_to_erc677/foreign_mediator.test.js index 77835c48..585b2a47 100644 --- a/test/multi_amb_erc20_to_erc677/foreign_mediator.test.js +++ b/test/multi_amb_erc20_to_erc677/foreign_mediator.test.js @@ -76,20 +76,6 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { await contract.methods['relayTokens(address,address,uint256)'](token.address, user2, value, { from: user }).should .be.fulfilled return user2 - }, - async function relayTokensWithAlternativeReceiver2() { - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user2, value, { - from: user - }).should.be.fulfilled - return user2 - }, - async function relayTokensForOtherUser() { - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user, value, { - from: user2 - }).should.be.fulfilled - return user } ] @@ -300,14 +286,11 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await contract.dailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ether('5')) expect(await contract.executionDailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ether('5')) - await contract.setDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await token.transfer(contract.address, value, { from: user }).should.be.fulfilled - await contract.setDailyLimit(token.address, ZERO, { from: owner }).should.be.fulfilled - await contract.setExecutionDailyLimit(token.address, ZERO, { from: owner }).should.be.fulfilled + await contract.setDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled + await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled - expect(await contract.dailyLimit(token.address)).to.be.bignumber.equal(ZERO) - expect(await contract.executionDailyLimit(token.address)).to.be.bignumber.equal(ZERO) + expect(await contract.dailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) + expect(await contract.executionDailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) }) it('should allow to update default max per tx limits', async () => { @@ -322,14 +305,11 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await contract.maxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ether('1.5')) expect(await contract.executionMaxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ether('1.5')) - await contract.setMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await contract.setExecutionMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await token.transfer(contract.address, value, { from: user }).should.be.fulfilled - await contract.setMaxPerTx(token.address, ZERO, { from: owner }).should.be.fulfilled - await contract.setExecutionMaxPerTx(token.address, ZERO, { from: owner }).should.be.fulfilled + await contract.setMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled + await contract.setExecutionMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled - expect(await contract.maxPerTx(token.address)).to.be.bignumber.equal(ZERO) - expect(await contract.executionMaxPerTx(token.address)).to.be.bignumber.equal(ZERO) + expect(await contract.maxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) + expect(await contract.executionMaxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) }) it('should allow to update default min per tx limit', async () => { @@ -393,6 +373,13 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(halfEther) }) + it('should respect global shutdown', async () => { + await contract.setDailyLimit(ZERO_ADDRESS, ZERO).should.be.fulfilled + await token.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.rejected + await contract.setDailyLimit(ZERO_ADDRESS, dailyLimit).should.be.fulfilled + await token.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.fulfilled + }) + it('should be able to specify a different receiver', async () => { expect(await contract.isTokenRegistered(token.address)).to.be.equal(false) // must be a valid address param @@ -435,42 +422,6 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(value) }) - it('should allow user to specify a itself as receiver', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user, value, { - from: user - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(token.address, currentDay)).to.be.bignumber.equal(value) - expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(value) - }) - - it('should allow to specify a different receiver', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user2, value, { - from: user - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(token.address, currentDay)).to.be.bignumber.equal(value) - expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(value) - }) - it('should allow to specify a different receiver without specifying sender', async () => { // Given await token.approve(contract.address, value, { from: user }).should.be.fulfilled @@ -504,27 +455,6 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(value) }) - it('should allow to complete a transfer approved by other user', async () => { - // Given - await token.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await token.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user2, value, { - from: user2 - }).should.be.rejected - await contract.methods['relayTokens(address,address,address,uint256)'](token.address, user, user, value, { - from: user2 - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(token.address, currentDay)).to.be.bignumber.equal(value) - expect(await token.balanceOf(contract.address)).to.be.bignumber.equal(value) - }) - it('should fail if user did not approve the transfer', async () => { await contract.methods['relayTokens(address,address,uint256)'](token.address, user, value, { from: user }) .should.be.rejected @@ -673,6 +603,36 @@ contract('ForeignMultiAMBErc20ToErc677', async accounts => { expect(await ambBridgeContract.messageCallStatus(failedMessageId)).to.be.equal(false) }) + + it('should not allow to operate when global shutdown is enabled', async () => { + await token.transfer(contract.address, value, { from: user }).should.be.fulfilled + await token.transfer(contract.address, value, { from: user }).should.be.fulfilled + + const data = await contract.contract.methods + .handleBridgedTokens(token.address, user, value.toString()) + .encodeABI() + + await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO).should.be.fulfilled + await ambBridgeContract.executeMessageCall( + contract.address, + otherSideMediator.address, + data, + exampleMessageId, + 1000000 + ).should.be.fulfilled + + expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(false) + await contract.setExecutionDailyLimit(ZERO_ADDRESS, executionDailyLimit).should.be.fulfilled + await ambBridgeContract.executeMessageCall( + contract.address, + otherSideMediator.address, + data, + otherMessageId, + 1000000 + ).should.be.fulfilled + + expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(true) + }) }) describe('requestFailedMessageFix', () => { diff --git a/test/multi_amb_erc20_to_erc677/home_mediator.test.js b/test/multi_amb_erc20_to_erc677/home_mediator.test.js index c8e3f3dc..2e7d4e95 100644 --- a/test/multi_amb_erc20_to_erc677/home_mediator.test.js +++ b/test/multi_amb_erc20_to_erc677/home_mediator.test.js @@ -92,20 +92,6 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { await contract.methods['relayTokens(address,address,uint256)'](homeToken.address, user2, value, { from: user }) .should.be.fulfilled return user2 - }, - async function relayTokensWithAlternativeReceiver2() { - await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user2, value, { - from: user - }).should.be.fulfilled - return user2 - }, - async function relayTokensForOtherUser() { - await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user, value, { - from: user2 - }).should.be.fulfilled - return user } ] @@ -498,14 +484,11 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(await contract.dailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ether('5')) expect(await contract.executionDailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ether('5')) - await contract.setDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - token = await bridgeToken(token) - await contract.setDailyLimit(token.address, ZERO, { from: owner }).should.be.fulfilled - await contract.setExecutionDailyLimit(token.address, ZERO, { from: owner }).should.be.fulfilled + await contract.setDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled + await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled - expect(await contract.dailyLimit(token.address)).to.be.bignumber.equal(ZERO) - expect(await contract.executionDailyLimit(token.address)).to.be.bignumber.equal(ZERO) + expect(await contract.dailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) + expect(await contract.executionDailyLimit(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) }) it('should allow to update default max per tx limits', async () => { @@ -520,14 +503,11 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(await contract.maxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ether('1.5')) expect(await contract.executionMaxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ether('1.5')) - await contract.setMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - await contract.setExecutionMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.rejected - token = await bridgeToken(token) - await contract.setMaxPerTx(token.address, ZERO, { from: owner }).should.be.fulfilled - await contract.setExecutionMaxPerTx(token.address, ZERO, { from: owner }).should.be.fulfilled + await contract.setMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled + await contract.setExecutionMaxPerTx(ZERO_ADDRESS, ZERO, { from: owner }).should.be.fulfilled - expect(await contract.maxPerTx(token.address)).to.be.bignumber.equal(ZERO) - expect(await contract.executionMaxPerTx(token.address)).to.be.bignumber.equal(ZERO) + expect(await contract.maxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) + expect(await contract.executionMaxPerTx(ZERO_ADDRESS)).to.be.bignumber.equal(ZERO) }) it('should allow to update default min per tx limit', async () => { @@ -600,6 +580,13 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) }) + it('should respect global shutdown', async () => { + await contract.setDailyLimit(ZERO_ADDRESS, ZERO).should.be.fulfilled + await homeToken.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.rejected + await contract.setDailyLimit(ZERO_ADDRESS, dailyLimit).should.be.fulfilled + await homeToken.transferAndCall(contract.address, halfEther, '0x', { from: user }).should.be.fulfilled + }) + it('should be able to specify a different receiver', async () => { // must be a valid address param await homeToken.transferAndCall(contract.address, halfEther, '0x00', { from: user }).should.be.rejected @@ -642,44 +629,6 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) }) - it('should allow user to specify a itself as receiver', async () => { - // Given - await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await homeToken.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user, value, { - from: user - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(token.address).toLowerCase())).to.be.equal(true) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(homeToken.address, currentDay)).to.be.bignumber.equal(value) - expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) - }) - - it('should allow to specify a different receiver', async () => { - // Given - await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await homeToken.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user2, value, { - from: user - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(token.address).toLowerCase())).to.be.equal(true) - expect(events[0].returnValues.encodedData.includes(strip0x(user2).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(homeToken.address, currentDay)).to.be.bignumber.equal(value) - expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) - }) - it('should allow to specify a different receiver without specifying sender', async () => { // Given await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled @@ -716,28 +665,6 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) }) - it('should allow to complete a transfer approved by other user', async () => { - // Given - await homeToken.approve(contract.address, value, { from: user }).should.be.fulfilled - expect(await homeToken.allowance(user, contract.address)).to.be.bignumber.equal(value) - - // When - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user2, value, { - from: user2 - }).should.be.rejected - await contract.methods['relayTokens(address,address,address,uint256)'](homeToken.address, user, user, value, { - from: user2 - }).should.be.fulfilled - - // Then - const events = await getEvents(ambBridgeContract, { event: 'MockedEvent' }) - expect(events.length).to.be.equal(1) - expect(events[0].returnValues.encodedData.includes(strip0x(token.address).toLowerCase())).to.be.equal(true) - expect(events[0].returnValues.encodedData.includes(strip0x(user).toLowerCase())).to.be.equal(true) - expect(await contract.totalSpentPerDay(homeToken.address, currentDay)).to.be.bignumber.equal(value) - expect(await homeToken.balanceOf(contract.address)).to.be.bignumber.equal(ZERO) - }) - it('should fail if user did not approve the transfer', async () => { await contract.methods['relayTokens(address,address,uint256)'](homeToken.address, user, value, { from: user }) .should.be.rejected @@ -797,6 +724,33 @@ contract('HomeMultiAMBErc20ToErc677', async accounts => { expect(event[1].returnValues.messageId).to.be.equal(exampleMessageId) }) + it('should not allow to operate when global shutdown is enabled', async () => { + const data = await contract.contract.methods + .handleBridgedTokens(token.address, user, value.toString()) + .encodeABI() + + await contract.setExecutionDailyLimit(ZERO_ADDRESS, ZERO).should.be.fulfilled + await ambBridgeContract.executeMessageCall( + contract.address, + otherSideMediator.address, + data, + exampleMessageId, + 1000000 + ).should.be.fulfilled + + expect(await ambBridgeContract.messageCallStatus(exampleMessageId)).to.be.equal(false) + await contract.setExecutionDailyLimit(ZERO_ADDRESS, executionDailyLimit).should.be.fulfilled + await ambBridgeContract.executeMessageCall( + contract.address, + otherSideMediator.address, + data, + otherMessageId, + 1000000 + ).should.be.fulfilled + + expect(await ambBridgeContract.messageCallStatus(otherMessageId)).to.be.equal(true) + }) + it('should not allow to use unregistered tokens', async () => { const data = await contract.contract.methods .handleBridgedTokens(homeToken.address, user, value.toString()) diff --git a/test/poa20_test.js b/test/poa20_test.js index 3f8ec2fd..c59fcb88 100644 --- a/test/poa20_test.js +++ b/test/poa20_test.js @@ -27,7 +27,7 @@ const executionMaxPerTx = halfEther const ZERO = new BN(0) const decimalShiftZero = 0 -async function testERC677BridgeToken(accounts, rewardable, permittable, createToken) { +function testERC677BridgeToken(accounts, rewardable, permittable, createToken) { let token const owner = accounts[0] const user = accounts[1] @@ -910,22 +910,22 @@ async function testERC677BridgeToken(accounts, rewardable, permittable, createTo } } -contract('ERC677BridgeToken', async accounts => { - await testERC677BridgeToken(accounts, false, false, args => POA20.new(...args)) +contract('ERC677BridgeToken', accounts => { + testERC677BridgeToken(accounts, false, false, args => POA20.new(...args)) }) -contract('ERC677BridgeTokenRewardable', async accounts => { - await testERC677BridgeToken(accounts, true, true, args => POA20RewardableMock.new(...args)) +contract('ERC677BridgeTokenRewardable', accounts => { + testERC677BridgeToken(accounts, true, true, args => POA20RewardableMock.new(...args)) }) -contract('TokenProxy', async accounts => { +contract('TokenProxy', accounts => { const createToken = async args => { const impl = await PermittableTokenMock.new(...args) const proxy = await TokenProxy.new(impl.address, ...args) return PermittableTokenMock.at(proxy.address) } - await testERC677BridgeToken(accounts, false, true, createToken) + testERC677BridgeToken(accounts, false, true, createToken) describe('constants', () => { let token