From a2df7b5cfb445b71d24327edaed9fedb1718d980 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Sun, 1 Mar 2020 21:02:09 +0200 Subject: [PATCH 1/7] solc 0.5.16 add competition... --- contracts/Migrations.sol | 2 +- contracts/controller/Avatar.sol | 38 +- contracts/controller/Controller.sol | 2 +- contracts/controller/DAOToken.sol | 2 +- .../GlobalConstraintInterface.sol | 2 +- contracts/globalConstraints/TokenCapGC.sol | 2 +- contracts/libs/SafeERC20.sol | 2 +- contracts/schemes/Agreement.sol | 2 +- contracts/schemes/Auction4Reputation.sol | 2 +- contracts/schemes/Competition.sol | 416 +++++ .../ContinuousLockingToken4Reputation.sol | 2 +- contracts/schemes/ContributionReward.sol | 2 +- contracts/schemes/ContributionRewardExt.sol | 464 ++++++ contracts/schemes/CurveInterface.sol | 2 +- .../schemes/ExternalLocking4Reputation.sol | 2 +- .../schemes/FixedReputationAllocation.sol | 2 +- contracts/schemes/Forwarder.sol | 2 +- contracts/schemes/GenericScheme.sol | 2 +- .../schemes/GlobalConstraintRegistrar.sol | 2 +- contracts/schemes/Locking4Reputation.sol | 2 +- contracts/schemes/LockingEth4Reputation.sol | 2 +- contracts/schemes/LockingToken4Reputation.sol | 2 +- contracts/schemes/PriceOracleInterface.sol | 2 +- contracts/schemes/ReputationFromToken.sol | 2 +- contracts/schemes/SchemeRegistrar.sol | 2 +- contracts/schemes/SignalScheme.sol | 2 +- contracts/schemes/UpgradeScheme.sol | 2 +- .../schemes/VoteInOrganizationScheme.sol | 2 +- contracts/test/ARCDebug.sol | 2 +- .../test/ARCGenesisProtocolCallbacksMock.sol | 2 +- contracts/test/ActionMock.sol | 2 +- contracts/test/AgreementMock.sol | 2 +- contracts/test/BadERC20.sol | 2 +- contracts/test/ERC20Mock.sol | 2 +- contracts/test/ExternalTokenLockerMock.sol | 2 +- contracts/test/GlobalConstraintMock.sol | 2 +- contracts/test/NectarRepAllocation.sol | 2 +- contracts/test/PolkaCurve.sol | 2 +- contracts/test/PriceOracleMock.sol | 2 +- contracts/test/SafeERC20Mock.sol | 2 +- contracts/test/SchemeMock.sol | 2 +- contracts/test/Wallet.sol | 2 +- contracts/utils/DAOFactory.sol | 31 +- contracts/utils/DaoCreator.sol | 2 +- contracts/utils/Redeemer.sol | 119 +- contracts/utils/RepAllocation.sol | 2 +- .../votingMachines/VotingMachineCallbacks.sol | 2 +- package-lock.json | 1409 ++++++++++++----- package.json | 6 +- test/avatar.js | 47 +- test/competition.js | 724 +++++++++ test/constants.js | 2 +- test/contributionreward.js | 37 +- test/contributionrewardext.js | 725 +++++++++ test/controller.js | 19 +- test/helpers.js | 8 +- truffle.js | 2 +- 57 files changed, 3579 insertions(+), 552 deletions(-) create mode 100644 contracts/schemes/Competition.sol create mode 100644 contracts/schemes/ContributionRewardExt.sol create mode 100644 test/competition.js create mode 100644 test/contributionrewardext.js diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index 73ed161b..63f5a911 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; contract Migrations { diff --git a/contracts/controller/Avatar.sol b/contracts/controller/Avatar.sol index a08fc4d2..15592d12 100644 --- a/contracts/controller/Avatar.sol +++ b/contracts/controller/Avatar.sol @@ -7,6 +7,27 @@ import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.so import "../libs/SafeERC20.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; + +//Proxy contracts cannot recive eth via fallback function. +//For now , we will use this vault to overcome that +contract Vault is Ownable { + event ReceiveEther(address indexed _sender, uint256 _value); + + /** + * @dev enables this contract to receive ethers + */ + function() external payable { + emit ReceiveEther(msg.sender, msg.value); + } + + function sendEther(uint256 _amountInWei, address payable _to) external onlyOwner returns(bool) { + // solhint-disable-next-line avoid-call-value + (bool success, ) = _to.call.value(_amountInWei)(""); + require(success, "sendEther failed."); + } +} + + /** * @title An Avatar holds tokens, reputation and ether for a controller */ @@ -16,20 +37,24 @@ contract Avatar is Initializable, Ownable { string public orgName; DAOToken public nativeToken; Reputation public nativeReputation; + Vault public vault; event GenericCall(address indexed _contract, bytes _data, uint _value, bool _success); event SendEther(uint256 _amountInWei, address indexed _to); event ExternalTokenTransfer(address indexed _externalToken, address indexed _to, uint256 _value); event ExternalTokenTransferFrom(address indexed _externalToken, address _from, address _to, uint256 _value); event ExternalTokenApproval(address indexed _externalToken, address _spender, uint256 _value); - event ReceiveEther(address indexed _sender, uint256 _value); event MetaData(string _metaData); /** * @dev enables an avatar to receive ethers */ function() external payable { - emit ReceiveEther(msg.sender, msg.value); + if (msg.sender != address(vault)) { + // solhint-disable-next-line avoid-call-value + (bool success, ) = address(vault).call.value(msg.value)(""); + require(success, "sendEther failed."); + } } /** @@ -46,6 +71,8 @@ contract Avatar is Initializable, Ownable { nativeToken = _nativeToken; nativeReputation = _nativeReputation; Ownable.initialize(_owner); + vault = new Vault(); + vault.initialize(address(this)); } /** @@ -60,7 +87,10 @@ contract Avatar is Initializable, Ownable { external onlyOwner returns(bool success, bytes memory returnValue) { - // solhint-disable-next-line avoid-call-value + if (_value > 0) { + vault.sendEther(_value, address(this)); + } + // solhint-disable-next-line avoid-call-value (success, returnValue) = _contract.call.value(_value)(_data); emit GenericCall(_contract, _data, _value, success); } @@ -72,7 +102,7 @@ contract Avatar is Initializable, Ownable { * @return bool which represents success */ function sendEther(uint256 _amountInWei, address payable _to) external onlyOwner returns(bool) { - _to.transfer(_amountInWei); + vault.sendEther(_amountInWei, _to); emit SendEther(_amountInWei, _to); return true; } diff --git a/contracts/controller/Controller.sol b/contracts/controller/Controller.sol index ab6b25d8..b845998e 100644 --- a/contracts/controller/Controller.sol +++ b/contracts/controller/Controller.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "./Avatar.sol"; import "../globalConstraints/GlobalConstraintInterface.sol"; diff --git a/contracts/controller/DAOToken.sol b/contracts/controller/DAOToken.sol index 890df748..1153d405 100644 --- a/contracts/controller/DAOToken.sol +++ b/contracts/controller/DAOToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20Burnable.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/globalConstraints/GlobalConstraintInterface.sol b/contracts/globalConstraints/GlobalConstraintInterface.sol index c3981a63..567ebd15 100644 --- a/contracts/globalConstraints/GlobalConstraintInterface.sol +++ b/contracts/globalConstraints/GlobalConstraintInterface.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; contract GlobalConstraintInterface { diff --git a/contracts/globalConstraints/TokenCapGC.sol b/contracts/globalConstraints/TokenCapGC.sol index 45921e55..a8bb476f 100644 --- a/contracts/globalConstraints/TokenCapGC.sol +++ b/contracts/globalConstraints/TokenCapGC.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; import "./GlobalConstraintInterface.sol"; diff --git a/contracts/libs/SafeERC20.sol b/contracts/libs/SafeERC20.sol index 7dfc0254..d428b92a 100644 --- a/contracts/libs/SafeERC20.sol +++ b/contracts/libs/SafeERC20.sol @@ -12,7 +12,7 @@ REFERENCE & RELATED READING - https://gist.github.com/BrendanChou/88a2eeb80947ff00bcf58ffdafeaeb61 */ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/schemes/Agreement.sol b/contracts/schemes/Agreement.sol index 04d0c21e..03f46910 100644 --- a/contracts/schemes/Agreement.sol +++ b/contracts/schemes/Agreement.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; /** * @title A scheme for conduct ERC20 Tokens auction for reputation diff --git a/contracts/schemes/Auction4Reputation.sol b/contracts/schemes/Auction4Reputation.sol index 2dc24af7..d0c6788d 100644 --- a/contracts/schemes/Auction4Reputation.sol +++ b/contracts/schemes/Auction4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol"; import "../controller/Controller.sol"; diff --git a/contracts/schemes/Competition.sol b/contracts/schemes/Competition.sol new file mode 100644 index 00000000..8cd35e6c --- /dev/null +++ b/contracts/schemes/Competition.sol @@ -0,0 +1,416 @@ +pragma solidity 0.5.16; + +import "./ContributionRewardExt.sol"; + + +contract Competition is Initializable { + using SafeMath for uint256; + + uint256 constant public MAX_NUMBER_OF_WINNERS = 100; + + event NewCompetitionProposal( + bytes32 indexed _proposalId, + uint256 _numberOfWinners, + uint256[] _rewardSplit, + uint256 _startTime, + uint256 _votingStartTime, + uint256 _suggestionsEndTime, + uint256 _endTime, + uint256 _maxNumberOfVotesPerVoter, + address payable _contributionRewardExt, //address of the contract to redeem from. + address _admin + ); + + event Redeem( + bytes32 indexed _proposalId, + uint256 indexed _suggestionId, + uint256 _rewardPercentage + ); + + event NewSuggestion( + bytes32 indexed _proposalId, + uint256 indexed _suggestionId, + string _descriptionHash, + address payable indexed _beneficiary + ); + + event NewVote( + bytes32 indexed _proposalId, + uint256 indexed _suggestionId, + address indexed _voter, + uint256 _reputation + ); + + event SnapshotBlock( + bytes32 indexed _proposalId, + uint256 _snapshotBlock + ); + + // A struct holding the data for a competition proposal + struct Proposal { + uint256 numberOfWinners; + uint256[] rewardSplit; + uint256 startTime; + uint256 votingStartTime; + uint256 suggestionsEndTime; + uint256 endTime; + uint256 maxNumberOfVotesPerVoter; + address payable contributionRewardExt; + uint256 snapshotBlock; + uint256 reputationReward; + uint256 ethReward; + uint256 nativeTokenReward; + uint256 externalTokenReward; + uint256[] topSuggestions; + address admin; + //mapping from suggestions totalVotes to the number of suggestions with the same totalVotes. + mapping(uint256=>uint256) suggestionsPerVote; + mapping(address=>uint256) votesPerVoter; + } + + struct Suggestion { + uint256 totalVotes; + bytes32 proposalId; + address payable beneficiary; + mapping(address=>uint256) votes; + } + + //mapping from proposalID to Proposal + mapping(bytes32=>Proposal) public proposals; + //mapping from suggestionId to Suggestion + mapping(uint256=>Suggestion) public suggestions; + uint256 public suggestionsCounter; + address payable public contributionRewardExt; //address of the contract to redeem from. + + /** + * @dev initialize + * @param _contributionRewardExt the contributionRewardExt scheme which + * manage and allocate the rewards for the competition. + */ + function initialize(address payable _contributionRewardExt) external initializer { + require(_contributionRewardExt != address(0), "contributionRewardExt cannot be zero"); + contributionRewardExt = _contributionRewardExt; + } + + /** + * @dev Submit a competion proposal + * @param _descriptionHash A hash of the proposal's description + * @param _reputationChange - Amount of reputation change requested. + * @param _rewards rewards array: + * rewards[0] - Amount of tokens requested per period + * rewards[1] - Amount of ETH requested per period + * rewards[2] - Amount of external tokens requested per period + * @param _externalToken Address of external token, if reward is requested there + * @param _rewardSplit an array of precentages which specify how to split the rewards + * between the winning suggestions + * @param _competitionParams competition parameters : + * _competitionParams[0] - competition startTime + * _competitionParams[1] - _votingStartTime competition voting start time + * _competitionParams[2] - _endTime competition end time + * _competitionParams[3] - _maxNumberOfVotesPerVoter on how many suggestions a voter can vote + * _competitionParams[4] - _suggestionsEndTime suggestion submission end time + * _proposerIsAdmin - + * true - proposer is an admin. + * false no admin. + * if admin is set, so only admin can suggest on this proposal. + * @return proposalId the proposal id. + */ + function proposeCompetition( + string calldata _descriptionHash, + int256 _reputationChange, + uint[3] calldata _rewards, + IERC20 _externalToken, + uint256[] calldata _rewardSplit, + uint256[5] calldata _competitionParams, + bool _proposerIsAdmin + ) + external + // solhint-disable-next-line function-max-lines + returns(bytes32 proposalId) { + uint256 numberOfWinners = _rewardSplit.length; + uint256 startTime = _competitionParams[0]; + if (startTime == 0) { + // solhint-disable-next-line not-rely-on-time + startTime = now; + } + // solhint-disable-next-line not-rely-on-time + require(startTime >= now, "startTime should be greater than proposing time"); + require(numberOfWinners <= MAX_NUMBER_OF_WINNERS, "number of winners greater than max allowed"); + require(_competitionParams[1] < _competitionParams[2], "voting start time greater than end time"); + require(_competitionParams[1] >= startTime, "voting start time smaller than start time"); + require(_competitionParams[3] > 0, "maxNumberOfVotesPerVoter should be greater than 0"); + require(_competitionParams[4] <= _competitionParams[2], + "suggestionsEndTime should be earlier than proposal end time"); + require(_competitionParams[4] > startTime, "suggestionsEndTime should be later than proposal start time"); + if (_rewards[2] > 0) { + require(_externalToken != ERC20(0), "extenal token cannot be zero"); + } + require(_reputationChange >= 0, "negative reputation change is not allowed for a competition"); + uint256 totalRewardSplit; + for (uint256 i = 0; i < numberOfWinners; i++) { + totalRewardSplit = totalRewardSplit.add(_rewardSplit[i]); + } + require(totalRewardSplit == 100, "total rewards split is not 100%"); + proposalId = ContributionRewardExt(contributionRewardExt).proposeContributionReward( + _descriptionHash, _reputationChange, _rewards, _externalToken, contributionRewardExt, msg.sender); + proposals[proposalId].numberOfWinners = numberOfWinners; + proposals[proposalId].rewardSplit = _rewardSplit; + proposals[proposalId].startTime = startTime; + proposals[proposalId].votingStartTime = _competitionParams[1]; + proposals[proposalId].endTime = _competitionParams[2]; + proposals[proposalId].maxNumberOfVotesPerVoter = _competitionParams[3]; + proposals[proposalId].suggestionsEndTime = _competitionParams[4]; + proposals[proposalId].reputationReward = uint256(_reputationChange); + proposals[proposalId].nativeTokenReward = _rewards[0]; + proposals[proposalId].ethReward = _rewards[1]; + proposals[proposalId].externalTokenReward = _rewards[2]; + proposals[proposalId].snapshotBlock = 0; + if (_proposerIsAdmin) { + proposals[proposalId].admin = msg.sender; + } + emit NewCompetitionProposal( + proposalId, + numberOfWinners, + proposals[proposalId].rewardSplit, + startTime, + proposals[proposalId].votingStartTime, + proposals[proposalId].suggestionsEndTime, + proposals[proposalId].endTime, + proposals[proposalId].maxNumberOfVotesPerVoter, + contributionRewardExt, + proposals[proposalId].admin + ); + } + + /** + * @dev submit a competion suggestion + * @param _proposalId the proposal id this suggestion is referring to. + * @param _descriptionHash a descriptionHash of the suggestion. + * @param _beneficiary the beneficiary of this suggestion. + * @return suggestionId the suggestionId. + */ + function suggest( + bytes32 _proposalId, + string calldata _descriptionHash, + address payable _beneficiary + ) + external + returns(uint256) + { + if (proposals[_proposalId].admin != address(0)) { + require(proposals[_proposalId].admin == msg.sender, "only admin can suggest"); + } + // solhint-disable-next-line not-rely-on-time + require(proposals[_proposalId].startTime <= now, "competition not started yet"); + // solhint-disable-next-line not-rely-on-time + require(proposals[_proposalId].suggestionsEndTime > now, "suggestions submission time is over"); + suggestionsCounter = suggestionsCounter.add(1); + suggestions[suggestionsCounter].proposalId = _proposalId; + address payable beneficiary; + if (_beneficiary == address(0)) { + beneficiary = msg.sender; + } else { + beneficiary = _beneficiary; + } + suggestions[suggestionsCounter].beneficiary = beneficiary; + emit NewSuggestion(_proposalId, suggestionsCounter, _descriptionHash, beneficiary); + return suggestionsCounter; + } + + /** + * @dev vote on a suggestion + * @param _suggestionId suggestionId + * @return bool + */ + function vote(uint256 _suggestionId) + external + returns(bool) + { + bytes32 proposalId = suggestions[_suggestionId].proposalId; + require(proposalId != bytes32(0), "suggestion does not exist"); + setSnapshotBlock(proposalId); + Avatar avatar = ContributionRewardExt(contributionRewardExt).avatar(); + uint256 reputation = avatar.nativeReputation().balanceOfAt(msg.sender, proposals[proposalId].snapshotBlock); + require(reputation > 0, "voter had no reputation when snapshot was taken"); + Proposal storage proposal = proposals[proposalId]; + // solhint-disable-next-line not-rely-on-time + require(proposal.endTime > now, "competition ended"); + Suggestion storage suggestion = suggestions[_suggestionId]; + require(suggestion.votes[msg.sender] == 0, "already voted on this suggestion"); + require(proposal.votesPerVoter[msg.sender] < proposal.maxNumberOfVotesPerVoter, + "exceed number of votes allowed"); + proposal.votesPerVoter[msg.sender] = proposal.votesPerVoter[msg.sender].add(1); + if (suggestion.totalVotes > 0) { + proposal.suggestionsPerVote[suggestion.totalVotes] = + proposal.suggestionsPerVote[suggestion.totalVotes].sub(1); + } + suggestion.totalVotes = suggestion.totalVotes.add(reputation); + proposal.suggestionsPerVote[suggestion.totalVotes] = proposal.suggestionsPerVote[suggestion.totalVotes].add(1); + suggestion.votes[msg.sender] = reputation; + refreshTopSuggestions(proposalId, _suggestionId); + emit NewVote(proposalId, _suggestionId, msg.sender, reputation); + return true; + } + + /** + * @dev setSnapshotBlock set the block for the reputaion snapshot + * this function is public in order to externaly set snapshot block regardless of the first voting event. + * @param _proposalId the proposal id + */ + function setSnapshotBlock(bytes32 _proposalId) public { + // solhint-disable-next-line not-rely-on-time + require(proposals[_proposalId].votingStartTime < now, "voting period not started yet"); + require(proposals[_proposalId].maxNumberOfVotesPerVoter > 0, "proposal does not exist"); + if (proposals[_proposalId].snapshotBlock == 0) { + proposals[_proposalId].snapshotBlock = block.number; + emit SnapshotBlock(_proposalId, block.number); + } + } + + /** + * @dev sendLeftOverFund send leftover funds back to the dao. + * @param _proposalId the proposal id + */ + function sendLeftOverFunds(bytes32 _proposalId) public { + // solhint-disable-next-line not-rely-on-time + require(proposals[_proposalId].endTime < now, "competition is still on"); + require(proposals[_proposalId].maxNumberOfVotesPerVoter > 0, "proposal does not exist"); + require(_proposalId != bytes32(0), "proposalId is zero"); + uint256[] memory topSuggestions = proposals[_proposalId].topSuggestions; + for (uint256 i = 0; i < topSuggestions.length; i++) { + require(suggestions[topSuggestions[i]].beneficiary == address(0), "not all winning suggestions redeemed"); + } + + (, , , , , , + uint256 nativeTokenRewardLeft, , + uint256 ethRewardLeft, + uint256 externalTokenRewardLeft,) + = ContributionRewardExt(contributionRewardExt).organizationProposals(_proposalId); + + Avatar avatar = ContributionRewardExt(contributionRewardExt).avatar(); + + ContributionRewardExt(contributionRewardExt).redeemExternalTokenByRewarder( + _proposalId, address(avatar), externalTokenRewardLeft); + + ContributionRewardExt(contributionRewardExt).redeemEtherByRewarder( + _proposalId, address(avatar.vault()), ethRewardLeft); + + ContributionRewardExt(contributionRewardExt).redeemNativeTokenByRewarder( + _proposalId, address(avatar), nativeTokenRewardLeft); + } + + /** + * @dev redeem a winning suggestion reward + * @param _suggestionId suggestionId + */ + function redeem(uint256 _suggestionId) public { + bytes32 proposalId = suggestions[_suggestionId].proposalId; + require(proposalId != bytes32(0), "proposalId is zero"); + Proposal storage proposal = proposals[proposalId]; + require(_suggestionId > 0, "suggestionId is zero"); + // solhint-disable-next-line not-rely-on-time + require(proposal.endTime < now, "competition is still on"); + require(proposal.maxNumberOfVotesPerVoter > 0, "proposal does not exist"); + require(suggestions[_suggestionId].beneficiary != address(0), + "suggestion was already redeemed"); + address payable beneficiary = suggestions[_suggestionId].beneficiary; + uint256 orderIndex = getOrderedIndexOfSuggestion(_suggestionId); + require(orderIndex < proposal.topSuggestions.length, "suggestion is not in winners list"); + suggestions[_suggestionId].beneficiary = address(0); + uint256 rewardPercentage = 0; + uint256 numberOfTieSuggestions = proposal.suggestionsPerVote[suggestions[_suggestionId].totalVotes]; + uint256 j; + //calc the reward percentage for this suggestion + for (j = orderIndex; j < (orderIndex+numberOfTieSuggestions) && j < proposal.numberOfWinners; j++) { + rewardPercentage = rewardPercentage.add(proposal.rewardSplit[j]); + } + rewardPercentage = rewardPercentage.div(numberOfTieSuggestions); + uint256 rewardPercentageLeft = 0; + if (proposal.topSuggestions.length < proposal.numberOfWinners) { + //if there are less winners than the proposal number of winners so divide the pre allocated + //left reward equally between the winners + for (j = proposal.topSuggestions.length; j < proposal.numberOfWinners; j++) { + rewardPercentageLeft = rewardPercentageLeft.add(proposal.rewardSplit[j]); + } + rewardPercentage = + rewardPercentage.add(rewardPercentageLeft.div(proposal.topSuggestions.length)); + } + uint256 amount; + amount = proposal.externalTokenReward.mul(rewardPercentage).div(100); + ContributionRewardExt(contributionRewardExt).redeemExternalTokenByRewarder( + proposalId, beneficiary, amount); + + amount = proposal.reputationReward.mul(rewardPercentage).div(100); + ContributionRewardExt(contributionRewardExt).redeemReputationByRewarder( + proposalId, beneficiary, amount); + + amount = proposal.ethReward.mul(rewardPercentage).div(100); + ContributionRewardExt(contributionRewardExt).redeemEtherByRewarder( + proposalId, beneficiary, amount); + + amount = proposal.nativeTokenReward.mul(rewardPercentage).div(100); + ContributionRewardExt(contributionRewardExt).redeemNativeTokenByRewarder( + proposalId, beneficiary, amount); + emit Redeem(proposalId, _suggestionId, rewardPercentage); + } + + /** + * @dev getOrderedIndexOfSuggestion return the index of specific suggestion in the winners list. + * for the case when the suggestion is NOT in the winners list, + * this method will return topSuggestions.length + * @param _suggestionId suggestion id + */ + function getOrderedIndexOfSuggestion(uint256 _suggestionId) + public + view + returns(uint256 index) { + bytes32 proposalId = suggestions[_suggestionId].proposalId; + require(proposalId != bytes32(0), "suggestion does not exist"); + uint256[] memory topSuggestions = proposals[proposalId].topSuggestions; + /** get how many elements are greater than a given element*/ + for (uint256 i = 0; i < topSuggestions.length; i++) { + if (suggestions[topSuggestions[i]].totalVotes > suggestions[_suggestionId].totalVotes) { + index++; + } + } + } + + /** + * @dev refreshTopSuggestions this function maintain a winners list array. + * it will check if the given suggestion is among the top suggestions, and if so, + * update the list of top suggestions + * @param _proposalId proposal id + * @param _suggestionId suggestion id + */ + // solhint-disable-next-line code-complexity + function refreshTopSuggestions(bytes32 _proposalId, uint256 _suggestionId) private { + uint256[] storage topSuggestions = proposals[_proposalId].topSuggestions; + uint256 topSuggestionsLength = topSuggestions.length; + uint256 i; + if (topSuggestionsLength < proposals[_proposalId].numberOfWinners) { + for (i = 0; i < topSuggestionsLength; i++) { + if (topSuggestions[i] == _suggestionId) { + return; + } + } + topSuggestions.push(_suggestionId); + } else { + /** get the index of the smallest element **/ + uint256 smallest = 0; + for (i = 0; i < proposals[_proposalId].numberOfWinners; i++) { + if (suggestions[topSuggestions[i]].totalVotes < + suggestions[topSuggestions[smallest]].totalVotes) { + smallest = i; + } else if (topSuggestions[i] == _suggestionId) { + //the suggestion is already in the topSuggestions list + return; + } + } + + if (suggestions[topSuggestions[smallest]].totalVotes < suggestions[_suggestionId].totalVotes) { + topSuggestions[smallest] = _suggestionId; + } + } + } + +} diff --git a/contracts/schemes/ContinuousLockingToken4Reputation.sol b/contracts/schemes/ContinuousLockingToken4Reputation.sol index bc0eaff9..9d8aaef3 100644 --- a/contracts/schemes/ContinuousLockingToken4Reputation.sol +++ b/contracts/schemes/ContinuousLockingToken4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/math/Math.sol"; diff --git a/contracts/schemes/ContributionReward.sol b/contracts/schemes/ContributionReward.sol index c132b0fd..bc4fb70b 100644 --- a/contracts/schemes/ContributionReward.sol +++ b/contracts/schemes/ContributionReward.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../votingMachines/VotingMachineCallbacks.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; diff --git a/contracts/schemes/ContributionRewardExt.sol b/contracts/schemes/ContributionRewardExt.sol new file mode 100644 index 00000000..28a5c69f --- /dev/null +++ b/contracts/schemes/ContributionRewardExt.sol @@ -0,0 +1,464 @@ +pragma solidity 0.5.16; + +import "../votingMachines/VotingMachineCallbacks.sol"; +import "../libs/SafeERC20.sol"; + +/** + * @title A scheme for proposing and rewarding contributions to an organization + * @dev An agent can ask an organization to recognize a contribution and reward + * him with token, reputation, ether or any combination. + * This scheme extend the functionality of the ContributionReward scheme. + * It enable to assign a rewarder, which, after the contributionreward has been accepted, + * can then later distribute the assets as it would like. + */ +contract ContributionRewardExt is VotingMachineCallbacks, ProposalExecuteInterface, Initializable { + using SafeMath for uint; + using SafeERC20 for address; + + event NewContributionProposal( + address indexed _avatar, + bytes32 indexed _proposalId, + address indexed _intVoteInterface, + string _descriptionHash, + int256 _reputationChange, + uint[3] _rewards, + IERC20 _externalToken, + address _beneficiary, + address _proposer + ); + + event ProposalExecuted(address indexed _avatar, bytes32 indexed _proposalId, int256 _param); + + event RedeemReputation( + address indexed _avatar, + bytes32 indexed _proposalId, + address indexed _beneficiary, + int256 _amount); + + event RedeemEther(address indexed _avatar, + bytes32 indexed _proposalId, + address indexed _beneficiary, + uint256 _amount); + + event RedeemNativeToken(address indexed _avatar, + bytes32 indexed _proposalId, + address indexed _beneficiary, + uint256 _amount); + + event RedeemExternalToken(address indexed _avatar, + bytes32 indexed _proposalId, + address indexed _beneficiary, + uint256 _amount); + + // A struct holding the data for a contribution proposal + struct ContributionProposal { + uint256 nativeTokenReward; // Reward asked in the native token of the organization. + int256 reputationChange; // Organization reputation reward requested. + uint256 ethReward; + IERC20 externalToken; + uint256 externalTokenReward; + address payable beneficiary; + uint256 nativeTokenRewardLeft; + uint256 reputationChangeLeft; + uint256 ethRewardLeft; + uint256 externalTokenRewardLeft; + bool acceptedByVotingMachine; + } + + modifier onlyRewarder() { + require(msg.sender == rewarder, "msg.sender is not authorized"); + _; + } + + mapping(bytes32=>ContributionProposal) public organizationProposals; + + IntVoteInterface public votingMachine; + bytes32 public voteParams; + Avatar public avatar; + address public rewarder; + Vault public vault; + + /** + * @dev initialize + * @param _avatar the avatar to mint reputation from + * @param _votingMachine the voting machines address + * @param _voteParams voting machine parameters + * @param _rewarder an address which allowed to redeem the contribution. + if _rewarder is 0 this param is agnored. + */ + function initialize( + Avatar _avatar, + IntVoteInterface _votingMachine, + bytes32 _voteParams, + address _rewarder + ) + external + initializer + { + require(_avatar != Avatar(0), "avatar cannot be zero"); + require(_votingMachine != IntVoteInterface(0), "votingMachine cannot be zero"); + avatar = _avatar; + votingMachine = _votingMachine; + voteParams = _voteParams; + rewarder = _rewarder; + vault = new Vault(); + vault.initialize(address(this)); + } + + /** + * @dev execution of proposals, can only be called by the voting machine in which the vote is held. + * @param _proposalId the ID of the proposal in the voting machine + * @param _decision a parameter of the voting result, 1 yes and 2 is no. + */ + function executeProposal(bytes32 _proposalId, int256 _decision) + external + onlyVotingMachine(_proposalId) + returns(bool) { + require(organizationProposals[_proposalId].acceptedByVotingMachine == false); + require(organizationProposals[_proposalId].beneficiary != address(0)); + if (_decision == 1) { + organizationProposals[_proposalId].acceptedByVotingMachine = true; + } + emit ProposalExecuted(address(avatar), _proposalId, _decision); + return true; + } + + /** + * @dev Submit a proposal for a reward for a contribution: + * @param _descriptionHash A hash of the proposal's description + * @param _reputationChange - Amount of reputation change requested .Can be negative. + * @param _rewards rewards array: + * rewards[0] - Amount of tokens requested + * rewards[1] - Amount of ETH requested + * rewards[2] - Amount of external tokens + * @param _externalToken Address of external token, if reward is requested there + * @param _beneficiary Who gets the rewards. if equal to 0 the beneficiary will be msg.sender. + * @param _proposer proposer . if equal to 0 the proposer will be msg.sender. + */ + function proposeContributionReward( + string memory _descriptionHash, + int256 _reputationChange, + uint[3] memory _rewards, + IERC20 _externalToken, + address payable _beneficiary, + address _proposer + ) + public + returns(bytes32 proposalId) + { + address proposer = _proposer; + if (proposer == address(0)) { + proposer = msg.sender; + } + proposalId = votingMachine.propose(2, voteParams, proposer, address(avatar)); + address payable beneficiary = _beneficiary; + if (beneficiary == address(0)) { + beneficiary = msg.sender; + } + if (beneficiary == address(this)) { + require(_reputationChange >= 0, "negative rep change not allowed for this case"); + } + + ContributionProposal memory proposal = ContributionProposal({ + nativeTokenReward: _rewards[0], + reputationChange: _reputationChange, + ethReward: _rewards[1], + externalToken: _externalToken, + externalTokenReward: _rewards[2], + beneficiary: beneficiary, + nativeTokenRewardLeft: 0, + reputationChangeLeft: 0, + ethRewardLeft: 0, + externalTokenRewardLeft: 0, + acceptedByVotingMachine: false + }); + organizationProposals[proposalId] = proposal; + + emit NewContributionProposal( + address(avatar), + proposalId, + address(votingMachine), + _descriptionHash, + _reputationChange, + _rewards, + _externalToken, + beneficiary, + proposer + ); + + proposalsInfo[address(votingMachine)][proposalId] = ProposalInfo({ + blockNumber:block.number, + avatar:avatar + }); + } + + /** + * @dev RedeemReputation reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @return reputation the redeemed reputation. + */ + function redeemReputation(bytes32 _proposalId) public returns(int256 reputation) { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + + //if the beneficiary is the current contract, we are not minting the rep to it + //but instead refer to a mechanism in which the rep can be minted by the current contract + //per request of the rewarder + if (proposal.beneficiary == address(this)) { + if (proposal.reputationChangeLeft == 0) {//for now only mint(not burn) rep allowed from ext contract. + proposal.reputationChangeLeft = uint256(proposal.reputationChange); + proposal.reputationChange = 0; + } + } else { + reputation = proposal.reputationChange; + //set proposal reward to zero to prevent reentrancy attack. + proposal.reputationChange = 0; + + if (reputation > 0) { + require( + Controller( + avatar.owner()).mintReputation(uint(reputation), proposal.beneficiary)); + } else if (reputation < 0) { + require( + Controller( + avatar.owner()).burnReputation(uint(reputation*(-1)), proposal.beneficiary)); + } + if (reputation != 0) { + emit RedeemReputation(address(avatar), _proposalId, proposal.beneficiary, reputation); + } + } + } + + /** + * @dev RedeemNativeToken reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @return amount the redeemed nativeToken. + */ + function redeemNativeToken(bytes32 _proposalId) public returns(uint256 amount) { + + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + + if (proposal.beneficiary == address(this)) { + //ensure nativeTokenRewardLeft can be set only one time + if (proposal.nativeTokenRewardLeft == 0) { + proposal.nativeTokenRewardLeft = proposal.nativeTokenReward; + } + } + amount = proposal.nativeTokenReward; + //set proposal rewards to zero to prevent reentrancy attack. + proposal.nativeTokenReward = 0; + if (amount > 0) { + require(Controller(avatar.owner()).mintTokens(amount, proposal.beneficiary)); + emit RedeemNativeToken(address(avatar), _proposalId, proposal.beneficiary, amount); + } + } + + /** + * @dev RedeemEther reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @return amount ether redeemed amount + */ + function redeemEther(bytes32 _proposalId) public returns(uint256 amount) { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + address payable beneficiary = proposal.beneficiary; + + if (proposal.beneficiary == address(this)) { + if (proposal.ethRewardLeft == 0) { + proposal.ethRewardLeft = proposal.ethReward; + } + beneficiary = address(vault); + } + amount = proposal.ethReward; + //set proposal rewards to zero to prevent reentrancy attack. + proposal.ethReward = 0; + if (amount > 0) { + require(Controller(avatar.owner()).sendEther(amount, beneficiary)); + emit RedeemEther(address(avatar), _proposalId, proposal.beneficiary, amount); + } + } + + /** + * @dev RedeemNativeToken reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @return amount the external token redeemed amount + */ + function redeemExternalToken(bytes32 _proposalId) public returns(uint256 amount) { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + + + if (proposal.beneficiary == address(this)) { + if (proposal.externalTokenRewardLeft == 0) { + proposal.externalTokenRewardLeft = proposal.externalTokenReward; + } + } + + if (proposal.externalToken != IERC20(0) && proposal.externalTokenReward > 0) { + amount = proposal.externalTokenReward; + //set proposal rewards to zero to prevent reentrancy attack. + proposal.externalTokenReward = 0; + require( + Controller( + avatar.owner()) + .externalTokenTransfer(proposal.externalToken, proposal.beneficiary, amount)); + emit RedeemExternalToken(address(avatar), _proposalId, proposal.beneficiary, amount); + } + } + + /** + * @dev redeemReputationByRewarder redeem reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @param _beneficiary the beneficiary to mint reputation to. + * @param _reputation the reputation amount to mint + * note: burn reputation is not supported via this function + */ + function redeemReputationByRewarder(bytes32 _proposalId, address _beneficiary, uint256 _reputation) + public + onlyRewarder + { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + //this will ensure sum zero of reputation + //and that there was a privious call to redeemReputation function. + proposal.reputationChangeLeft = + proposal.reputationChangeLeft.sub(_reputation, + "cannot redeem more reputation than allocated for this proposal or no redeemReputation was called"); + require( + Controller( + avatar.owner()).mintReputation(_reputation, _beneficiary)); + if (_reputation != 0) { + emit RedeemReputation(address(avatar), _proposalId, _beneficiary, int256(_reputation)); + } + } + + /** + * @dev redeemNativeTokenByRewarder redeem reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @param _beneficiary the beneficiary to mint tokens to. + * @param _amount the tokens amount to mint + */ + function redeemNativeTokenByRewarder(bytes32 _proposalId, address _beneficiary, uint256 _amount) + public + onlyRewarder + { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + //this will ensure sum zero of reputation + //and that there was a privious call to redeemNativeToken function. + proposal.nativeTokenRewardLeft = + proposal.nativeTokenRewardLeft.sub(_amount, + "cannot redeem more tokens than allocated for this proposal or no redeemNativeToken was called"); + + if (_amount > 0) { + address(avatar.nativeToken()).safeTransfer(_beneficiary, _amount); + emit RedeemNativeToken(address(avatar), _proposalId, _beneficiary, _amount); + } + } + + /** + * @dev redeemEtherByRewarder redeem reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @param _beneficiary the beneficiary to send eth to. + * @param _amount eth amount to send + */ + function redeemEtherByRewarder(bytes32 _proposalId, address payable _beneficiary, uint256 _amount) + public + onlyRewarder + { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + //this will ensure sum zero of reputation. + //and that there was a privious call to redeemEther function. + proposal.ethRewardLeft = proposal.ethRewardLeft.sub(_amount, + "cannot redeem more Ether than allocated for this proposal or no redeemEther was called"); + + if (_amount > 0) { + vault.sendEther(_amount, _beneficiary); + emit RedeemEther(address(avatar), _proposalId, _beneficiary, _amount); + } + } + + /** + * @dev redeemExternalTokenByRewarder redeem reward for proposal + * @param _proposalId the ID of the voting in the voting machine + * @param _beneficiary the beneficiary to send the external token to. + * @param _amount the amount of external token to send + */ + function redeemExternalTokenByRewarder(bytes32 _proposalId, address _beneficiary, uint256 _amount) + public + onlyRewarder { + ContributionProposal storage proposal = organizationProposals[_proposalId]; + require(proposal.acceptedByVotingMachine, "proposal was not accepted by the voting machine"); + //this will ensure sum zero of reputation. + //and that there was a privious call to redeemExternalToken function. + proposal.externalTokenRewardLeft = + proposal.externalTokenRewardLeft.sub(_amount, + "cannot redeem more tokens than allocated for this proposal or no redeemExternalToken was called"); + + if (proposal.externalToken != IERC20(0)) { + if (_amount > 0) { + address(proposal.externalToken).safeTransfer(_beneficiary, _amount); + emit RedeemExternalToken(address(avatar), _proposalId, _beneficiary, _amount); + } + } + } + + /** + * @dev redeem rewards for proposal + * @param _proposalId the ID of the voting in the voting machine + * @param _whatToRedeem whatToRedeem array of boolean values: + * whatToRedeem[0] - reputation + * whatToRedeem[1] - nativeTokenReward + * whatToRedeem[2] - Ether + * whatToRedeem[3] - ExternalToken + * @return result boolean array for each redeem type. + */ + function redeem(bytes32 _proposalId, bool[4] memory _whatToRedeem) + public + returns(int256 reputationReward, uint256 nativeTokenReward, uint256 etherReward, uint256 externalTokenReward) + { + + if (_whatToRedeem[0]) { + reputationReward = redeemReputation(_proposalId); + } + + if (_whatToRedeem[1]) { + nativeTokenReward = redeemNativeToken(_proposalId); + } + + if (_whatToRedeem[2]) { + etherReward = redeemEther(_proposalId); + } + + if (_whatToRedeem[3]) { + externalTokenReward = redeemExternalToken(_proposalId); + } + } + + function getProposalEthReward(bytes32 _proposalId) public view returns (uint256) { + return organizationProposals[_proposalId].ethReward; + } + + function getProposalExternalTokenReward(bytes32 _proposalId) public view returns (uint256) { + return organizationProposals[_proposalId].externalTokenReward; + } + + function getProposalExternalToken(bytes32 _proposalId) public view returns (address) { + return address(organizationProposals[_proposalId].externalToken); + } + + function getProposalReputationReward(bytes32 _proposalId) public view returns (int256) { + return organizationProposals[_proposalId].reputationChange; + } + + function getProposalNativeTokenReward(bytes32 _proposalId) public view returns (uint256) { + return organizationProposals[_proposalId].nativeTokenReward; + } + + function getProposalAcceptedByVotingMachine(bytes32 _proposalId) public view returns (bool) { + return organizationProposals[_proposalId].acceptedByVotingMachine; + } + +} diff --git a/contracts/schemes/CurveInterface.sol b/contracts/schemes/CurveInterface.sol index e3580f65..b0db6c13 100644 --- a/contracts/schemes/CurveInterface.sol +++ b/contracts/schemes/CurveInterface.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; interface CurveInterface { diff --git a/contracts/schemes/ExternalLocking4Reputation.sol b/contracts/schemes/ExternalLocking4Reputation.sol index 6de7ade6..b653d32d 100644 --- a/contracts/schemes/ExternalLocking4Reputation.sol +++ b/contracts/schemes/ExternalLocking4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "./Locking4Reputation.sol"; diff --git a/contracts/schemes/FixedReputationAllocation.sol b/contracts/schemes/FixedReputationAllocation.sol index 7d531119..2ef1b09c 100644 --- a/contracts/schemes/FixedReputationAllocation.sol +++ b/contracts/schemes/FixedReputationAllocation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; diff --git a/contracts/schemes/Forwarder.sol b/contracts/schemes/Forwarder.sol index 66dd8632..e9b6fd6e 100644 --- a/contracts/schemes/Forwarder.sol +++ b/contracts/schemes/Forwarder.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; diff --git a/contracts/schemes/GenericScheme.sol b/contracts/schemes/GenericScheme.sol index f9c6b272..940ed835 100644 --- a/contracts/schemes/GenericScheme.sol +++ b/contracts/schemes/GenericScheme.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol"; import "@daostack/infra-experimental/contracts/votingMachines/VotingMachineCallbacksInterface.sol"; diff --git a/contracts/schemes/GlobalConstraintRegistrar.sol b/contracts/schemes/GlobalConstraintRegistrar.sol index cfdacd95..5a15a8fc 100644 --- a/contracts/schemes/GlobalConstraintRegistrar.sol +++ b/contracts/schemes/GlobalConstraintRegistrar.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol"; import "@daostack/infra-experimental/contracts/votingMachines/VotingMachineCallbacksInterface.sol"; diff --git a/contracts/schemes/Locking4Reputation.sol b/contracts/schemes/Locking4Reputation.sol index aebc62cf..837fea92 100644 --- a/contracts/schemes/Locking4Reputation.sol +++ b/contracts/schemes/Locking4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; import "./Agreement.sol"; diff --git a/contracts/schemes/LockingEth4Reputation.sol b/contracts/schemes/LockingEth4Reputation.sol index 38d95c42..49e5bbb9 100644 --- a/contracts/schemes/LockingEth4Reputation.sol +++ b/contracts/schemes/LockingEth4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "./Locking4Reputation.sol"; diff --git a/contracts/schemes/LockingToken4Reputation.sol b/contracts/schemes/LockingToken4Reputation.sol index 8c19b4af..f30e3061 100644 --- a/contracts/schemes/LockingToken4Reputation.sol +++ b/contracts/schemes/LockingToken4Reputation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "./Locking4Reputation.sol"; import "./PriceOracleInterface.sol"; diff --git a/contracts/schemes/PriceOracleInterface.sol b/contracts/schemes/PriceOracleInterface.sol index 5a3e0f4a..8f73b019 100644 --- a/contracts/schemes/PriceOracleInterface.sol +++ b/contracts/schemes/PriceOracleInterface.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; interface PriceOracleInterface { diff --git a/contracts/schemes/ReputationFromToken.sol b/contracts/schemes/ReputationFromToken.sol index 6d67b77d..fccb78b0 100644 --- a/contracts/schemes/ReputationFromToken.sol +++ b/contracts/schemes/ReputationFromToken.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/schemes/SchemeRegistrar.sol b/contracts/schemes/SchemeRegistrar.sol index 7e95b3c4..4850c7a5 100644 --- a/contracts/schemes/SchemeRegistrar.sol +++ b/contracts/schemes/SchemeRegistrar.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol"; import "@daostack/infra-experimental/contracts/votingMachines/VotingMachineCallbacksInterface.sol"; diff --git a/contracts/schemes/SignalScheme.sol b/contracts/schemes/SignalScheme.sol index 7c2ecf06..73e75cd7 100644 --- a/contracts/schemes/SignalScheme.sol +++ b/contracts/schemes/SignalScheme.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol"; import "@daostack/infra-experimental/contracts/votingMachines/VotingMachineCallbacksInterface.sol"; diff --git a/contracts/schemes/UpgradeScheme.sol b/contracts/schemes/UpgradeScheme.sol index 9eb22f24..713df704 100644 --- a/contracts/schemes/UpgradeScheme.sol +++ b/contracts/schemes/UpgradeScheme.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/IntVoteInterface.sol"; import "@daostack/infra-experimental/contracts/votingMachines/ProposalExecuteInterface.sol"; diff --git a/contracts/schemes/VoteInOrganizationScheme.sol b/contracts/schemes/VoteInOrganizationScheme.sol index c4d70e25..c1979e5b 100644 --- a/contracts/schemes/VoteInOrganizationScheme.sol +++ b/contracts/schemes/VoteInOrganizationScheme.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../votingMachines/VotingMachineCallbacks.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; diff --git a/contracts/test/ARCDebug.sol b/contracts/test/ARCDebug.sol index a7067d2c..ee489113 100644 --- a/contracts/test/ARCDebug.sol +++ b/contracts/test/ARCDebug.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/GenesisProtocol.sol"; import "@daostack/infra-experimental/contracts/votingMachines/AbsoluteVote.sol"; diff --git a/contracts/test/ARCGenesisProtocolCallbacksMock.sol b/contracts/test/ARCGenesisProtocolCallbacksMock.sol index c72f2dc7..ff027b5c 100644 --- a/contracts/test/ARCGenesisProtocolCallbacksMock.sol +++ b/contracts/test/ARCGenesisProtocolCallbacksMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../votingMachines/VotingMachineCallbacks.sol"; diff --git a/contracts/test/ActionMock.sol b/contracts/test/ActionMock.sol index a079e5b6..537b5ba6 100644 --- a/contracts/test/ActionMock.sol +++ b/contracts/test/ActionMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Avatar.sol"; diff --git a/contracts/test/AgreementMock.sol b/contracts/test/AgreementMock.sol index a631d2eb..fdf77dcf 100644 --- a/contracts/test/AgreementMock.sol +++ b/contracts/test/AgreementMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../schemes/Agreement.sol"; diff --git a/contracts/test/BadERC20.sol b/contracts/test/BadERC20.sol index 3c4cf1e6..195a6550 100644 --- a/contracts/test/BadERC20.sol +++ b/contracts/test/BadERC20.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; //this is a mock to simulate bad ERC20 token implementation as describe at //https://github.com/ethereum/solidity/issues/4116 diff --git a/contracts/test/ERC20Mock.sol b/contracts/test/ERC20Mock.sol index fa1dd100..de763282 100644 --- a/contracts/test/ERC20Mock.sol +++ b/contracts/test/ERC20Mock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol"; diff --git a/contracts/test/ExternalTokenLockerMock.sol b/contracts/test/ExternalTokenLockerMock.sol index 095feb1d..8f9c0cbc 100644 --- a/contracts/test/ExternalTokenLockerMock.sol +++ b/contracts/test/ExternalTokenLockerMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; diff --git a/contracts/test/GlobalConstraintMock.sol b/contracts/test/GlobalConstraintMock.sol index f55bb0d2..db465aa8 100644 --- a/contracts/test/GlobalConstraintMock.sol +++ b/contracts/test/GlobalConstraintMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../globalConstraints/GlobalConstraintInterface.sol"; diff --git a/contracts/test/NectarRepAllocation.sol b/contracts/test/NectarRepAllocation.sol index 293a631f..963c1931 100644 --- a/contracts/test/NectarRepAllocation.sol +++ b/contracts/test/NectarRepAllocation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/math/SafeMath.sol"; diff --git a/contracts/test/PolkaCurve.sol b/contracts/test/PolkaCurve.sol index bb15e72f..8018de0e 100644 --- a/contracts/test/PolkaCurve.sol +++ b/contracts/test/PolkaCurve.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../schemes/CurveInterface.sol"; diff --git a/contracts/test/PriceOracleMock.sol b/contracts/test/PriceOracleMock.sol index f853af20..39a3efcc 100644 --- a/contracts/test/PriceOracleMock.sol +++ b/contracts/test/PriceOracleMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../schemes/PriceOracleInterface.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; diff --git a/contracts/test/SafeERC20Mock.sol b/contracts/test/SafeERC20Mock.sol index 59b0f7f7..305ec278 100644 --- a/contracts/test/SafeERC20Mock.sol +++ b/contracts/test/SafeERC20Mock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "./BadERC20.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; diff --git a/contracts/test/SchemeMock.sol b/contracts/test/SchemeMock.sol index e0ccff98..cd5bbfa2 100644 --- a/contracts/test/SchemeMock.sol +++ b/contracts/test/SchemeMock.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; diff --git a/contracts/test/Wallet.sol b/contracts/test/Wallet.sol index 2cfc537a..72010c7d 100644 --- a/contracts/test/Wallet.sol +++ b/contracts/test/Wallet.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; diff --git a/contracts/utils/DAOFactory.sol b/contracts/utils/DAOFactory.sol index 77d756ea..e654fc5b 100644 --- a/contracts/utils/DAOFactory.sol +++ b/contracts/utils/DAOFactory.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/upgrades/contracts/Initializable.sol"; import "@openzeppelin/upgrades/contracts/application/App.sol"; @@ -20,6 +20,7 @@ contract DAOFactory is Initializable { address indexed _reputation, address _daotoken ); + event InitialSchemesSet (address indexed _avatar); event SchemeInstance(address indexed _scheme, string _name); /** @@ -64,15 +65,7 @@ contract DAOFactory is Initializable { uint64[3] calldata _version) external returns(address) { - Package package; - uint64[3] memory latestVersion; - (package, latestVersion) = app.getPackage(PACKAGE_NAME); - if (package.getContract(_version) == address(0)) { - require(package.getContract(latestVersion) != address(0), "ImplementationProvider does not exist"); - packageVersion = latestVersion; - } else { - packageVersion = _version; - } + packageVersion = getPackageVersion(_version); return _forgeOrg(_orgName, _tokenInitData, _founders, _foundersTokenAmount, _foundersReputationAmount); } @@ -162,12 +155,12 @@ contract DAOFactory is Initializable { payable returns (AdminUpgradeabilityProxy) { Package package; - + uint64[3] memory version = getPackageVersion(_packageVersion); (package, ) = app.getPackage(PACKAGE_NAME); - ImplementationProvider provider = ImplementationProvider(package.getContract(_packageVersion)); + ImplementationProvider provider = ImplementationProvider(package.getContract(version)); address implementation = provider.getImplementation(_contractName); AdminUpgradeabilityProxy proxy = (new AdminUpgradeabilityProxy).value(msg.value)(implementation, _admin, _data); - emit ProxyCreated(address(proxy), implementation, _contractName, _packageVersion); + emit ProxyCreated(address(proxy), implementation, _contractName, version); return proxy; } @@ -300,4 +293,16 @@ contract DAOFactory is Initializable { return (address(avatar)); } + function getPackageVersion(uint64[3] memory _version) private view returns(uint64[3] memory version) { + Package package; + uint64[3] memory latestVersion; + (package, latestVersion) = app.getPackage(PACKAGE_NAME); + if (package.getContract(_version) == address(0)) { + require(package.getContract(latestVersion) != address(0), "ImplementationProvider does not exist"); + version = latestVersion; + } else { + version = _version; + } + } + } diff --git a/contracts/utils/DaoCreator.sol b/contracts/utils/DaoCreator.sol index 5b975f33..03bb6291 100644 --- a/contracts/utils/DaoCreator.sol +++ b/contracts/utils/DaoCreator.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../controller/Controller.sol"; diff --git a/contracts/utils/Redeemer.sol b/contracts/utils/Redeemer.sol index 48a5f6a2..116c84e4 100644 --- a/contracts/utils/Redeemer.sol +++ b/contracts/utils/Redeemer.sol @@ -1,6 +1,7 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "../schemes/ContributionReward.sol"; +import "../schemes/ContributionRewardExt.sol"; import "@daostack/infra-experimental/contracts/votingMachines/GenesisProtocol.sol"; import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/IERC20.sol"; @@ -19,7 +20,6 @@ contract Redeemer { * @param _contributionReward contributionReward * @param _genesisProtocol genesisProtocol * @param _proposalId the ID of the voting in the voting machine - * @param _avatar address of the controller * @param _beneficiary beneficiary * @return gpRewards array * gpRewards[0] - stakerTokenAmount @@ -41,7 +41,6 @@ contract Redeemer { function redeem(ContributionReward _contributionReward, GenesisProtocol _genesisProtocol, bytes32 _proposalId, - Avatar _avatar, address _beneficiary) external returns(uint[3] memory gpRewards, @@ -53,6 +52,82 @@ contract Redeemer { uint256 crEthReward, uint256 crExternalTokenReward) { + bool callContributionReward; + (gpRewards, gpDaoBountyReward, executed, winningVote, callContributionReward) = + genesisProtocolRedeem(_genesisProtocol, _proposalId, _beneficiary); + if (callContributionReward) { + //redeem from contributionReward only if it executed + if (_contributionReward.getProposalExecutionTime(_proposalId) > 0) { + (crReputationReward, crNativeTokenReward, crEthReward, crExternalTokenReward) = + contributionRewardRedeem(_contributionReward, _proposalId); + } + } + } + + /** + * @dev helper to redeem rewards for a proposal + * It calls execute on the proposal if it is not yet executed. + * It tries to redeem reputation and stake from the GenesisProtocol. + * It tries to redeem proposal rewards from the contribution rewards scheme. + * This function does not emit events. + * A client should listen to GenesisProtocol and ContributionReward redemption events + * to monitor redemption operations. + * @param _contributionRewardExt contributionRewardExt + * @param _genesisProtocol genesisProtocol + * @param _proposalId the ID of the voting in the voting machine + * @param _beneficiary beneficiary + * @return gpRewards array + * gpRewards[0] - stakerTokenAmount + * gpRewards[1] - voterReputationAmount + * gpRewards[2] - proposerReputationAmount + * @return gpDaoBountyReward array + * gpDaoBountyReward[0] - staker dao bounty reward - + * will be zero for the case there is not enough tokens in avatar for the reward. + * gpDaoBountyReward[1] - staker potential dao bounty reward. + * @return executed bool true or false + * @return winningVote + * 1 - executed or closed and the winning vote is YES + * 2 - executed or closed and the winning vote is NO + * @return int256 crReputationReward Reputation - from ContributionReward + * @return int256 crNativeTokenReward NativeTokenReward - from ContributionReward + * @return int256 crEthReward Ether - from ContributionReward + * @return int256 crExternalTokenReward ExternalToken - from ContributionReward + */ + function redeemFromCRExt(ContributionRewardExt _contributionRewardExt, + GenesisProtocol _genesisProtocol, + bytes32 _proposalId, + address _beneficiary) + external + returns(uint[3] memory gpRewards, + uint[2] memory gpDaoBountyReward, + bool executed, + uint256 winningVote, + int256 crReputationReward, + uint256 crNativeTokenReward, + uint256 crEthReward, + uint256 crExternalTokenReward) + { + bool callContributionReward; + (gpRewards, gpDaoBountyReward, executed, winningVote, callContributionReward) = + genesisProtocolRedeem(_genesisProtocol, _proposalId, _beneficiary); + if (callContributionReward) { + //redeem from contributionReward only if it executed + if (_contributionRewardExt.getProposalAcceptedByVotingMachine(_proposalId)) { + (crReputationReward, crNativeTokenReward, crEthReward, crExternalTokenReward) = + contributionRewardExtRedeem(_contributionRewardExt, _proposalId); + } + } + } + + function genesisProtocolRedeem(GenesisProtocol _genesisProtocol, + bytes32 _proposalId, + address _beneficiary) + private + returns(uint[3] memory gpRewards, + uint[2] memory gpDaoBountyReward, + bool executed, + uint256 winningVote, + bool callContributionReward) { GenesisProtocol.ProposalState pState = _genesisProtocol.state(_proposalId); if ((pState == GenesisProtocolLogic.ProposalState.Queued)|| @@ -70,15 +145,11 @@ contract Redeemer { _genesisProtocol.redeemDaoBounty(_proposalId, _beneficiary); } winningVote = _genesisProtocol.winningVote(_proposalId); - //redeem from contributionReward only if it executed - if (_contributionReward.getProposalExecutionTime(_proposalId) > 0) { - (crReputationReward, crNativeTokenReward, crEthReward, crExternalTokenReward) = - contributionRewardRedeem(_contributionReward, _proposalId, _avatar); - } + callContributionReward = true; } } - function contributionRewardRedeem(ContributionReward _contributionReward, bytes32 _proposalId, Avatar _avatar) + function contributionRewardRedeem(ContributionReward _contributionReward, bytes32 _proposalId) private returns (int256 reputation, uint256 nativeToken, uint256 eth, uint256 externalToken) { @@ -90,7 +161,9 @@ contract Redeemer { uint256 externalTokenReward = _contributionReward.getProposalExternalTokenReward(_proposalId); address externalTokenAddress = _contributionReward.getProposalExternalToken(_proposalId); ethReward = periodsToPay.mul(ethReward); - if ((ethReward == 0) || (address(_avatar).balance < ethReward)) { + Avatar avatar = _contributionReward.avatar(); + address vault = address(avatar.vault()); + if ((ethReward == 0) || (vault.balance < ethReward)) { whatToRedeem[2] = false; } else { whatToRedeem[2] = true; @@ -98,11 +171,35 @@ contract Redeemer { periodsToPay = _contributionReward.getPeriodsToPay(_proposalId, 3); externalTokenReward = periodsToPay.mul(externalTokenReward); if ((externalTokenReward == 0) || - (IERC20(externalTokenAddress).balanceOf(address(_avatar)) < externalTokenReward)) { + (IERC20(externalTokenAddress).balanceOf(address(avatar)) < externalTokenReward)) { whatToRedeem[3] = false; } else { whatToRedeem[3] = true; } (reputation, nativeToken, eth, externalToken) = _contributionReward.redeem(_proposalId, whatToRedeem); } + + function contributionRewardExtRedeem(ContributionRewardExt _contributionRewardExt, bytes32 _proposalId) + private + returns (int256 reputation, uint256 nativeToken, uint256 eth, uint256 externalToken) + { + bool[4] memory whatToRedeem; + whatToRedeem[0] = true; //reputation + whatToRedeem[1] = true; //nativeToken + uint256 ethReward = _contributionRewardExt.getProposalEthReward(_proposalId); + uint256 externalTokenReward = _contributionRewardExt.getProposalExternalTokenReward(_proposalId); + address externalTokenAddress = _contributionRewardExt.getProposalExternalToken(_proposalId); + if ((ethReward == 0) || (address((_contributionRewardExt.avatar()).vault()).balance < ethReward)) { + whatToRedeem[2] = false; + } else { + whatToRedeem[2] = true; + } + if ((externalTokenReward == 0) || + (IERC20(externalTokenAddress).balanceOf(address(_contributionRewardExt.avatar())) < externalTokenReward)) { + whatToRedeem[3] = false; + } else { + whatToRedeem[3] = true; + } + (reputation, nativeToken, eth, externalToken) = _contributionRewardExt.redeem(_proposalId, whatToRedeem); + } } diff --git a/contracts/utils/RepAllocation.sol b/contracts/utils/RepAllocation.sol index a2642289..ed38c33e 100644 --- a/contracts/utils/RepAllocation.sol +++ b/contracts/utils/RepAllocation.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@openzeppelin/contracts-ethereum-package/contracts/ownership/Ownable.sol"; import "@openzeppelin/upgrades/contracts/Initializable.sol"; diff --git a/contracts/votingMachines/VotingMachineCallbacks.sol b/contracts/votingMachines/VotingMachineCallbacks.sol index 2eda54d1..c3d63feb 100644 --- a/contracts/votingMachines/VotingMachineCallbacks.sol +++ b/contracts/votingMachines/VotingMachineCallbacks.sol @@ -1,4 +1,4 @@ -pragma solidity ^0.5.13; +pragma solidity ^0.5.16; import "@daostack/infra-experimental/contracts/votingMachines/GenesisProtocol.sol"; import "../controller/Avatar.sol"; diff --git a/package-lock.json b/package-lock.json index 78579e8d..ca5e9f40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@babel/cli": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.7.4.tgz", - "integrity": "sha512-O7mmzaWdm+VabWQmxuM8hqNrWGGihN83KfhPUzp2lAW4kzIMwBxujXkZbD4fMwKMYY9FXTbDvXsJqU+5XHXi4A==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.8.4.tgz", + "integrity": "sha512-XXLgAm6LBbaNxaGhMAznXXaxtCWfuv6PIDJ9Alsy9JYTOh+j2jJz+L/162kkfU1j/pTSxK1xGmlwI4pdIMkoag==", "dev": true, "requires": { "chokidar": "^2.1.8", @@ -22,9 +22,9 @@ }, "dependencies": { "commander": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.0.1.tgz", - "integrity": "sha512-IPF4ouhCP+qdlcmCedhxX4xiGBPyigb8v5NeUp+0LyhwLgxMqyp3S0vl7TAPfS/hiP7FC3caI/PB9lTmP8r1NA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true }, "make-dir": { @@ -46,59 +46,59 @@ } }, "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/highlight": "^7.8.3" } }, "@babel/generator": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", - "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.6.tgz", + "integrity": "sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg==", "dev": true, "requires": { - "@babel/types": "^7.7.4", + "@babel/types": "^7.8.6", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", - "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.4", - "@babel/template": "^7.7.4", - "@babel/types": "^7.7.4" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-get-function-arity": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", - "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", "dev": true, "requires": { - "@babel/types": "^7.7.4" + "@babel/types": "^7.8.3" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", - "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, "requires": { - "@babel/types": "^7.7.4" + "@babel/types": "^7.8.3" } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", "dev": true, "requires": { "chalk": "^2.0.0", @@ -107,34 +107,34 @@ } }, "@babel/parser": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", - "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.6.tgz", + "integrity": "sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g==", "dev": true }, "@babel/template": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", - "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.4", - "@babel/types": "^7.7.4" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" } }, "@babel/traverse": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", - "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.6.tgz", + "integrity": "sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.4", - "@babel/helper-function-name": "^7.7.4", - "@babel/helper-split-export-declaration": "^7.7.4", - "@babel/parser": "^7.7.4", - "@babel/types": "^7.7.4", + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.6", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -158,9 +158,9 @@ } }, "@babel/types": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", - "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.6.tgz", + "integrity": "sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA==", "dev": true, "requires": { "esutils": "^2.0.2", @@ -176,20 +176,72 @@ "@openzeppelin/contracts-ethereum-package": "2.3.0", "@openzeppelin/upgrades": "2.5.3", "ethereumjs-abi": "^0.6.5" + }, + "dependencies": { + "@openzeppelin/contracts-ethereum-package": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-ethereum-package/-/contracts-ethereum-package-2.3.0.tgz", + "integrity": "sha512-voAH5uPmfZ0bpMHV6JgXoaWqkp0YIMmAino04nvJWso4S9di/rrWr8nnJB+b5bwQEz06u1rN9O3nXM9vIiHBlw==" + }, + "@openzeppelin/upgrades": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades/-/upgrades-2.5.3.tgz", + "integrity": "sha512-3tF3CCcfXb1OsCVjlv7v694pGdO+ssJddgDYI+K6AwUdAmxafaHSaftCFQ5BRmdpHKCxzAYrc2SSLHZpLpXl2g==", + "requires": { + "@types/cbor": "^2.0.0", + "@types/web3": "^1.0.14", + "axios": "^0.18.0", + "bignumber.js": "^7.2.0", + "cbor": "^4.1.5", + "chalk": "^2.4.1", + "ethers": "^4.0.20", + "glob": "^7.1.3", + "lodash.concat": "^4.5.0", + "lodash.difference": "^4.5.0", + "lodash.every": "^4.6.0", + "lodash.findlast": "^4.6.0", + "lodash.flatten": "^4.4.0", + "lodash.includes": "^4.3.0", + "lodash.invertby": "^4.7.0", + "lodash.isempty": "^4.4.0", + "lodash.isequal": "^4.5.0", + "lodash.isstring": "^4.0.1", + "lodash.keys": "^4.2.0", + "lodash.map": "^4.6.0", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.pickby": "^4.6.0", + "lodash.random": "^3.2.0", + "lodash.reverse": "^4.0.1", + "lodash.some": "^4.6.0", + "lodash.uniq": "^4.5.0", + "lodash.values": "^4.3.0", + "lodash.without": "^4.4.0", + "semver": "^5.5.1", + "spinnies": "^0.4.2", + "truffle-flattener": "^1.4.0", + "web3": "1.2.1", + "web3-utils": "1.2.0" + } + }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + } } }, "@openzeppelin/contracts-ethereum-package": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-ethereum-package/-/contracts-ethereum-package-2.3.0.tgz", - "integrity": "sha512-voAH5uPmfZ0bpMHV6JgXoaWqkp0YIMmAino04nvJWso4S9di/rrWr8nnJB+b5bwQEz06u1rN9O3nXM9vIiHBlw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-ethereum-package/-/contracts-ethereum-package-2.4.0.tgz", + "integrity": "sha512-GC1aOgTnuNnlhdYOCKFizLCQRgYlbImWi+aJ9Lw4Yw4BSLHzfPg+XV0tgn9l+KnFAzgoUEg2aD2wmaHZBjEnSw==" }, "@openzeppelin/upgrades": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades/-/upgrades-2.5.3.tgz", - "integrity": "sha512-3tF3CCcfXb1OsCVjlv7v694pGdO+ssJddgDYI+K6AwUdAmxafaHSaftCFQ5BRmdpHKCxzAYrc2SSLHZpLpXl2g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades/-/upgrades-2.7.1.tgz", + "integrity": "sha512-oTYCgfC9+gHqqKQRn6Q8YGzXu5J1ioeUfVTHTZQG0opzmQplVA5zkudUvgkgqzr219vfEW6kKJpFJhXqBgkQIw==", "requires": { "@types/cbor": "^2.0.0", - "@types/web3": "^1.0.14", "axios": "^0.18.0", "bignumber.js": "^7.2.0", "cbor": "^4.1.5", @@ -220,14 +272,358 @@ "semver": "^5.5.1", "spinnies": "^0.4.2", "truffle-flattener": "^1.4.0", - "web3": "1.2.1", - "web3-utils": "1.2.0" + "web3": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" }, "dependencies": { + "@types/node": { + "version": "12.12.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.29.tgz", + "integrity": "sha512-yo8Qz0ygADGFptISDj3pOC9wXfln/5pQaN/ysDIzOaAWXt73cNHmtEC8zSO2Y+kse/txmwIAJzkYZ5fooaS5DQ==" + }, "bignumber.js": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, + "eth-lib": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.7.tgz", + "integrity": "sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco=", + "requires": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "setimmediate": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", + "integrity": "sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48=" + }, + "uuid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", + "integrity": "sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w=" + }, + "web3": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.2.2.tgz", + "integrity": "sha512-/ChbmB6qZpfGx6eNpczt5YSUBHEA5V2+iUCbn85EVb3Zv6FVxrOo5Tv7Lw0gE2tW7EEjASbCyp3mZeiZaCCngg==", + "requires": { + "@types/node": "^12.6.1", + "web3-bzz": "1.2.2", + "web3-core": "1.2.2", + "web3-eth": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-shh": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-bzz": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.2.2.tgz", + "integrity": "sha512-b1O2ObsqUN1lJxmFSjvnEC4TsaCbmh7Owj3IAIWTKqL9qhVgx7Qsu5O9cD13pBiSPNZJ68uJPaKq380QB4NWeA==", + "requires": { + "@types/node": "^10.12.18", + "got": "9.6.0", + "swarm-js": "0.1.39", + "underscore": "1.9.1" + }, + "dependencies": { + "@types/node": { + "version": "10.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", + "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" + } + } + }, + "web3-core": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.2.2.tgz", + "integrity": "sha512-miHAX3qUgxV+KYfaOY93Hlc3kLW2j5fH8FJy6kSxAv+d4d5aH0wwrU2IIoJylQdT+FeenQ38sgsCnFu9iZ1hCQ==", + "requires": { + "@types/bn.js": "^4.11.4", + "@types/node": "^12.6.1", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-requestmanager": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-helpers": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.2.2.tgz", + "integrity": "sha512-HJrRsIGgZa1jGUIhvGz4S5Yh6wtOIo/TMIsSLe+Xay+KVnbseJpPprDI5W3s7H2ODhMQTbogmmUFquZweW2ImQ==", + "requires": { + "underscore": "1.9.1", + "web3-eth-iban": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-method": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.2.2.tgz", + "integrity": "sha512-szR4fDSBxNHaF1DFqE+j6sFR/afv9Aa36OW93saHZnrh+iXSrYeUUDfugeNcRlugEKeUCkd4CZylfgbK2SKYJA==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-core-promievent": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.2.2.tgz", + "integrity": "sha512-tKvYeT8bkUfKABcQswK6/X79blKTKYGk949urZKcLvLDEaWrM3uuzDwdQT3BNKzQ3vIvTggFPX9BwYh0F1WwqQ==", + "requires": { + "any-promise": "1.3.0", + "eventemitter3": "3.1.2" + } + }, + "web3-core-requestmanager": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.2.2.tgz", + "integrity": "sha512-a+gSbiBRHtHvkp78U2bsntMGYGF2eCb6219aMufuZWeAZGXJ63Wc2321PCbA8hF9cQrZI4EoZ4kVLRI4OF15Hw==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "web3-providers-http": "1.2.2", + "web3-providers-ipc": "1.2.2", + "web3-providers-ws": "1.2.2" + } + }, + "web3-core-subscriptions": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.2.2.tgz", + "integrity": "sha512-QbTgigNuT4eicAWWr7ahVpJyM8GbICsR1Ys9mJqzBEwpqS+RXTRVSkwZ2IsxO+iqv6liMNwGregbJLq4urMFcQ==", + "requires": { + "eventemitter3": "3.1.2", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + } + }, + "web3-eth": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.2.2.tgz", + "integrity": "sha512-UXpC74mBQvZzd4b+baD4Ocp7g+BlwxhBHumy9seyE/LMIcMlePXwCKzxve9yReNpjaU16Mmyya6ZYlyiKKV8UA==", + "requires": { + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-accounts": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-eth-ens": "1.2.2", + "web3-eth-iban": "1.2.2", + "web3-eth-personal": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-abi": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.2.2.tgz", + "integrity": "sha512-Yn/ZMgoOLxhTVxIYtPJ0eS6pnAnkTAaJgUJh1JhZS4ekzgswMfEYXOwpMaD5eiqPJLpuxmZFnXnBZlnQ1JMXsw==", + "requires": { + "ethers": "4.0.0-beta.3", + "underscore": "1.9.1", + "web3-utils": "1.2.2" + }, + "dependencies": { + "@types/node": { + "version": "10.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", + "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" + }, + "elliptic": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.3.3.tgz", + "integrity": "sha1-VILZZG1UvLif19mU/J4ulWiHbj8=", + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, + "ethers": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.0-beta.3.tgz", + "integrity": "sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog==", + "requires": { + "@types/node": "^10.3.2", + "aes-js": "3.0.0", + "bn.js": "^4.4.0", + "elliptic": "6.3.3", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.3", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + } + } + }, + "web3-eth-accounts": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.2.2.tgz", + "integrity": "sha512-KzHOEyXOEZ13ZOkWN3skZKqSo5f4Z1ogPFNn9uZbKCz+kSp+gCAEKxyfbOsB/JMAp5h7o7pb6eYsPCUBJmFFiA==", + "requires": { + "any-promise": "1.3.0", + "crypto-browserify": "3.12.0", + "eth-lib": "0.2.7", + "ethereumjs-common": "^1.3.2", + "ethereumjs-tx": "^2.1.1", + "scrypt-shim": "github:web3-js/scrypt-shim#be5e616323a8b5e568788bf94d03c1b8410eac54", + "underscore": "1.9.1", + "uuid": "3.3.2", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "web3-eth-contract": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.2.2.tgz", + "integrity": "sha512-EKT2yVFws3FEdotDQoNsXTYL798+ogJqR2//CaGwx3p0/RvQIgfzEwp8nbgA6dMxCsn9KOQi7OtklzpnJMkjtA==", + "requires": { + "@types/bn.js": "^4.11.4", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-ens": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.2.2.tgz", + "integrity": "sha512-CFjkr2HnuyMoMFBoNUWojyguD4Ef+NkyovcnUc/iAb9GP4LHohKrODG4pl76R5u61TkJGobC2ij6TyibtsyVYg==", + "requires": { + "eth-ens-namehash": "2.0.8", + "underscore": "1.9.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-promievent": "1.2.2", + "web3-eth-abi": "1.2.2", + "web3-eth-contract": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-eth-iban": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.2.2.tgz", + "integrity": "sha512-gxKXBoUhaTFHr0vJB/5sd4i8ejF/7gIsbM/VvemHT3tF5smnmY6hcwSMmn7sl5Gs+83XVb/BngnnGkf+I/rsrQ==", + "requires": { + "bn.js": "4.11.8", + "web3-utils": "1.2.2" + } + }, + "web3-eth-personal": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.2.2.tgz", + "integrity": "sha512-4w+GLvTlFqW3+q4xDUXvCEMU7kRZ+xm/iJC8gm1Li1nXxwwFbs+Y+KBK6ZYtoN1qqAnHR+plYpIoVo27ixI5Rg==", + "requires": { + "@types/node": "^12.6.1", + "web3-core": "1.2.2", + "web3-core-helpers": "1.2.2", + "web3-core-method": "1.2.2", + "web3-net": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-net": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.2.2.tgz", + "integrity": "sha512-K07j2DXq0x4UOJgae65rWZKraOznhk8v5EGSTdFqASTx7vWE/m+NqBijBYGEsQY1lSMlVaAY9UEQlcXK5HzXTw==", + "requires": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-utils": "1.2.2" + } + }, + "web3-providers-http": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.2.2.tgz", + "integrity": "sha512-BNZ7Hguy3eBszsarH5gqr9SIZNvqk9eKwqwmGH1LQS1FL3NdoOn7tgPPdddrXec4fL94CwgNk4rCU+OjjZRNDg==", + "requires": { + "web3-core-helpers": "1.2.2", + "xhr2-cookies": "1.1.0" + } + }, + "web3-providers-ipc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.2.2.tgz", + "integrity": "sha512-t97w3zi5Kn/LEWGA6D9qxoO0LBOG+lK2FjlEdCwDQatffB/+vYrzZ/CLYVQSoyFZAlsDoBasVoYSWZK1n39aHA==", + "requires": { + "oboe": "2.1.4", + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2" + } + }, + "web3-providers-ws": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.2.2.tgz", + "integrity": "sha512-Wb1mrWTGMTXOpJkL0yGvL/WYLt8fUIXx8k/l52QB2IiKzvyd42dTWn4+j8IKXGSYYzOm7NMqv6nhA5VDk12VfA==", + "requires": { + "underscore": "1.9.1", + "web3-core-helpers": "1.2.2", + "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" + } + }, + "web3-shh": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.2.2.tgz", + "integrity": "sha512-og258NPhlBn8yYrDWjoWBBb6zo1OlBgoWGT+LL5/LPqRbjPe09hlOYHgscAAr9zZGtohTOty7RrxYw6Z6oDWCg==", + "requires": { + "web3-core": "1.2.2", + "web3-core-method": "1.2.2", + "web3-core-subscriptions": "1.2.2", + "web3-net": "1.2.2" + } + }, + "web3-utils": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.2.2.tgz", + "integrity": "sha512-joF+s3243TY5cL7Z7y4h1JsJpUCf/kmFmj+eJar7Y2yNIGVcW961VyrAms75tjUysSuHaUQ3eQXjBEUJueT52A==", + "requires": { + "bn.js": "4.11.8", + "eth-lib": "0.2.7", + "ethereum-bloom-filters": "^1.0.6", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "underscore": "1.9.1", + "utf8": "3.0.0" + } } } }, @@ -358,9 +754,9 @@ } }, "@types/bn.js": { - "version": "4.11.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.5.tgz", - "integrity": "sha512-AEAZcIZga0JgVMHNtl1CprA/hXX7/wPt79AgR4XqaDt7jyj3QWYw6LPoOiznPtugDmlubUnAahMs2PFxGcQrng==", + "version": "4.11.6", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", + "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", "requires": { "@types/node": "*" } @@ -374,9 +770,9 @@ } }, "@types/node": { - "version": "12.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", - "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==" + "version": "13.7.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.7.tgz", + "integrity": "sha512-Uo4chgKbnPNlxQwoFmYIwctkQVkMMmsAoGGU4JKwLuvBefF0pCq4FybNSnfkfRCpC7ZW7kttcC/TrRtAJsvGtg==" }, "@types/web3": { "version": "1.2.2", @@ -427,9 +823,9 @@ } }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, "aes-js": { @@ -438,11 +834,11 @@ "integrity": "sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0=" }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" @@ -581,13 +977,14 @@ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "array-includes": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", - "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", + "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.7.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "is-string": "^1.0.5" } }, "array-unique": { @@ -596,6 +993,16 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -691,9 +1098,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", - "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "axios": { "version": "0.18.1", @@ -799,15 +1206,15 @@ } }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", "eslint-visitor-keys": "^1.0.0", "resolve": "^1.12.0" } @@ -1271,6 +1678,17 @@ "lodash": "^4.17.4", "mkdirp": "^0.5.1", "source-map-support": "^0.4.15" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } } }, "babel-runtime": { @@ -1416,9 +1834,9 @@ } }, "base-x": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.7.tgz", - "integrity": "sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.8.tgz", + "integrity": "sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==", "requires": { "safe-buffer": "^5.0.1" } @@ -1877,9 +2295,9 @@ } }, "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" }, "cipher-base": { "version": "1.0.4", @@ -1914,9 +2332,9 @@ } }, "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -2197,9 +2615,9 @@ "dev": true }, "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", "dev": true }, "core-util-is": { @@ -2291,9 +2709,9 @@ } }, "cron": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/cron/-/cron-1.7.2.tgz", - "integrity": "sha512-+SaJ2OfeRvfQqwXQ2kgr0Y5pzBR/lijf5OpnnaruwWnmI799JfWr2jN2ItOV9s3A/+TFOt6mxvKzQq5F0Jp6VQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/cron/-/cron-1.8.2.tgz", + "integrity": "sha512-Gk2c4y6xKEO8FSAUTklqtfSr7oTq0CiPQeLBG5Fl0qoXpZyMcj1SG59YL+hqq04bu6/IuEA7lMkYDAplQNKkyg==", "dev": true, "requires": { "moment-timezone": "^0.5.x" @@ -2338,9 +2756,9 @@ } }, "crypto-js": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz", - "integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz", + "integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q==" }, "d": { "version": "1.0.1", @@ -2467,9 +2885,24 @@ } }, "deep-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "dependencies": { + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + } + } }, "deep-is": { "version": "0.1.3", @@ -2496,9 +2929,9 @@ } }, "defer-to-connect": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.0.tgz", - "integrity": "sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" }, "deferred-leveldown": { "version": "1.2.2", @@ -2643,6 +3076,14 @@ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" }, + "dotignore": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz", + "integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==", + "requires": { + "minimatch": "^3.0.4" + } + }, "drbg.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/drbg.js/-/drbg.js-1.0.1.tgz", @@ -2739,27 +3180,23 @@ } }, "es-abstract": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.2.tgz", - "integrity": "sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA==", + "version": "1.17.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.4.tgz", + "integrity": "sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ==", "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" }, "dependencies": { - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -2894,6 +3331,15 @@ "ms": "^2.1.1" } }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -2924,48 +3370,43 @@ "dev": true }, "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", + "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", "dev": true, "requires": { "debug": "^2.6.9", - "resolve": "^1.5.0" + "resolve": "^1.13.1" } }, "eslint-module-utils": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", - "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", + "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", "dev": true, "requires": { - "debug": "^2.6.8", + "debug": "^2.6.9", "pkg-dir": "^2.0.0" } }, - "eslint-plugin-eslint-plugin": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-plugin/-/eslint-plugin-eslint-plugin-2.1.0.tgz", - "integrity": "sha512-kT3A/ZJftt28gbl/Cv04qezb/NQ1dwYIbi8lyf806XMxkus7DvOVCLIfTXMrorp322Pnoez7+zabXH29tADIDg==", - "dev": true - }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", "dev": true, "requires": { "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", + "eslint-module-utils": "^2.4.1", "has": "^1.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" + "resolve": "^1.12.0" }, "dependencies": { "doctrine": { @@ -3061,21 +3502,21 @@ "dev": true }, "eslint-plugin-react": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.17.0.tgz", - "integrity": "sha512-ODB7yg6lxhBVMeiH1c7E95FLD4E/TwmFjltiU+ethv7KPdCwgiFuOZg9zNRHyufStTDLl/dEFqI2Q1VPmCd78A==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.18.3.tgz", + "integrity": "sha512-Bt56LNHAQCoou88s8ViKRjMB2+36XRejCQ1VoLj716KI1MoE99HpTVvIThJ0rvFmG4E4Gsq+UgToEjn+j044Bg==", "dev": true, "requires": { - "array-includes": "^3.0.3", + "array-includes": "^3.1.1", "doctrine": "^2.1.0", - "eslint-plugin-eslint-plugin": "^2.1.0", "has": "^1.0.3", "jsx-ast-utils": "^2.2.3", - "object.entries": "^1.1.0", - "object.fromentries": "^2.0.1", - "object.values": "^1.1.0", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.13.1" + "resolve": "^1.14.2", + "string.prototype.matchall": "^4.0.2" }, "dependencies": { "doctrine": { @@ -3138,9 +3579,9 @@ "dev": true }, "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", + "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", "dev": true, "requires": { "estraverse": "^4.0.0" @@ -3194,6 +3635,21 @@ "xhr-request-promise": "^0.1.2" } }, + "ethereum-bloom-filters": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.6.tgz", + "integrity": "sha512-dE9CGNzgOOsdh7msZirvv8qjHtnHpvBlKe2647kM8v+yeF71IRso55jpojemvHV+jMjr48irPWxMRaHuOWzAFA==", + "requires": { + "js-sha3": "^0.8.0" + }, + "dependencies": { + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + } + } + }, "ethereum-common": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", @@ -3257,6 +3713,22 @@ "merkle-patricia-tree": "^2.1.2" }, "dependencies": { + "ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "requires": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + }, + "dependencies": { + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + } + } + }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", @@ -3285,49 +3757,17 @@ } }, "ethereumjs-common": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.4.0.tgz", - "integrity": "sha512-ser2SAplX/YI5W2AnzU8wmSjKRy4KQd4uxInJ36BzjS3m18E/B9QedPUIresZN1CSEQb/RgNQ2gN7C/XbpTafA==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz", + "integrity": "sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ==" }, "ethereumjs-tx": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", - "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz", + "integrity": "sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw==", "requires": { - "ethereum-common": "^0.0.18", - "ethereumjs-util": "^5.0.0" - }, - "dependencies": { - "ethereum-common": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", - "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" - }, - "ethereumjs-util": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", - "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", - "requires": { - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "ethjs-util": "^0.1.3", - "keccak": "^1.0.2", - "rlp": "^2.0.0", - "safe-buffer": "^5.1.1", - "secp256k1": "^3.0.1" - } - }, - "keccak": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", - "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", - "requires": { - "bindings": "^1.2.1", - "inherits": "^2.0.3", - "nan": "^2.2.1", - "safe-buffer": "^5.1.0" - } - } + "ethereumjs-common": "^1.5.0", + "ethereumjs-util": "^6.0.0" } }, "ethereumjs-util": { @@ -3363,12 +3803,12 @@ }, "dependencies": { "ethereumjs-block": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.1.tgz", - "integrity": "sha512-ze8I1844m5oKZL7hiHuezRcPzqdi4Iv0ssqQyuRaJ9Je0/YCYfXobJHvNLnex2ETgs5JypicdtLYrCNWdgcLvg==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz", + "integrity": "sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg==", "requires": { "async": "^2.0.1", - "ethereumjs-common": "^1.1.0", + "ethereumjs-common": "^1.5.0", "ethereumjs-tx": "^2.1.1", "ethereumjs-util": "^5.0.0", "merkle-patricia-tree": "^2.1.2" @@ -3390,15 +3830,6 @@ } } }, - "ethereumjs-tx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-2.1.1.tgz", - "integrity": "sha512-QtVriNqowCFA19X9BCRPMgdVNJ0/gMBS91TQb1DfrhsbR748g4STwxZptFAwfqehMyrF8rDwB23w87PQwru0wA==", - "requires": { - "ethereumjs-common": "^1.3.1", - "ethereumjs-util": "^6.0.0" - } - }, "keccak": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", @@ -3413,8 +3844,8 @@ } }, "ethereumjs-wallet": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.5.16.tgz", "integrity": "sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w==", "requires": { "aes-js": "^3.1.1", @@ -3436,9 +3867,9 @@ } }, "ethers": { - "version": "4.0.40", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.40.tgz", - "integrity": "sha512-MC9BtV7Hpq4dgFONEfanx9aU9GhhoWU270F+/wegHZXA7FR+2KXFdt36YIQYLmVY5ykUWswDxd+f9EVkIa7JOA==", + "version": "4.0.45", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.45.tgz", + "integrity": "sha512-N/Wmc6Mw4pQO+Sss1HnKDCSS6KSCx0luoBMiPNq+1GbOaO3YaZOyplBEhj+NEoYsizZYODtkITg2oecPeNnidQ==", "requires": { "aes-js": "3.0.0", "bn.js": "^4.4.0", @@ -3732,9 +4163,9 @@ } }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, "fast-diff": { "version": "1.2.0", @@ -3743,9 +4174,9 @@ "dev": true }, "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-levenshtein": { "version": "2.0.6", @@ -3969,14 +4400,15 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", + "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", "dev": true, "optional": true, "requires": { + "bindings": "^1.5.0", "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" + "node-pre-gyp": "*" }, "dependencies": { "abbrev": { @@ -3988,8 +4420,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -4010,21 +4441,19 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "chownr": { - "version": "1.1.1", + "version": "1.1.3", "bundled": true, "dev": true, "optional": true @@ -4032,20 +4461,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -4054,7 +4480,7 @@ "optional": true }, "debug": { - "version": "4.1.1", + "version": "3.2.6", "bundled": true, "dev": true, "optional": true, @@ -4081,12 +4507,12 @@ "optional": true }, "fs-minipass": { - "version": "1.2.5", + "version": "1.2.7", "bundled": true, "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs.realpath": { @@ -4112,7 +4538,7 @@ } }, "glob": { - "version": "7.1.3", + "version": "7.1.6", "bundled": true, "dev": true, "optional": true, @@ -4141,7 +4567,7 @@ } }, "ignore-walk": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "dev": true, "optional": true, @@ -4160,10 +4586,9 @@ } }, "inherits": { - "version": "2.0.3", + "version": "2.0.4", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -4175,7 +4600,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4190,7 +4614,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4198,56 +4621,53 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { - "version": "2.3.5", + "version": "2.9.0", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.2.1", + "version": "1.3.3", "bundled": true, "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mkdirp": { "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { - "version": "2.1.1", + "version": "2.1.2", "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.3.0", + "version": "2.4.0", "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "^4.1.0", + "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.12.0", + "version": "0.14.0", "bundled": true, "dev": true, "optional": true, @@ -4261,7 +4681,7 @@ "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", - "tar": "^4" + "tar": "^4.4.2" } }, "nopt": { @@ -4275,13 +4695,22 @@ } }, "npm-bundled": { - "version": "1.0.6", + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.4.1", + "version": "1.4.7", "bundled": true, "dev": true, "optional": true, @@ -4305,8 +4734,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4318,7 +4746,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -4352,7 +4779,7 @@ "optional": true }, "process-nextick-args": { - "version": "2.0.0", + "version": "2.0.1", "bundled": true, "dev": true, "optional": true @@ -4393,7 +4820,7 @@ } }, "rimraf": { - "version": "2.6.3", + "version": "2.7.1", "bundled": true, "dev": true, "optional": true, @@ -4404,8 +4831,7 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -4420,7 +4846,7 @@ "optional": true }, "semver": { - "version": "5.7.0", + "version": "5.7.1", "bundled": true, "dev": true, "optional": true @@ -4441,7 +4867,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4461,7 +4886,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4473,18 +4897,18 @@ "optional": true }, "tar": { - "version": "4.4.8", + "version": "4.4.13", "bundled": true, "dev": true, "optional": true, "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "yallist": "^3.0.3" } }, "util-deprecate": { @@ -4505,14 +4929,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { - "version": "3.0.3", + "version": "3.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -4527,9 +4949,9 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "ganache-cli": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.7.0.tgz", - "integrity": "sha512-9CZsClo9hl5MxGL7hkk14mie89Q94P0idh92jcV7LmppTYTCG7SHatuwcfqN7emFHArMt3fneN4QbH2do2N6Ow==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.1.tgz", + "integrity": "sha512-VPBumkNUZzXDRQwVOby5YyQpd5t1clkr06xMgB28lZdEIn5ht1GMwUskOTFOAxdkQ4J12IWP0gdeacVRGowqbA==", "dev": true, "requires": { "ethereumjs-util": "6.1.0", @@ -5470,14 +5892,14 @@ } }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==" + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-Z2EICWNJou7Tr9Bd2M2UqDJq3A9F2ePG9w3lIpjoyuSyXFP9QbniJVu3XQYytuw5ebmG7dXSXO9PgAjJG8DDKA==" }, "http-errors": { "version": "1.7.2", @@ -5672,6 +6094,17 @@ } } }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + } + }, "interpret": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", @@ -5693,9 +6126,9 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, "is": { "version": "3.3.0", @@ -5729,6 +6162,11 @@ } } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -5749,9 +6187,9 @@ "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" }, "is-data-descriptor": { "version": "0.1.4", @@ -5780,9 +6218,9 @@ } }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-descriptor": { "version": "0.1.6", @@ -5840,13 +6278,10 @@ "dev": true }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -5932,11 +6367,11 @@ "dev": true }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", "requires": { - "has": "^1.0.1" + "has": "^1.0.3" } }, "is-retry-allowed": { @@ -5949,6 +6384,12 @@ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -6156,9 +6597,9 @@ } }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, "klaw": { @@ -6674,16 +7115,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "requires": { - "mime-db": "1.42.0" + "mime-db": "1.43.0" } }, "mimic-fn": { @@ -6766,12 +7207,9 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "requires": { - "minimist": "0.0.8" - } + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.3.tgz", + "integrity": "sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g==" }, "mkdirp-promise": { "version": "5.0.1", @@ -6829,6 +7267,15 @@ "path-is-absolute": "^1.0.0" } }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -6841,9 +7288,9 @@ } }, "mock-fs": { - "version": "4.10.4", - "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.10.4.tgz", - "integrity": "sha512-gDfZDLaPIvtOusbusLinfx6YSe2YpQsDT8qdP41P47dQ/NQggtkHukz7hwqgt8QvMBmAv+Z6DGmXPyb5BWX2nQ==" + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.11.0.tgz", + "integrity": "sha512-Yp4o3/ZA15wsXqJTT+R+9w2AYIkD1i80Lds47wDbuUhOvQvm+O2EfjFZSz0pMgZZSPHRhGxgcd2+GL4+jZMtdw==" }, "moment": { "version": "2.24.0", @@ -6852,9 +7299,9 @@ "dev": true }, "moment-timezone": { - "version": "0.5.27", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", - "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", + "version": "0.5.28", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz", + "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==", "dev": true, "requires": { "moment": ">= 2.9.0" @@ -6907,9 +7354,9 @@ "dev": true }, "needle": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", - "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.2.tgz", + "integrity": "sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w==", "dev": true, "requires": { "debug": "^3.2.6", @@ -7073,9 +7520,14 @@ } }, "object-inspect": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", - "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + }, + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==" }, "object-keys": { "version": "0.4.0", @@ -7095,7 +7547,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -7106,31 +7557,30 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" } } }, "object.entries": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", - "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } }, "object.fromentries": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.1.tgz", - "integrity": "sha512-PUQv8Hbg3j2QX0IQYv3iAGCbGcu4yY4KQ92/dhA4sFSixBmSmp13UpDLs6jGK8rBtbmhNNIK99LD2k293jpiGA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.15.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -7145,13 +7595,13 @@ } }, "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", "dev": true, "requires": { "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "es-abstract": "^1.17.0-next.1", "function-bind": "^1.1.1", "has": "^1.0.3" } @@ -7493,6 +7943,15 @@ "ms": "^2.1.1" } }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7727,12 +8186,12 @@ } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, "prr": { @@ -7747,9 +8206,9 @@ "dev": true }, "psl": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.5.0.tgz", - "integrity": "sha512-4vqUjKi2huMu1OJiLhi3jN6jeeKvMZdI1tYgi/njW5zV52jNLgSAZSdN16m9bJFe61/cT8ulmw4qFitV9QRsEA==" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", + "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==" }, "public-encrypt": { "version": "4.0.3", @@ -7958,9 +8417,9 @@ } }, "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==", + "version": "16.13.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.0.tgz", + "integrity": "sha512-GFMtL0vHkiBv9HluwNZTggSn/sCyEt9n02aM0dSAjGGyqyNlAyftYm4phPxdvCigG15JreC5biwxCgTAJZ7yAA==", "dev": true }, "read": { @@ -8011,9 +8470,9 @@ } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -8084,6 +8543,15 @@ "safe-regex": "^1.1.0" } }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -8152,9 +8620,9 @@ } }, "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -8163,7 +8631,7 @@ "extend": "~3.0.2", "forever-agent": "~0.6.1", "form-data": "~2.3.2", - "har-validator": "~5.1.0", + "har-validator": "~5.1.3", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -8173,7 +8641,7 @@ "performance-now": "^2.1.0", "qs": "~6.5.2", "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", + "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" }, @@ -8201,9 +8669,9 @@ "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" }, "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "requires": { "path-parse": "^1.0.6" } @@ -8286,9 +8754,9 @@ } }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", + "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", "dev": true, "requires": { "is-promise": "^2.1.0" @@ -8310,9 +8778,9 @@ "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" }, "rxjs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", - "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -8357,6 +8825,21 @@ "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz", "integrity": "sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q=" }, + "scrypt-shim": { + "version": "github:web3-js/scrypt-shim#be5e616323a8b5e568788bf94d03c1b8410eac54", + "from": "github:web3-js/scrypt-shim", + "requires": { + "scryptsy": "^2.1.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, "scrypt.js": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/scrypt.js/-/scrypt.js-0.3.0.tgz", @@ -8382,16 +8865,16 @@ "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==" }, "secp256k1": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.7.1.tgz", - "integrity": "sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.8.0.tgz", + "integrity": "sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw==", "requires": { "bindings": "^1.5.0", "bip66": "^1.1.5", "bn.js": "^4.11.8", "create-hash": "^1.2.0", "drbg.js": "^1.0.1", - "elliptic": "^6.4.1", + "elliptic": "^6.5.2", "nan": "^2.14.0", "safe-buffer": "^5.1.2" } @@ -8543,6 +9026,16 @@ "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", "dev": true }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -8790,12 +9283,12 @@ "dev": 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==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -8942,29 +9435,43 @@ } } }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + } + }, "string.prototype.trim": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", - "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.0", - "function-bind": "^1.0.2" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" } }, "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", + "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" } }, "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", + "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", "requires": { "define-properties": "^1.1.3", "function-bind": "^1.1.1" @@ -9128,22 +9635,24 @@ } }, "tape": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", - "integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.0.tgz", + "integrity": "sha512-J/hvA+GJnuWJ0Sj8Z0dmu3JgMNU+MmusvkCT7+SN4/2TklW18FNCp/UuHIEhPZwHfy4sXfKYgC7kypKg4umbOw==", "requires": { - "deep-equal": "~1.0.1", + "deep-equal": "~1.1.1", "defined": "~1.0.0", + "dotignore": "~0.1.2", "for-each": "~0.3.3", "function-bind": "~1.1.1", - "glob": "~7.1.4", + "glob": "~7.1.6", "has": "~1.0.3", "inherits": "~2.0.4", + "is-regex": "~1.0.5", "minimist": "~1.2.0", - "object-inspect": "~1.6.0", - "resolve": "~1.11.1", + "object-inspect": "~1.7.0", + "resolve": "~1.14.2", "resumer": "~0.0.0", - "string.prototype.trim": "~1.1.2", + "string.prototype.trim": "~1.2.1", "through": "~2.3.8" }, "dependencies": { @@ -9153,9 +9662,9 @@ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "resolve": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", - "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", + "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", "requires": { "path-parse": "^1.0.6" } @@ -9174,6 +9683,16 @@ "mkdirp": "^0.5.0", "safe-buffer": "^5.1.2", "yallist": "^3.0.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + } } }, "tar-stream": { @@ -9291,19 +9810,12 @@ "dev": true }, "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - } + "psl": "^1.1.28", + "punycode": "^2.1.1" } }, "trim-right": { @@ -9333,6 +9845,16 @@ "mkdirp": "^0.5.1", "solidity-parser-antlr": "^0.4.11", "tsort": "0.0.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + } } }, "truffle-hdwallet-provider": { @@ -9370,9 +9892,9 @@ } }, "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", "dev": true }, "tsort": { @@ -9637,9 +10159,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, "v8-compile-cache": { "version": "1.1.2", @@ -9962,9 +10484,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz", - "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==" + "version": "10.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.17.tgz", + "integrity": "sha512-gpNnRnZP3VWzzj5k3qrpRC6Rk3H/uclhAVo1aIvwzK5p5cOrs9yEyQ8H/HBsBY0u5rrWxXEiVPQ0dEB6pkjE8Q==" }, "elliptic": { "version": "6.3.3", @@ -10325,6 +10847,20 @@ "version": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9", "from": "git+https://github.com/debris/bignumber.js.git#master" }, + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-tx": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz", + "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==", + "requires": { + "ethereum-common": "^0.0.18", + "ethereumjs-util": "^5.0.0" + } + }, "ethereumjs-util": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", @@ -10360,7 +10896,7 @@ "resolved": "https://registry.npmjs.org/web3/-/web3-0.16.0.tgz", "integrity": "sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk=", "requires": { - "bignumber.js": "git+https://github.com/debris/bignumber.js.git#master", + "bignumber.js": "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9", "crypto-js": "^3.1.4", "utf8": "^2.1.1", "xmlhttprequest": "*" @@ -10394,7 +10930,7 @@ "requires": { "underscore": "1.9.1", "web3-core-helpers": "1.2.1", - "websocket": "github:web3-js/WebSocket-Node#polyfill/globalThis" + "websocket": "github:web3-js/WebSocket-Node#905deb4812572b344f5801f8c9ce8bb02799d82e" } }, "web3-shh": { @@ -10541,6 +11077,17 @@ "dev": true, "requires": { "mkdirp": "^0.5.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } } }, "ws": { diff --git a/package.json b/package.json index e0a180c3..1ce9f536 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "tsconfig.json" ], "config": { - "gasLimit": "6500000" + "gasLimit": "7100000" }, "scripts": { "test": "cross-conf-env run-with-ganache --ganache-cmd 'npm run ganache' 'npm run truffle compile && npm run truffle migrate && npm run truffle test'", @@ -76,8 +76,8 @@ "homepage": "https://daostack.io", "dependencies": { "@daostack/infra-experimental": "0.0.1-rc.16", - "@openzeppelin/contracts-ethereum-package": "2.3.0", - "@openzeppelin/upgrades": "2.5.3", + "@openzeppelin/contracts-ethereum-package": "2.4.0", + "@openzeppelin/upgrades": "2.7.1", "math": "0.0.3", "solidity-bytes-utils": "0.0.8", "truffle-flattener": "^1.4.2" diff --git a/test/avatar.js b/test/avatar.js index 7b205d5b..90df196a 100644 --- a/test/avatar.js +++ b/test/avatar.js @@ -14,20 +14,20 @@ const setup = async function (accounts) { contract('Avatar', accounts => { - it("genericCall no owner", async () => { - avatar = await setup(accounts); - let actionMock = await ActionMock.new(); - var scheme = await SchemeMock.new(); - let a = 7; - let b = actionMock.address; - let c = "0x1234"; - try{ - await scheme.genericCallDirect.call(avatar.address,actionMock.address,a,b,c,0,{from :accounts[1]}); - assert(false, "genericAction should fail due to wrong owner"); - } catch (ex) { - helpers.assertVMException(ex); - } - }); + // it("genericCall no owner", async () => { + // avatar = await setup(accounts); + // let actionMock = await ActionMock.new(); + // var scheme = await SchemeMock.new(); + // let a = 7; + // let b = actionMock.address; + // let c = "0x1234"; + // try{ + // await scheme.genericCallDirect.call(avatar.address,actionMock.address,a,b,c,0,{from :accounts[1]}); + // assert(false, "genericAction should fail due to wrong owner"); + // } catch (ex) { + // helpers.assertVMException(ex); + // } + // }); it("generic call", async () => { avatar = await setup(accounts); @@ -38,6 +38,7 @@ contract('Avatar', accounts => { let b = actionMock.address; let c = "0x1234"; await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); + var vault = await avatar.vault(); var result = await scheme.genericCallDirect.call(avatar.address,actionMock.address,a,b,c,100); assert.equal(result[1],a*2); await scheme.genericCallDirect(avatar.address,actionMock.address,a,b,c,100); @@ -59,22 +60,26 @@ contract('Avatar', accounts => { it("pay ether to avatar", async () => { avatar = await setup(accounts); await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); + var vault = await avatar.vault(); + var avatarBalance = await web3.eth.getBalance(vault)/web3.utils.toWei('1', "ether"); assert.equal(avatarBalance,1); }); it("sendEther from ", async () => { avatar = await setup(accounts); - let otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); + let otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); + var vault = await avatar.vault(); + var avatarBalance = await web3.eth.getBalance(vault)/web3.utils.toWei('1', "ether"); assert.equal(avatarBalance,1); var tx = await avatar.sendEther(web3.utils.toWei('1', "ether"),otherAvatar.address); - assert.equal(tx.logs.length, 2); - assert.equal(tx.logs[1].event, "SendEther"); - avatarBalance =await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "SendEther"); + avatarBalance =await web3.eth.getBalance(vault)/web3.utils.toWei('1', "ether"); assert.equal(avatarBalance,0); - var otherAvatarBalance = await web3.eth.getBalance(otherAvatar.address)/web3.utils.toWei('1', "ether"); + var otherVault = await otherAvatar.vault(); + var otherAvatarBalance = await web3.eth.getBalance(otherVault)/web3.utils.toWei('1', "ether"); assert.equal(otherAvatarBalance,1); }); diff --git a/test/competition.js b/test/competition.js new file mode 100644 index 00000000..5499a37b --- /dev/null +++ b/test/competition.js @@ -0,0 +1,724 @@ +import * as helpers from './helpers'; +const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); +const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); +const Competition = artifacts.require("./Competition.sol"); + +export class ContributionRewardParams { + constructor() { + } +} + +const setupContributionRewardExt = async function( + accounts, + genesisProtocol, + token, + avatarAddress, + rewarderAddress + ) { + var contributionRewardParams = new ContributionRewardParams(); + + if (genesisProtocol === true) { + contributionRewardParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS); + contributionRewardParams.initdata = await new web3.eth.Contract(registration.contributionRewardExt.abi) + .methods + .initialize(avatarAddress, + contributionRewardParams.votingMachine.genesisProtocol.address, + contributionRewardParams.votingMachine.params, + rewarderAddress) + .encodeABI(); + } else { + contributionRewardParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); + contributionRewardParams.initdata = await new web3.eth.Contract(registration.contributionRewardExt.abi) + .methods + .initialize(avatarAddress, + contributionRewardParams.votingMachine.absoluteVote.address, + contributionRewardParams.votingMachine.params, + rewarderAddress) + .encodeABI(); + } + return contributionRewardParams; +}; + +var registration; +const setup = async function (accounts,genesisProtocol = false,tokenAddress=0) { + var testSetup = new helpers.TestSetup(); + testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100000); + registration = await helpers.registerImplementation(); + + if (genesisProtocol) { + testSetup.reputationArray = [1000,100,0]; + } else { + testSetup.reputationArray = [2000,5000,7000]; + } + testSetup.proxyAdmin = accounts[5]; + testSetup.org = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, + accounts, + registration, + [accounts[0], + accounts[1], + accounts[2]], + [1000,0,0], + testSetup.reputationArray); + + var tx = await registration.daoFactory.createInstance( + [0,0,0], + "Competition", + testSetup.proxyAdmin, + Buffer.from(''), + {from:testSetup.proxyAdmin}); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "ProxyCreated"); + testSetup.competition = await Competition.at(tx.logs[0].args._proxy); + testSetup.contributionRewardExtParams= await setupContributionRewardExt( + accounts, + genesisProtocol, + tokenAddress, + testSetup.org.avatar.address, + testSetup.competition.address); + + var permissions = "0x00000000"; + tx = await registration.daoFactory.setSchemes( + testSetup.org.avatar.address, + [web3.utils.fromAscii("ContributionRewardExt")], + testSetup.contributionRewardExtParams.initdata, + [helpers.getBytesLength(testSetup.contributionRewardExtParams.initdata)], + [permissions], + "metaData",{from:testSetup.proxyAdmin}); + + testSetup.contributionRewardExt = await ContributionRewardExt.at(tx.logs[1].args._scheme); + + await testSetup.competition.initialize(testSetup.contributionRewardExt.address); + testSetup.admin = accounts[0]; + + return testSetup; +}; + +const proposeCompetition = async function( + _testSetup, + _descriptionHash = "description-hash", + _reputationChange = 10, + _rewards = [1,2,3], + _rewardSplit = [50,25,15,10], + _startTime = 10, + _votingStartTime = 600, + _endTime = 1200, + _maxNumberOfVotesPerVoter = 3, + _suggestionsEndTime = 1200, + _admin = helpers.NULL_ADDRESS + ) { + + var block = await web3.eth.getBlock("latest"); + _testSetup.startTime = block.timestamp + _startTime; + _testSetup.votingStartTime = block.timestamp + _votingStartTime; + _testSetup.endTime = block.timestamp + _endTime; + _testSetup.suggestionsEndTime = block.timestamp + _suggestionsEndTime; + var sender = _testSetup.admin; + if (_admin !== helpers.NULL_ADDRESS) { + sender = _admin; + } + var tx = await _testSetup.competition.proposeCompetition( + _descriptionHash, + _reputationChange, + _rewards, + _testSetup.standardTokenMock.address, + _rewardSplit, + [_testSetup.startTime, + _testSetup.votingStartTime, + _testSetup.endTime, + _maxNumberOfVotesPerVoter, + _testSetup.suggestionsEndTime], + (_admin !== helpers.NULL_ADDRESS), + {from:sender} + ); + + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "NewCompetitionProposal"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._numberOfWinners,_rewardSplit.length); + assert.equal(tx.logs[0].args._rewardSplit[0],_rewardSplit[0]); + assert.equal(tx.logs[0].args._rewardSplit[1],_rewardSplit[1]); + assert.equal(tx.logs[0].args._rewardSplit[2],_rewardSplit[2]); + assert.equal(tx.logs[0].args._rewardSplit[3],_rewardSplit[3]); + assert.equal(tx.logs[0].args._startTime,_testSetup.startTime); + assert.equal(tx.logs[0].args._votingStartTime,_testSetup.votingStartTime); + assert.equal(tx.logs[0].args._endTime,_testSetup.endTime); + assert.equal(tx.logs[0].args._maxNumberOfVotesPerVoter,_maxNumberOfVotesPerVoter); + assert.equal(tx.logs[0].args._contributionRewardExt,_testSetup.contributionRewardExt.address); + assert.equal(tx.logs[0].args._suggestionsEndTime,_testSetup.suggestionsEndTime); + if (_admin !== helpers.NULL_ADDRESS) { + assert.equal(tx.logs[0].args._admin,sender); + } else { + assert.equal(tx.logs[0].args._admin,helpers.NULL_ADDRESS); + } + + return proposalId; +}; + + +contract('Competition', accounts => { + + it("proposeCompetition log", async function() { + var testSetup = await setup(accounts); + await proposeCompetition(testSetup); + + var descriptionHash = "description-hash"; + var reputationChange = 10; + var rewards = [1,2,3]; + var rewardSplit = new Array(101).fill(0); + var startTime = 0; + var votingStartTime = 600; + var endTime = 1200; + rewardSplit[0]= 100; + try { + + await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit); + assert(false, 'number of winners should be <= 100'); + } catch (ex) { + helpers.assertVMException(ex); + } + rewardSplit = [50,25,15,0]; + try { + + await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit); + assert(false, 'total reward split should be 100%'); + } catch (ex) { + helpers.assertVMException(ex); + } + rewardSplit = [50,25,15,10]; + + try { + + await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit, + startTime, + endTime);//votingStartTime + assert(false, '_votingStartTime < _endTime'); + } catch (ex) { + helpers.assertVMException(ex); + } + + try { + + await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit, + votingStartTime,//startTime + votingStartTime-1);//votingStartTime + assert(false, '_votingStartTime >= _startTime,'); + } catch (ex) { + helpers.assertVMException(ex); + } + + try { + + await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit, + startTime,//startTime + votingStartTime, + endTime, + 0); + assert(false, 'maxNumberOfVotesPerVoter > 0'); + } catch (ex) { + helpers.assertVMException(ex); + } + }); + + it("suggest", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + var tx = await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "NewSuggestion"); + assert.equal(tx.logs[0].args._suggestionId,1); + assert.equal(tx.logs[0].args._descriptionHash,"suggestion"); + }); + + it("suggest only admin", async function() { + var testSetup = await setup(accounts); + var admin = accounts[1]; + var proposalId = await proposeCompetition(testSetup, + "description-hash",10,[1,2,3],[50,25,15,10],10,600,1200,3,1200,admin); + await helpers.increaseTime(20); + try { + await testSetup.competition.suggest(proposalId,"suggestion",accounts[3]); + assert(false, 'only admin can suggest'); + } catch (ex) { + helpers.assertVMException(ex); + } + var tx = await testSetup.competition.suggest(proposalId,"suggestion",accounts[3],{from:admin}); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "NewSuggestion"); + assert.equal(tx.logs[0].args._suggestionId,1); + assert.equal(tx.logs[0].args._descriptionHash,"suggestion"); + assert.equal(tx.logs[0].args._beneficiary,accounts[3]); + }); + + it("cannot suggest after suggestionEndTime", async function() { + var descriptionHash = "description-hash"; + var reputationChange = 10; + var rewards = [1,2,3]; + var rewardSplit = [100]; + var startTime = 10; + var votingStartTime = 600; + var endTime = 1200; + var maxNumberOfVotesPerVoter = 3; + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit, + startTime, + votingStartTime, + endTime, + maxNumberOfVotesPerVoter, + 200);//suggestionEndTime + await helpers.increaseTime(20);//increase time for suggestion + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + //increase time after suggestion end time + await helpers.increaseTime(250); + try { + + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + assert(false, 'cannot suggest after suggestionEndTime'); + } catch (ex) { + helpers.assertVMException(ex); + } + + }); + + it("cannot suggest before start time", async function() { + var testSetup = await setup(accounts); + var descriptionHash = "description-hash"; + var reputationChange = 10; + var rewards = [1,2,3]; + var rewardSplit = [0,50,25,25]; + var proposalId = await proposeCompetition(testSetup, + descriptionHash, + reputationChange, + rewards, + rewardSplit, + 20//startTime + );//votingStartTime + try { + + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + assert(false, 'cannot suggest before start time'); + } catch (ex) { + helpers.assertVMException(ex); + } + await helpers.increaseTime(20); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + }); + + it("cannot suggest after competition end", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup);//votingStartTime + await helpers.increaseTime(20); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await helpers.increaseTime(1200+100); + try { + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + assert(false, 'cannot suggest after competition end'); + } catch (ex) { + helpers.assertVMException(ex); + } + }); + + it("vote", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + var tx = await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + var suggestionId = tx.logs[0].args._suggestionId; + + try { + await testSetup.competition.vote(suggestionId); + assert(false, 'vote before voting start time should fail'); + } catch (ex) { + helpers.assertVMException(ex); + } + await helpers.increaseTime(650); + + try { + await testSetup.competition.vote(suggestionId+1); + assert(false, 'vote on none valid suggestion'); + } catch (ex) { + helpers.assertVMException(ex); + } + var proposal = await testSetup.competition.proposals(proposalId); + tx = await testSetup.competition.vote(suggestionId); + + try { + await testSetup.competition.vote(suggestionId); + assert(false, 'can vote only one time on each suggestion'); + } catch (ex) { + helpers.assertVMException(ex); + } + + assert.equal(tx.logs.length, 2); + assert.equal(tx.logs[0].event, "SnapshotBlock"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._snapshotBlock,tx.logs[0].blockNumber); + + assert.equal(tx.logs[1].event, "NewVote"); + assert.equal(tx.logs[1].args._suggestionId,1); + assert.equal(tx.logs[1].args._reputation,testSetup.reputationArray[0]); + + //first vote set the snapshotBlock + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.vote(2); + proposal = await testSetup.competition.proposals(proposalId); + assert.equal(proposal.snapshotBlock, tx.logs[0].blockNumber); + + //3rd suggestion + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + //4th suggestion + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.vote(3); + + try { + await testSetup.competition.vote(4); + assert(false, 'cannot vote more than allowed per voter'); + } catch (ex) { + helpers.assertVMException(ex); + } + + }); + + + it("total votes", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + var tx = await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + var suggestionId = tx.logs[0].args._suggestionId; + await helpers.increaseTime(650); + await testSetup.competition.vote(suggestionId); + await testSetup.competition.vote(suggestionId,{from:accounts[1]}); + await testSetup.competition.vote(suggestionId,{from:accounts[2]}); + var suggestion = await testSetup.competition.suggestions(suggestionId); + assert.equal(suggestion.totalVotes, testSetup.reputationArray[0] +testSetup.reputationArray[1]+testSetup.reputationArray[2]); + }); + + it("getOrderedIndexOfSuggestion", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + for (var i=0;i<20;i++) { + //submit 20 suggestion + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + } + await helpers.increaseTime(650); + await testSetup.competition.vote(10,{from:accounts[0]}); + await testSetup.competition.vote(16,{from:accounts[2]}); + await testSetup.competition.vote(5,{from:accounts[1]}); + + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(10),2); + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(5),1); + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(16),0); + + }); + + it("getOrderedIndexOfSuggestion equality case", async function() { + var testSetup = await setup(accounts); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + for (var i=0;i<20;i++) { + //submit 20 suggestion + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + } + await helpers.increaseTime(650); + await testSetup.competition.vote(10,{from:accounts[1]}); + await testSetup.competition.vote(16,{from:accounts[1]}); + await testSetup.competition.vote(5,{from:accounts[0]}); + + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(10),0); + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(16),0); + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(5),2); + try { + await testSetup.competition.getOrderedIndexOfSuggestion(0); + assert(false, 'revert if suggestion does not exist'); + } catch (ex) { + helpers.assertVMException(ex); + } + try { + await testSetup.competition.getOrderedIndexOfSuggestion(21); + assert(false, 'revert if suggestion does not exist'); + } catch (ex) { + helpers.assertVMException(ex); + } + assert.equal(await testSetup.competition.getOrderedIndexOfSuggestion(1),3); + }); + + it("redeem", async function() { + var testSetup = await setup(accounts); + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,30,{from:accounts[1]}); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var proposalId = await proposeCompetition(testSetup); + await helpers.increaseTime(20); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + try { + await testSetup.competition.redeem(1); + assert(false, 'cannot redeem if no vote'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + await helpers.increaseTime(650); + await testSetup.competition.vote(1,{from:accounts[1]}); + try { + await testSetup.competition.redeem(1); + assert(false, 'cannot redeem if competion not ended yet'); + } catch (ex) { + helpers.assertVMException(ex); + } + await helpers.increaseTime(650); + var tx = await testSetup.competition.redeem(1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,100); + + await testSetup.contributionRewardExt.getPastEvents('RedeemReputation', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemReputation"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,10); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemEther', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemEther"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,2); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemNativeToken', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemNativeToken"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,1); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemExternalToken', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemExternalToken"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,3); + }); + + }); + + it("negative reputation change is not allowed", async function() { + var testSetup = await setup(accounts); + try { + await proposeCompetition(testSetup,"description-hash",-1000); + assert(false, 'negative reputation change is not allowed'); + } catch (ex) { + helpers.assertVMException(ex); + } + await proposeCompetition(testSetup,"description-hash",0); + }); + + it("redeem multipe suggestions", async function() { + var testSetup = await setup(accounts); + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,3000,{from:accounts[1]}); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:2000}); + var proposalId = await proposeCompetition(testSetup,"description-hash",1000,[1000,2000,3000]); + await helpers.increaseTime(20); + + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + await helpers.increaseTime(650); + await testSetup.competition.vote(1,{from:accounts[0]}); + await testSetup.competition.vote(2,{from:accounts[1]}); + await testSetup.competition.vote(3,{from:accounts[2]}); + await helpers.increaseTime(650); + var tx = await testSetup.competition.redeem(1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,18); + + await testSetup.contributionRewardExt.getPastEvents('RedeemReputation', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemReputation"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,180); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemEther', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemEther"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,(2000*18/100)); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemNativeToken', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemNativeToken"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,(1000*18/100)); + }); + + await testSetup.contributionRewardExt.getPastEvents('RedeemExternalToken', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemExternalToken"); + assert.equal(events[0].args._beneficiary,accounts[0]); + assert.equal(events[0].args._amount,(3000*18/100)); + }); + tx = await testSetup.competition.redeem(2); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,28); + + try { + await testSetup.competition.sendLeftOverFunds(proposalId); + assert(false, 'cannot sendLeftOverFunds because not all proposals redeemed yet'); + } catch (ex) { + helpers.assertVMException(ex); + } + + tx = await testSetup.competition.redeem(3); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,53); + + var proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + tx = await testSetup.competition.sendLeftOverFunds(proposalId); + + await testSetup.contributionRewardExt.getPastEvents('RedeemExternalToken', { + fromBlock: tx.blockNumber, + toBlock: 'latest' + }) + .then(function(events){ + assert.equal(events[0].event,"RedeemExternalToken"); + assert.equal(events[0].args._beneficiary,testSetup.org.avatar.address); + assert.equal(events[0].args._amount.toNumber(),proposal.externalTokenRewardLeft.toNumber()); + }); + + }); + + it("redeem multipe suggestions - multiple smallers suggestion", async function() { + var testSetup = await setup(accounts); + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,3000,{from:accounts[1]}); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:2000}); + var proposalId = await proposeCompetition(testSetup,"description-hash",1000,[1000,2000,3000]); + await helpers.increaseTime(20); + + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + await helpers.increaseTime(650); + await testSetup.competition.vote(1,{from:accounts[2]}); + await testSetup.competition.vote(2,{from:accounts[1]}); + await testSetup.competition.vote(3,{from:accounts[1]}); + await testSetup.competition.vote(4,{from:accounts[0]}); + await testSetup.competition.vote(5,{from:accounts[0]}); + await testSetup.competition.vote(6,{from:accounts[0]}); + await helpers.increaseTime(650); + var tx = await testSetup.competition.redeem(4); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,3); + + tx = await testSetup.competition.redeem(5); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,3); + + tx = await testSetup.competition.redeem(6); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,3); + }); + + it("multiple users vote on the same suggestion ", async function() { + var testSetup = await setup(accounts); + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,3000,{from:accounts[1]}); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:2000}); + var proposalId = await proposeCompetition(testSetup,"description-hash",1000,[1000,2000,3000],[50,30,10,10]); + await helpers.increaseTime(20); + + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + await testSetup.competition.suggest(proposalId,"suggestion",helpers.NULL_ADDRESS); + + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + await helpers.increaseTime(650); + await testSetup.competition.vote(1,{from:accounts[1]}); + await testSetup.competition.vote(2,{from:accounts[0]}); + await testSetup.competition.vote(2,{from:accounts[2]}); + await helpers.increaseTime(650); + var tx = await testSetup.competition.redeem(2); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "Redeem"); + assert.equal(tx.logs[0].args._proposalId,proposalId); + assert.equal(tx.logs[0].args._rewardPercentage,60); + }); +}); diff --git a/test/constants.js b/test/constants.js index 3f8b91cb..499b08e6 100644 --- a/test/constants.js +++ b/test/constants.js @@ -1,3 +1,3 @@ -const ARC_GAS_LIMIT = 6500000; +const ARC_GAS_LIMIT = 7100000; module.exports = { ARC_GAS_LIMIT }; diff --git a/test/contributionreward.js b/test/contributionreward.js index e0b9027f..181ec27e 100644 --- a/test/contributionreward.js +++ b/test/contributionreward.js @@ -91,7 +91,7 @@ const setup = async function (accounts,genesisProtocol = false,tokenAddress=0) { tokenAddress, testSetup.org.avatar.address); var permissions = "0x00000000"; - + var tx = await registration.daoFactory.setSchemes( testSetup.org.avatar.address, [web3.utils.fromAscii("ContributionReward")], @@ -252,7 +252,8 @@ contract('ContributionReward', accounts => { await testSetup.contributionRewardParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); await helpers.increaseTime(periodLength+1); await testSetup.contributionReward.redeem(proposalId,[false,false,true,false]); - var eth = await web3.eth.getBalance(otherAvatar.address); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward); }); @@ -351,7 +352,8 @@ contract('ContributionReward', accounts => { assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "RedeemEther"); assert.equal(tx.logs[0].args._amount, ethReward); - var eth = await web3.eth.getBalance(otherAvatar.address); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward); await checkRedeemedPeriods(testSetup,proposalId,0,0,1,0); @@ -359,7 +361,7 @@ contract('ContributionReward', accounts => { //now try again on the same period tx = await testSetup.contributionReward.redeem(proposalId,[false,false,true,false]); assert.equal(tx.logs.length, 0); - eth = await web3.eth.getBalance(otherAvatar.address); + eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward); //now try again on 2nd period @@ -372,7 +374,7 @@ contract('ContributionReward', accounts => { assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "RedeemEther"); assert.equal(tx.logs[0].args._amount, ethReward); - eth = await web3.eth.getBalance(otherAvatar.address); + eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward*2); //now try again on 4th period @@ -385,7 +387,7 @@ contract('ContributionReward', accounts => { assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "RedeemEther"); assert.equal(tx.logs[0].args._amount, ethReward*2); - eth = await web3.eth.getBalance(otherAvatar.address); + eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward*4); //now try again on 5th period - no ether on avatar should revert @@ -407,7 +409,7 @@ contract('ContributionReward', accounts => { assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "RedeemEther"); assert.equal(tx.logs[0].args._amount, ethReward); - eth = await web3.eth.getBalance(otherAvatar.address); + eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward*5); await checkRedeemedPeriods(testSetup,proposalId,0,0,5,0); @@ -418,7 +420,7 @@ contract('ContributionReward', accounts => { await helpers.increaseTime(periodLength+1); tx = await testSetup.contributionReward.redeem(proposalId,[false,false,true,false]); assert.equal(tx.logs.length, 0); - eth = await web3.eth.getBalance(otherAvatar.address); + eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward*5); await checkRedeemedPeriods(testSetup,proposalId,0,0,5,0); @@ -524,7 +526,7 @@ contract('ContributionReward', accounts => { var arcUtils = await Redeemer.new(); var redeemRewards = await arcUtils.redeem.call(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, - proposalId,testSetup.org.avatar.address, + proposalId, accounts[0]); assert.equal(redeemRewards[0][1],100); //redeemRewards[0] gpRewards assert.equal(redeemRewards[0][2],60); @@ -539,10 +541,10 @@ contract('ContributionReward', accounts => { await arcUtils.redeem(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, - proposalId,testSetup.org.avatar.address, + proposalId, accounts[0]); - - var eth = await web3.eth.getBalance(otherAvatar.address); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward); assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),reputationReward); assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),nativeTokenReward); @@ -582,7 +584,7 @@ contract('ContributionReward', accounts => { var arcUtils = await Redeemer.new(); var redeemRewards = await arcUtils.redeem.call(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, - proposalId,testSetup.org.avatar.address, + proposalId, accounts[0]); assert.equal(redeemRewards[0][1],0); //redeemRewards[0] gpRewards assert.equal(redeemRewards[0][2],60); @@ -597,10 +599,10 @@ contract('ContributionReward', accounts => { await arcUtils.redeem(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, - proposalId,testSetup.org.avatar.address, + proposalId, accounts[0]); - - var eth = await web3.eth.getBalance(otherAvatar.address); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); assert.equal(eth,ethReward); assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),reputationReward); assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),nativeTokenReward); @@ -638,7 +640,6 @@ contract('ContributionReward', accounts => { await arcUtils.redeem(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, proposalId, - testSetup.org.avatar.address, accounts[0]); var eth = await web3.eth.getBalance(otherAvatar.address); assert.equal(eth,0); @@ -675,7 +676,7 @@ contract('ContributionReward', accounts => { var arcUtils = await Redeemer.new(); await arcUtils.redeem(testSetup.contributionReward.address, testSetup.contributionRewardParams.votingMachine.genesisProtocol.address, - proposalId,testSetup.org.avatar.address, + proposalId, accounts[1]); var proposal = await testSetup.contributionRewardParams.votingMachine.genesisProtocol.proposals(proposalId); assert.equal(proposal.state,1); //ExpiredInQueue diff --git a/test/contributionrewardext.js b/test/contributionrewardext.js new file mode 100644 index 00000000..1bbaf7a6 --- /dev/null +++ b/test/contributionrewardext.js @@ -0,0 +1,725 @@ +import * as helpers from './helpers'; +const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); +const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); +const Avatar = artifacts.require("./Avatar.sol"); +const Redeemer = artifacts.require("./Redeemer.sol"); + + + +export class ContributionRewardParams { + constructor() { + } +} + +const setupContributionRewardExt = async function( + accounts, + genesisProtocol, + token, + avatarAddress, + rewarderAddress = helpers.NULL_ADDRESS + ) { + var contributionRewardParams = new ContributionRewardParams(); + + if (genesisProtocol === true) { + contributionRewardParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS); + contributionRewardParams.initdata = await new web3.eth.Contract(registration.contributionRewardExt.abi) + .methods + .initialize(avatarAddress, + contributionRewardParams.votingMachine.genesisProtocol.address, + contributionRewardParams.votingMachine.params, + rewarderAddress) + .encodeABI(); + } else { + contributionRewardParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); + contributionRewardParams.initdata = await new web3.eth.Contract(registration.contributionRewardExt.abi) + .methods + .initialize(avatarAddress, + contributionRewardParams.votingMachine.absoluteVote.address, + contributionRewardParams.votingMachine.params, + rewarderAddress) + .encodeABI(); + } + return contributionRewardParams; +}; +var registration; +const setup = async function (accounts,genesisProtocol = false,tokenAddress=0,service=helpers.NULL_ADDRESS) { + var testSetup = new helpers.TestSetup(); + testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100000); + registration = await helpers.registerImplementation(); + + if (genesisProtocol) { + testSetup.reputationArray = [1000,100,0]; + } else { + testSetup.reputationArray = [2000,4000,7000]; + } + testSetup.proxyAdmin = accounts[5]; + testSetup.org = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, + accounts, + registration, + [accounts[0], + accounts[1], + accounts[2]], + [1000,0,0], + testSetup.reputationArray); + testSetup.contributionRewardExtParams= await setupContributionRewardExt( + accounts, + genesisProtocol, + tokenAddress, + testSetup.org.avatar.address, + service); + + var permissions = "0x00000000"; + var tx = await registration.daoFactory.setSchemes( + testSetup.org.avatar.address, + [web3.utils.fromAscii("ContributionRewardExt")], + testSetup.contributionRewardExtParams.initdata, + [helpers.getBytesLength(testSetup.contributionRewardExtParams.initdata)], + [permissions], + "metaData",{from:testSetup.proxyAdmin}); + + testSetup.contributionRewardExt = await ContributionRewardExt.at(tx.logs[1].args._scheme); + + testSetup.admin = accounts[0]; + + return testSetup; +}; +contract('ContributionRewardExt', accounts => { + + it("initialize", async function() { + var testSetup = await setup(accounts); + assert.equal(await testSetup.contributionRewardExt.votingMachine(),testSetup.contributionRewardExtParams.votingMachine.absoluteVote.address); + }); + + it("proposeContributionReward log", async function() { + var testSetup = await setup(accounts); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + "description-hash", + 10, + [1,2,3], + testSetup.standardTokenMock.address, + accounts[0], + helpers.NULL_ADDRESS); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "NewContributionProposal"); + assert.equal(await helpers.getValueFromLogs(tx, '_avatar',0), testSetup.org.avatar.address, "Wrong log: _avatar"); + assert.equal(await helpers.getValueFromLogs(tx, '_intVoteInterface',0), testSetup.contributionRewardExtParams.votingMachine.absoluteVote.address, "Wrong log: _intVoteInterface"); + assert.equal(await helpers.getValueFromLogs(tx, '_descriptionHash',15), "description-hash", "Wrong log: _contributionDescription"); + assert.equal(await helpers.getValueFromLogs(tx, '_reputationChange',0), 10, "Wrong log: _reputationChange"); + var arr = await helpers.getValueFromLogs(tx, '_rewards',0); + assert.equal(arr[0].words[0], 1, "Wrong log: _rewards"); + assert.equal(arr[1].words[0], 2, "Wrong log: _rewards"); + assert.equal(arr[2].words[0], 3, "Wrong log: _rewards"); + assert.equal(await helpers.getValueFromLogs(tx, '_externalToken',0), testSetup.standardTokenMock.address, "Wrong log: _externalToken"); + assert.equal(await helpers.getValueFromLogs(tx, '_beneficiary',0), accounts[0], "Wrong log: _beneficiary"); + }); + + it("proposeContributionReward check beneficiary==0", async() => { + var testSetup = await setup(accounts); + var beneficiary = helpers.NULL_ADDRESS; + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + 0, + [0,0,0], + testSetup.standardTokenMock.address, + beneficiary, + helpers.NULL_ADDRESS + ); + assert.equal(await helpers.getValueFromLogs(tx, '_beneficiary'),accounts[0]); + }); + + it("execute proposeContributionReward yes ", async function() { + var testSetup = await setup(accounts); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + 0, + [0,0,0], + testSetup.standardTokenMock.address, + accounts[0], + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + var organizationProposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.notEqual(organizationProposal.acceptedByVotingMachine,0);//acceptedByVotingMachine + }); + + it("execute proposeContributionReward mint reputation ", async function() { + var testSetup = await setup(accounts); + var reputationReward = 12; + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [0,0,0], + testSetup.standardTokenMock.address, + accounts[1], + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + tx = await testSetup.contributionRewardExt.redeem(proposalId,[true,false,false,false]); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemReputation"); + assert.equal(tx.logs[0].args._amount, reputationReward); + var rep = await testSetup.org.reputation.balanceOf(accounts[1]); + assert.equal(rep.toNumber(),testSetup.reputationArray[1]+reputationReward); + }); + + it("execute proposeContributionReward mint tokens ", async function() { + var testSetup = await setup(accounts); + var reputationReward = 12; + var nativeTokenReward = 12; + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,0,0], + testSetup.standardTokenMock.address, + accounts[1], + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + tx = await testSetup.contributionRewardExt.redeem(proposalId,[false,true,false,false]); + var tokens = await testSetup.org.token.balanceOf(accounts[1]); + assert.equal(tokens.toNumber(),nativeTokenReward); + }); + + it("execute proposeContributionReward send ethers ", async function() { + var testSetup = await setup(accounts); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + //send some ether to the org avatar + var otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,0], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExt.redeem(proposalId,[false,false,true,false]); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); + assert.equal(eth,ethReward); + }); + + it("execute proposeContributionReward send externalToken ", async function() { + var testSetup = await setup(accounts); + //give some tokens to organization avatar + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,30,{from:accounts[1]}); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + var externalTokenReward = 12; + //send some ether to the org avatar + var otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,externalTokenReward], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExt.redeem(proposalId,[false,false,false,true]); + var tokens = await testSetup.standardTokenMock.balanceOf(otherAvatar.address); + assert.equal(tokens.toNumber(),externalTokenReward); + }); + + it("execute proposeContributionReward proposal decision=='no' send externalToken ", async function() { + var testSetup = await setup(accounts); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + var externalTokenReward = 12; + + //send some ether to the org avatar + var otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,externalTokenReward], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + var organizationProposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(organizationProposal[5],otherAvatar.address);//beneficiary + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,0,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + + try { + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + assert(false, 'redeem should revert because there was no positive voting'); + } catch (ex) { + helpers.assertVMException(ex); + } + }); + + it("execute proposeContributionReward mint negative reputation ", async function() { + var testSetup = await setup(accounts); + var reputationReward = -12; + + + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [0,0,0], + testSetup.standardTokenMock.address, + accounts[0], + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + + tx = await testSetup.contributionRewardExt.redeem(proposalId,[true,false,false,false]); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemReputation"); + assert.equal(tx.logs[0].args._amount, reputationReward); + var rep = await testSetup.org.reputation.balanceOf(accounts[0]); + assert.equal(rep.toNumber(),testSetup.reputationArray[0]+reputationReward); + }); + + + it("call execute should revert ", async function() { + var testSetup = await setup(accounts); + var reputationReward = -12; + + + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [0,0,0], + testSetup.standardTokenMock.address, + accounts[0], + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + try { + await testSetup.contributionRewardExt.executeProposal(proposalId,1); + assert(false, 'only voting machine can call execute'); + } catch (ex) { + helpers.assertVMException(ex); + } + + }); + + it("execute proposeContributionReward via genesisProtocol and redeem using Redeemer", async function() { + var standardTokenMock = await ERC20Mock.new(accounts[0],1000); + var testSetup = await setup(accounts,true,standardTokenMock.address); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + + + //send some ether to the org avatar + var otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,0], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + + var arcUtils = await Redeemer.new(); + var redeemRewards = await arcUtils.redeemFromCRExt.call(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[0]); + assert.equal(redeemRewards[0][1],100); //redeemRewards[0] gpRewards + assert.equal(redeemRewards[0][2],60); + assert.equal(redeemRewards[1][0],0); //daoBountyRewards + assert.equal(redeemRewards[1][1],0); //daoBountyRewards + assert.equal(redeemRewards[2],false); //isExecuted + assert.equal(redeemRewards[3],1); //winningVote + assert.equal(redeemRewards[4],reputationReward); //crReputationReward + assert.equal(redeemRewards[5],nativeTokenReward); //crNativeTokenReward + assert.equal(redeemRewards[6],ethReward); //crEthReward + assert.equal(redeemRewards[7],0); //crExternalTokenReward + + await arcUtils.redeemFromCRExt(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[0]); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); + assert.equal(eth,ethReward); + assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),reputationReward); + assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),nativeTokenReward); + var reputation = await testSetup.org.reputation.balanceOf(accounts[0]); + var reputationGainAsVoter = 0; + var proposingRepRewardConstA=60; + var reputationGainAsProposer = proposingRepRewardConstA; + assert.equal(reputation, 1000+reputationGainAsVoter + reputationGainAsProposer); + }); + + it("execute proposeContributionReward via genesisProtocol and redeem using Redeemer for un excuted boosted proposal", async function() { + var standardTokenMock = await ERC20Mock.new(accounts[0],1000); + var testSetup = await setup(accounts,true,standardTokenMock.address); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + //send some ether to the org avatar + var otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,0], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[1]}); + + await standardTokenMock.approve(testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address,1000); + await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.stake(proposalId,1,1000); + await helpers.increaseTime(60+1); + var arcUtils = await Redeemer.new(); + + var redeemRewards = await arcUtils.redeemFromCRExt.call(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[0]); + + assert.equal(redeemRewards[0][1],0); //redeemRewards[0] gpRewards + assert.equal(redeemRewards[0][2],60); + assert.equal(redeemRewards[1][0],0); //daoBountyRewards + assert.equal(redeemRewards[1][1],15); //daoBountyRewards + assert.equal(redeemRewards[2],true); //isExecuted + assert.equal(redeemRewards[3],1); //winningVote + assert.equal(redeemRewards[4],reputationReward); //crReputationReward + assert.equal(redeemRewards[5],nativeTokenReward); //crNativeTokenReward + assert.equal(redeemRewards[6],ethReward); //crEthReward + assert.equal(redeemRewards[7],0); //crExternalTokenReward + + await arcUtils.redeemFromCRExt(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[0]); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); + assert.equal(eth,ethReward); + assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),reputationReward); + assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),nativeTokenReward); + var reputation = await testSetup.org.reputation.balanceOf(accounts[0]); + var reputationGainAsVoter = 0; + var proposingRepRewardConstA=60; + var reputationGainAsProposer = proposingRepRewardConstA; + assert.equal(reputation, 1000+reputationGainAsVoter + reputationGainAsProposer); + }); + + it("execute proposeContributionReward via genesisProtocol and redeem using Redeemer for negative proposal", async function() { + var standardTokenMock = await ERC20Mock.new(accounts[0],1000); + var testSetup = await setup(accounts,true,standardTokenMock.address); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + + + //send some ether to the org avatar + var otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,0], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.vote(proposalId,2,0,helpers.NULL_ADDRESS,{from:accounts[0]}); + + var arcUtils = await Redeemer.new(); + await arcUtils.redeemFromCRExt(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[0]); + var vault = await otherAvatar.vault(); + var eth = await web3.eth.getBalance(vault); + assert.equal(eth,0); + assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),0); + assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),0); + var reputation = await testSetup.org.reputation.balanceOf(accounts[0]); + //no reputation reward for proposer for negative proposal. + //reputation reward for a single voter = 0 + assert.equal(reputation, 1000); + }); + + it("execute proposeContributionReward via genesisProtocol and redeem using Redeemer ExpiredInQueue", async function() { + var standardTokenMock = await ERC20Mock.new(accounts[0],1000); + var testSetup = await setup(accounts,true,standardTokenMock.address); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + + + //send some ether to the org avatar + var otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,0], + testSetup.standardTokenMock.address, + otherAvatar.address, + helpers.NULL_ADDRESS + ); + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + + await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[1]}); + await helpers.increaseTime(60+1); + var arcUtils = await Redeemer.new(); + await arcUtils.redeemFromCRExt(testSetup.contributionRewardExt.address, + testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.address, + proposalId, + accounts[1]); + var proposal = await testSetup.contributionRewardExtParams.votingMachine.genesisProtocol.proposals(proposalId); + assert.equal(proposal.state,1); //ExpiredInQueue + var reputation = await testSetup.org.reputation.balanceOf(accounts[1]); + //accounts[1] redeems its deposit rep. + assert.equal(reputation.toNumber(), 100); + }); + + it("execute proposeContributionReward mint reputation with period 0 ", async function() { + var testSetup = await setup(accounts); + var reputationReward = 12; + + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [0,0,0], + testSetup.standardTokenMock.address, + accounts[1], + helpers.NULL_ADDRESS, + {from:accounts[2]} + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + tx = await testSetup.contributionRewardExt.redeem(proposalId,[true,false,false,false]); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemReputation"); + assert.equal(tx.logs[0].args._amount, reputationReward); + var rep = await testSetup.org.reputation.balanceOf(accounts[1]); + assert.equal(rep.toNumber(),testSetup.reputationArray[1]+reputationReward); + //try to redeem again. + tx = await testSetup.contributionRewardExt.redeem(proposalId,[true,false,false,false]); + assert.equal(tx.logs.length, 0); + rep = await testSetup.org.reputation.balanceOf(accounts[1]); + assert.equal(rep.toNumber(),testSetup.reputationArray[1]+reputationReward); + }); + + it("cannot initialize twice", async function() { + var testSetup = await setup(accounts); + try { + await testSetup.contributionRewardExt.initialize( + testSetup.org.avatar.address, + testSetup.contributionRewardExtParams.votingMachine.absoluteVote.address, + testSetup.contributionRewardExtParams.votingMachine.absoluteVote.address, + helpers.NULL_ADDRESS + ); + assert(false, 'cannot initialize twice'); + } catch (ex) { + helpers.assertVMException(ex); + } + }); + it("execute proposeContributionReward to self and redeem from external contract ", async function() { + var testSetup = await setup(accounts,false,0,accounts[0]); + var reputationReward = 12; + var nativeTokenReward = 12; + var ethReward = 12; + await testSetup.standardTokenMock.transfer(testSetup.org.avatar.address,30,{from:accounts[1]}); + var externalTokenReward = 12; + //send some ether to the org avatar + await web3.eth.sendTransaction({from:accounts[0],to:testSetup.org.avatar.address, value:20}); + var tx = await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,externalTokenReward], + testSetup.standardTokenMock.address, + testSetup.contributionRewardExt.address, + helpers.NULL_ADDRESS + ); + //Vote with reputation to trigger execution + var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); + await testSetup.contributionRewardExtParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); + await testSetup.contributionRewardExt.redeem(proposalId,[true,true,true,true]); + var contVault = await testSetup.contributionRewardExt.vault(); + var eth = await web3.eth.getBalance(contVault); + assert.equal(eth,ethReward); + var otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, helpers.NULL_ADDRESS,accounts[0]); + + //redeem ether + try { + await testSetup.contributionRewardExt.redeemEtherByRewarder(proposalId,otherAvatar.address,1,{from:accounts[1]}); + assert(false, 'only service contract can redeem'); + } catch (ex) { + helpers.assertVMException(ex); + } + tx = await testSetup.contributionRewardExt.redeemEtherByRewarder(proposalId,otherAvatar.address,1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemEther"); + assert.equal(tx.logs[0].args._amount, 1); + var vault = await otherAvatar.vault(); + assert.equal(await web3.eth.getBalance(vault),1); + //cannot redeem more than the proposal reward + var proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.ethRewardLeft, ethReward - 1); + try { + await testSetup.contributionRewardExt.redeemEtherByRewarder(proposalId,otherAvatar.address,proposal.ethRewardLeft+1); + assert(false, 'cannot redeem more than the proposal reward'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExt.redeemEtherByRewarder(proposalId,otherAvatar.address,proposal.ethRewardLeft); + assert.equal(await web3.eth.getBalance(vault),ethReward); + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.ethRewardLeft, 0); + + //redeem nativeToken + try { + await testSetup.contributionRewardExt.redeemNativeTokenByRewarder(proposalId,otherAvatar.address,1,{from:accounts[1]}); + assert(false, 'only service contract can redeem'); + } catch (ex) { + helpers.assertVMException(ex); + } + tx = await testSetup.contributionRewardExt.redeemNativeTokenByRewarder(proposalId,otherAvatar.address,1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemNativeToken"); + assert.equal(tx.logs[0].args._amount, 1); + + assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),1); + //cannot redeem more than the proposal reward + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.nativeTokenRewardLeft, nativeTokenReward - 1); + try { + await testSetup.contributionRewardExt.redeemNativeTokenByRewarder(proposalId,otherAvatar.address,proposal.nativeTokenRewardLeft+1); + assert(false, 'cannot redeem more than the proposal reward'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExt.redeemNativeTokenByRewarder(proposalId,otherAvatar.address,proposal.nativeTokenRewardLeft); + assert.equal(await testSetup.org.token.balanceOf(otherAvatar.address),nativeTokenReward); + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.nativeTokenRewardLeft, 0); + + + //redeem externalToken + try { + await testSetup.contributionRewardExt.redeemExternalTokenByRewarder(proposalId,otherAvatar.address,1,{from:accounts[1]}); + assert(false, 'only service contract can redeem'); + } catch (ex) { + helpers.assertVMException(ex); + } + tx = await testSetup.contributionRewardExt.redeemExternalTokenByRewarder(proposalId,otherAvatar.address,1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemExternalToken"); + assert.equal(tx.logs[0].args._amount, 1); + + assert.equal(await testSetup.standardTokenMock.balanceOf(otherAvatar.address),1); + //cannot redeem more than the proposal reward + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.externalTokenRewardLeft, externalTokenReward - 1); + try { + await testSetup.contributionRewardExt.redeemExternalTokenByRewarder(proposalId,otherAvatar.address,proposal.externalTokenRewardLeft+1); + assert(false, 'cannot redeem more than the proposal reward'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExt.redeemExternalTokenByRewarder(proposalId,otherAvatar.address,proposal.externalTokenRewardLeft); + assert.equal(await testSetup.standardTokenMock.balanceOf(otherAvatar.address),externalTokenReward); + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.externalTokenRewardLeft, 0); + + + //redeem reputation + try { + await testSetup.contributionRewardExt.redeemReputationByRewarder(proposalId,otherAvatar.address,1,{from:accounts[1]}); + assert(false, 'only service contract can redeem'); + } catch (ex) { + helpers.assertVMException(ex); + } + tx = await testSetup.contributionRewardExt.redeemReputationByRewarder(proposalId,otherAvatar.address,1); + assert.equal(tx.logs.length, 1); + assert.equal(tx.logs[0].event, "RedeemReputation"); + assert.equal(tx.logs[0].args._amount, 1); + + assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),1); + //cannot redeem more than the proposal reward + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.reputationChangeLeft, reputationReward - 1); + try { + await testSetup.contributionRewardExt.redeemReputationByRewarder(proposalId,otherAvatar.address,proposal.reputationChangeLeft+1); + assert(false, 'cannot redeem more than the proposal reward'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExt.redeemReputationByRewarder(proposalId,otherAvatar.address,proposal.reputationChangeLeft); + assert.equal(await testSetup.org.reputation.balanceOf(otherAvatar.address),reputationReward); + proposal = await testSetup.contributionRewardExt.organizationProposals(proposalId); + assert.equal(proposal.reputationChangeLeft, 0); + + }); + + it("negativ rep change is not allowed for rewarder to set ", async function() { + var testSetup = await setup(accounts,false,0,accounts[0]); + var reputationReward = -12; + var nativeTokenReward = 12; + var ethReward = 12; + var externalTokenReward = 12; + try { + await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + reputationReward, + [nativeTokenReward,ethReward,externalTokenReward], + testSetup.standardTokenMock.address, + testSetup.contributionRewardExt.address, + helpers.NULL_ADDRESS + ); + assert(false, 'negativ rep change is not allowed for rewarder to set'); + } catch (ex) { + helpers.assertVMException(ex); + } + await testSetup.contributionRewardExt.proposeContributionReward( + web3.utils.asciiToHex("description"), + 0, + [nativeTokenReward,ethReward,externalTokenReward], + testSetup.standardTokenMock.address, + testSetup.contributionRewardExt.address, + helpers.NULL_ADDRESS + ); + }); + +}); diff --git a/test/controller.js b/test/controller.js index 9c765b50..830655d6 100644 --- a/test/controller.js +++ b/test/controller.js @@ -331,7 +331,9 @@ contract('Controller', accounts => { }); it("sendEther", async () => { controller = await setup(accounts); - let otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, avatar.address); + let otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, avatar.address,accounts[0]); + await avatar.transferOwnership(controller.address); //send some ether to the avatar await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); @@ -345,9 +347,11 @@ contract('Controller', accounts => { .then(function(events){ assert.equal(events[0].event,"SendEther"); }); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); + var vault = await avatar.vault(); + var avatarBalance = await web3.eth.getBalance(vault)/web3.utils.toWei('1', "ether"); assert.equal(avatarBalance, 0); - var otherAvatarBalance = await web3.eth.getBalance(otherAvatar.address)/web3.utils.toWei('1', "ether"); + var otherVault = await otherAvatar.vault(); + var otherAvatarBalance = await web3.eth.getBalance(otherVault)/web3.utils.toWei('1', "ether"); assert.equal(otherAvatarBalance, 1); }); @@ -497,7 +501,8 @@ contract('Controller', accounts => { it("globalConstraints sendEther add & remove", async () => { controller = await setup(accounts); var globalConstraints = await constraint("sendEther"); - let otherAvatar = await Avatar.new('otheravatar', helpers.NULL_ADDRESS, avatar.address); + let otherAvatar = await Avatar.new(); + await otherAvatar.initialize('otheravatar', helpers.NULL_ADDRESS, avatar.address,accounts[0]); await avatar.transferOwnership(controller.address); web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); @@ -520,9 +525,11 @@ contract('Controller', accounts => { .then(function(events){ assert.equal(events[0].event,"SendEther"); }); - var avatarBalance = await web3.eth.getBalance(avatar.address)/web3.utils.toWei('1', "ether"); + var vault = await avatar.vault(); + var avatarBalance = await web3.eth.getBalance(vault)/web3.utils.toWei('1', "ether"); assert.equal(avatarBalance, 0); - var otherAvatarBalance = await web3.eth.getBalance(otherAvatar.address)/web3.utils.toWei('1', "ether"); + var otherVault = await otherAvatar.vault(); + var otherAvatarBalance = await web3.eth.getBalance(otherVault)/web3.utils.toWei('1', "ether"); assert.equal(otherAvatarBalance, 1); }); diff --git a/test/helpers.js b/test/helpers.js index b18ed3ab..1364f5a8 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -16,6 +16,8 @@ const Package = artifacts.require("./Package.sol"); var ImplementationDirectory = artifacts.require("./ImplementationDirectory.sol"); var Controller = artifacts.require("./Controller.sol"); const ContributionReward = artifacts.require("./ContributionReward.sol"); +const Competition = artifacts.require("./Competition.sol"); +const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); export const MAX_UINT_256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; export const NULL_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; @@ -145,6 +147,8 @@ export const registrationAddVersionToPackege = async function (registration,vers registration.schemeMock = await SchemeMock.new(); registration.wallet = await Wallet.new(); registration.contributionReward = await ContributionReward.new(); + registration.competition = await Competition.new(); + registration.contributionRewardExt = await ContributionRewardExt.new(); await implementationDirectory.setImplementation("DAOToken",registration.daoToken.address); await implementationDirectory.setImplementation("Reputation",registration.reputation.address); await implementationDirectory.setImplementation("Avatar",registration.avatar.address); @@ -152,6 +156,8 @@ export const registrationAddVersionToPackege = async function (registration,vers await implementationDirectory.setImplementation("SchemeMock",registration.schemeMock.address); await implementationDirectory.setImplementation("Wallet",registration.wallet.address); await implementationDirectory.setImplementation("ContributionReward",registration.contributionReward.address); + await implementationDirectory.setImplementation("Competition",registration.competition.address); + await implementationDirectory.setImplementation("ContributionRewardExt",registration.contributionRewardExt.address); return registration; }; @@ -161,7 +167,7 @@ export const registerImplementation = async function (version = [0,1,0]) { registration.app = await App.new(); registration = await registrationAddVersionToPackege(registration,version); registration.daoFactory = await DAOFactory.new({gas:constants.ARC_GAS_LIMIT}); - registration.daoFactory.initialize(registration.app.address); + await registration.daoFactory.initialize(registration.app.address); return registration; }; diff --git a/truffle.js b/truffle.js index 61804b88..7d6bd79b 100644 --- a/truffle.js +++ b/truffle.js @@ -56,7 +56,7 @@ module.exports = { }, compilers: { solc: { - version: "0.5.13", // Fetch exact version from solc-bin (default: truffle's version) + version: "0.5.16", // Fetch exact version from solc-bin (default: truffle's version) // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) optimizer: { enabled: true, From 8f6696e5f8a3778c61bb9b77baa0068d2f7e01ba Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Sun, 1 Mar 2020 21:42:03 +0200 Subject: [PATCH 2/7] update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index ca5e9f40..f730a6f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3844,8 +3844,8 @@ } }, "ethereumjs-wallet": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.5.16.tgz", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz", "integrity": "sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w==", "requires": { "aes-js": "^3.1.1", From 4338cf0b4671e592f1378f4d74353928ad4cc914 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Sun, 1 Mar 2020 22:42:54 +0200 Subject: [PATCH 3/7] fix test --- package.json | 2 +- test/avatar.js | 1 - test/constants.js | 2 +- test/helpers.js | 6 ++++ test/schemeregistrar.js | 67 ++++++++++++++++++++++++++--------------- 5 files changed, 50 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 1ce9f536..404d1d3b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "tsconfig.json" ], "config": { - "gasLimit": "7100000" + "gasLimit": "7200000" }, "scripts": { "test": "cross-conf-env run-with-ganache --ganache-cmd 'npm run ganache' 'npm run truffle compile && npm run truffle migrate && npm run truffle test'", diff --git a/test/avatar.js b/test/avatar.js index 90df196a..52fc3610 100644 --- a/test/avatar.js +++ b/test/avatar.js @@ -38,7 +38,6 @@ contract('Avatar', accounts => { let b = actionMock.address; let c = "0x1234"; await web3.eth.sendTransaction({from:accounts[0],to:avatar.address, value: web3.utils.toWei('1', "ether")}); - var vault = await avatar.vault(); var result = await scheme.genericCallDirect.call(avatar.address,actionMock.address,a,b,c,100); assert.equal(result[1],a*2); await scheme.genericCallDirect(avatar.address,actionMock.address,a,b,c,100); diff --git a/test/constants.js b/test/constants.js index 499b08e6..f7a5ef70 100644 --- a/test/constants.js +++ b/test/constants.js @@ -1,3 +1,3 @@ -const ARC_GAS_LIMIT = 7100000; +const ARC_GAS_LIMIT = 7200000; module.exports = { ARC_GAS_LIMIT }; diff --git a/test/helpers.js b/test/helpers.js index 1364f5a8..486eee7f 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -18,6 +18,7 @@ var Controller = artifacts.require("./Controller.sol"); const ContributionReward = artifacts.require("./ContributionReward.sol"); const Competition = artifacts.require("./Competition.sol"); const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); +const SchemeRegistrar = artifacts.require("./SchemeRegistrar.sol"); export const MAX_UINT_256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; export const NULL_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; @@ -149,6 +150,7 @@ export const registrationAddVersionToPackege = async function (registration,vers registration.contributionReward = await ContributionReward.new(); registration.competition = await Competition.new(); registration.contributionRewardExt = await ContributionRewardExt.new(); + registration.schemeRegistrar = await SchemeRegistrar.new(); await implementationDirectory.setImplementation("DAOToken",registration.daoToken.address); await implementationDirectory.setImplementation("Reputation",registration.reputation.address); await implementationDirectory.setImplementation("Avatar",registration.avatar.address); @@ -158,6 +160,8 @@ export const registrationAddVersionToPackege = async function (registration,vers await implementationDirectory.setImplementation("ContributionReward",registration.contributionReward.address); await implementationDirectory.setImplementation("Competition",registration.competition.address); await implementationDirectory.setImplementation("ContributionRewardExt",registration.contributionRewardExt.address); + await implementationDirectory.setImplementation("SchemeRegistrar",registration.schemeRegistrar.address); + return registration; }; @@ -231,7 +235,9 @@ export const setupGenesisProtocol = async function ( export const setupOrganizationWithArrays = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,cap=0) { var org = new Organization(); + console.log("a") var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",daoCreatorOwner,founderToken,founderReputation,cap,{gas: constants.ARC_GAS_LIMIT}); + console.log("b") assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewOrg"); var avatarAddress = tx.logs[0].args._avatar; diff --git a/test/schemeregistrar.js b/test/schemeregistrar.js index f807ef30..2e0c0373 100644 --- a/test/schemeregistrar.js +++ b/test/schemeregistrar.js @@ -1,51 +1,67 @@ import * as helpers from './helpers'; -const constants = require('./constants'); const SchemeRegistrar = artifacts.require("./SchemeRegistrar.sol"); const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); -const DaoCreator = artifacts.require("./DaoCreator.sol"); const SchemeMock = artifacts.require('./SchemeMock.sol'); const Controller = artifacts.require('./Controller.sol'); -const ControllerCreator = artifacts.require("./ControllerCreator.sol"); - - export class SchemeRegistrarParams { constructor() { } } +var registration; const setupSchemeRegistrarParams = async function( - schemeRegistrar, avatarAddress ) { var schemeRegistrarParams = new SchemeRegistrarParams(); - schemeRegistrarParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50,schemeRegistrar.address); - await schemeRegistrar.initialize(avatarAddress,schemeRegistrarParams.votingMachine.absoluteVote.address,schemeRegistrarParams.votingMachine.params,schemeRegistrarParams.votingMachine.params); + + schemeRegistrarParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); + schemeRegistrarParams.initdata = await new web3.eth.Contract(registration.schemeRegistrar.abi) + .methods + .initialize(avatarAddress, + schemeRegistrarParams.votingMachine.absoluteVote.address, + schemeRegistrarParams.votingMachine.params, + schemeRegistrarParams.votingMachine.params) + .encodeABI(); return schemeRegistrarParams; }; const setup = async function (accounts) { - var testSetup = new helpers.TestSetup(); - testSetup.fee = 10; - testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); - testSetup.schemeRegistrar = await SchemeRegistrar.new(); - var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); - - testSetup.daoCreator = await DaoCreator.new(controllerCreator.address,{gas:constants.ARC_GAS_LIMIT}); - testSetup.reputationArray = [20,40,70]; - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],accounts[2]],[1000,0,0],testSetup.reputationArray); - testSetup.schemeRegistrarParams= await setupSchemeRegistrarParams(testSetup.schemeRegistrar,testSetup.org.avatar.address); - var permissions = "0x0000001F"; - await testSetup.daoCreator.setSchemes(testSetup.org.avatar.address,[testSetup.schemeRegistrar.address],[permissions],"metaData"); - - return testSetup; + var testSetup = new helpers.TestSetup(); + testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); + registration = await helpers.registerImplementation(); + testSetup.reputationArray = [2000,4000,7000]; + testSetup.proxyAdmin = accounts[5]; + testSetup.org = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, + accounts, + registration, + [accounts[0], + accounts[1], + accounts[2]], + [1000,0,0], + testSetup.reputationArray); + testSetup.schemeRegistrarParams= await setupSchemeRegistrarParams( + testSetup.org.avatar.address); + + var permissions = "0x0000001f"; + var tx = await registration.daoFactory.setSchemes( + testSetup.org.avatar.address, + [web3.utils.fromAscii("SchemeRegistrar")], + testSetup.schemeRegistrarParams.initdata, + [helpers.getBytesLength(testSetup.schemeRegistrarParams.initdata)], + [permissions], + "metaData",{from:testSetup.proxyAdmin}); + + testSetup.schemeRegistrar = await SchemeRegistrar.at(tx.logs[1].args._scheme); + return testSetup; }; contract('SchemeRegistrar', accounts => { it("initialize", async() => { - var schemeRegistrar = await SchemeRegistrar.new(); - var params = await setupSchemeRegistrarParams(schemeRegistrar,helpers.SOME_ADDRESS); - assert.equal(await schemeRegistrar.votingMachine(),params.votingMachine.absoluteVote.address); + var testSetup = await setup(accounts); + assert.equal(await testSetup.schemeRegistrar.votingMachine(), + testSetup.schemeRegistrarParams.votingMachine.absoluteVote.address); + assert.equal(await testSetup.schemeRegistrar.avatar(),testSetup.org.avatar.address); }); it("proposeScheme log", async function() { @@ -74,6 +90,7 @@ contract('SchemeRegistrar', accounts => { var testSetup = await setup(accounts); var universalScheme = await SchemeMock.new(); var tx = await testSetup.schemeRegistrar.proposeScheme(universalScheme.address,"0x00000000",helpers.NULL_HASH); + //Vote with reputation to trigger execution var proposalId = await helpers.getValueFromLogs(tx, '_proposalId',1); await testSetup.schemeRegistrarParams.votingMachine.absoluteVote.vote(proposalId,1,0,helpers.NULL_ADDRESS,{from:accounts[2]}); From 3ac7f37fabb0fb2748356fa5ca51e0c4fd2927f6 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Sun, 1 Mar 2020 22:45:23 +0200 Subject: [PATCH 4/7] lint --- test/helpers.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/helpers.js b/test/helpers.js index 486eee7f..7b1e7e80 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -235,9 +235,7 @@ export const setupGenesisProtocol = async function ( export const setupOrganizationWithArrays = async function (daoCreator,daoCreatorOwner,founderToken,founderReputation,cap=0) { var org = new Organization(); - console.log("a") var tx = await daoCreator.forgeOrg("testOrg","TEST","TST",daoCreatorOwner,founderToken,founderReputation,cap,{gas: constants.ARC_GAS_LIMIT}); - console.log("b") assert.equal(tx.logs.length, 1); assert.equal(tx.logs[0].event, "NewOrg"); var avatarAddress = tx.logs[0].args._avatar; From 376ba94e250feae174c9afcfddcaf6135e9f3183 Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Mon, 2 Mar 2020 15:05:13 +0200 Subject: [PATCH 5/7] genericScheme test use daofactory --- test/genericscheme.js | 109 ++++++++++++++++++++++++------------------ test/helpers.js | 4 ++ 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/test/genericscheme.js b/test/genericscheme.js index a66b9214..d7b73ebc 100644 --- a/test/genericscheme.js +++ b/test/genericscheme.js @@ -1,68 +1,85 @@ import * as helpers from './helpers'; -const constants = require('./constants'); const GenericScheme = artifacts.require('./GenericScheme.sol'); -const DaoCreator = artifacts.require("./DaoCreator.sol"); -const ControllerCreator = artifacts.require("./ControllerCreator.sol"); - const ERC20Mock = artifacts.require("./ERC20Mock.sol"); const ActionMock = artifacts.require("./ActionMock.sol"); const Wallet = artifacts.require("./Wallet.sol"); + export class GenericSchemeParams { constructor() { } } +var registration; const setupGenericSchemeParams = async function( - genericScheme, - accounts, - contractToCall, - genesisProtocol = false, - tokenAddress = 0, - avatar + accounts, + genesisProtocol, + token, + avatarAddress, + contractToCall ) { var genericSchemeParams = new GenericSchemeParams(); - if (genesisProtocol === true){ - genericSchemeParams.votingMachine = await helpers.setupGenesisProtocol(accounts,tokenAddress,helpers.NULL_ADDRESS); - await genericScheme.initialize( - avatar.address, - genericSchemeParams.votingMachine.genesisProtocol.address, - genericSchemeParams.votingMachine.params, - contractToCall); - } - else { - genericSchemeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50,genericScheme.address); - await genericScheme.initialize( - avatar.address, - genericSchemeParams.votingMachine.absoluteVote.address, - genericSchemeParams.votingMachine.params, - contractToCall); + + if (genesisProtocol === true) { + genericSchemeParams.votingMachine = await helpers.setupGenesisProtocol(accounts,token,helpers.NULL_ADDRESS); + genericSchemeParams.initdata = await new web3.eth.Contract(registration.genericScheme.abi) + .methods + .initialize(avatarAddress, + genericSchemeParams.votingMachine.genesisProtocol.address, + genericSchemeParams.votingMachine.params, + contractToCall) + .encodeABI(); + } else { + genericSchemeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); + genericSchemeParams.initdata = await new web3.eth.Contract(registration.genericScheme.abi) + .methods + .initialize(avatarAddress, + genericSchemeParams.votingMachine.absoluteVote.address, + genericSchemeParams.votingMachine.params, + contractToCall) + .encodeABI(); } return genericSchemeParams; }; const setup = async function (accounts,contractToCall = 0,reputationAccount=0,genesisProtocol = false,tokenAddress=0) { - var testSetup = new helpers.TestSetup(); - testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); - testSetup.genericScheme = await GenericScheme.new(); - var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); - - testSetup.daoCreator = await DaoCreator.new(controllerCreator.address,{gas:constants.ARC_GAS_LIMIT}); - testSetup.reputationArray = [20,10,70]; - if (reputationAccount === 0) { - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],accounts[2]],[1000,1000,1000],testSetup.reputationArray); - } else { - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],reputationAccount],[1000,1000,1000],testSetup.reputationArray); - } - testSetup.genericSchemeParams= await setupGenericSchemeParams(testSetup.genericScheme,accounts,contractToCall,genesisProtocol,tokenAddress,testSetup.org.avatar); - var permissions = "0x00000010"; - - - await testSetup.daoCreator.setSchemes(testSetup.org.avatar.address, - [testSetup.genericScheme.address], - [permissions],"metaData"); - - return testSetup; + var testSetup = new helpers.TestSetup(); + testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); + registration = await helpers.registerImplementation(); + testSetup.reputationArray = [20,10,70]; + var account2; + if (reputationAccount === 0) { + account2 = accounts[2]; + } else { + account2 = reputationAccount; + } + testSetup.proxyAdmin = accounts[5]; + testSetup.org = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, + accounts, + registration, + [accounts[0], + accounts[1], + account2], + [1000,0,0], + testSetup.reputationArray); + testSetup.genericSchemeParams= await setupGenericSchemeParams( + accounts, + genesisProtocol, + tokenAddress, + testSetup.org.avatar.address, + contractToCall + ); + + var permissions = "0x0000001f"; + var tx = await registration.daoFactory.setSchemes( + testSetup.org.avatar.address, + [web3.utils.fromAscii("GenericScheme")], + testSetup.genericSchemeParams.initdata, + [helpers.getBytesLength(testSetup.genericSchemeParams.initdata)], + [permissions], + "metaData",{from:testSetup.proxyAdmin}); + testSetup.genericScheme = await GenericScheme.at(tx.logs[1].args._scheme); + return testSetup; }; const createCallToActionMock = async function(_avatar,_actionMock) { diff --git a/test/helpers.js b/test/helpers.js index 7b1e7e80..277e5c89 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -19,6 +19,7 @@ const ContributionReward = artifacts.require("./ContributionReward.sol"); const Competition = artifacts.require("./Competition.sol"); const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); const SchemeRegistrar = artifacts.require("./SchemeRegistrar.sol"); +const GenericScheme = artifacts.require("./GenericScheme.sol"); export const MAX_UINT_256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; export const NULL_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; @@ -151,6 +152,7 @@ export const registrationAddVersionToPackege = async function (registration,vers registration.competition = await Competition.new(); registration.contributionRewardExt = await ContributionRewardExt.new(); registration.schemeRegistrar = await SchemeRegistrar.new(); + registration.genericScheme = await GenericScheme.new(); await implementationDirectory.setImplementation("DAOToken",registration.daoToken.address); await implementationDirectory.setImplementation("Reputation",registration.reputation.address); await implementationDirectory.setImplementation("Avatar",registration.avatar.address); @@ -161,6 +163,8 @@ export const registrationAddVersionToPackege = async function (registration,vers await implementationDirectory.setImplementation("Competition",registration.competition.address); await implementationDirectory.setImplementation("ContributionRewardExt",registration.contributionRewardExt.address); await implementationDirectory.setImplementation("SchemeRegistrar",registration.schemeRegistrar.address); + await implementationDirectory.setImplementation("GenericScheme",registration.genericScheme.address); + return registration; }; From 6132d58b6922d25ef03367ffdc591c5787e6614a Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Mon, 2 Mar 2020 15:33:02 +0200 Subject: [PATCH 6/7] upgradeScheme use daofactory --- test/helpers.js | 4 +++ test/upgradescheme.js | 67 +++++++++++++++++++++++-------------------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/test/helpers.js b/test/helpers.js index 277e5c89..b602eda5 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -20,6 +20,7 @@ const Competition = artifacts.require("./Competition.sol"); const ContributionRewardExt = artifacts.require("./ContributionRewardExt.sol"); const SchemeRegistrar = artifacts.require("./SchemeRegistrar.sol"); const GenericScheme = artifacts.require("./GenericScheme.sol"); +const UpgradeScheme = artifacts.require("./UpgradeScheme.sol"); export const MAX_UINT_256 = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; export const NULL_HASH = '0x0000000000000000000000000000000000000000000000000000000000000000'; @@ -153,6 +154,7 @@ export const registrationAddVersionToPackege = async function (registration,vers registration.contributionRewardExt = await ContributionRewardExt.new(); registration.schemeRegistrar = await SchemeRegistrar.new(); registration.genericScheme = await GenericScheme.new(); + registration.upgradeScheme = await UpgradeScheme.new(); await implementationDirectory.setImplementation("DAOToken",registration.daoToken.address); await implementationDirectory.setImplementation("Reputation",registration.reputation.address); await implementationDirectory.setImplementation("Avatar",registration.avatar.address); @@ -164,6 +166,8 @@ export const registrationAddVersionToPackege = async function (registration,vers await implementationDirectory.setImplementation("ContributionRewardExt",registration.contributionRewardExt.address); await implementationDirectory.setImplementation("SchemeRegistrar",registration.schemeRegistrar.address); await implementationDirectory.setImplementation("GenericScheme",registration.genericScheme.address); + await implementationDirectory.setImplementation("UpgradeScheme",registration.upgradeScheme.address); + return registration; diff --git a/test/upgradescheme.js b/test/upgradescheme.js index b16960ff..d5687385 100644 --- a/test/upgradescheme.js +++ b/test/upgradescheme.js @@ -4,31 +4,28 @@ const Controller = artifacts.require("./Controller.sol"); const AbsoluteVote = artifacts.require('./AbsoluteVote.sol'); const UpgradeScheme = artifacts.require('./UpgradeScheme.sol'); const ERC20Mock = artifacts.require('./test/ERC20Mock.sol'); -const DaoCreator = artifacts.require("./DaoCreator.sol"); const Avatar = artifacts.require("./Avatar.sol"); const DAOToken = artifacts.require("./DAOToken.sol"); const Reputation = artifacts.require("./Reputation.sol"); -const ControllerCreator = artifacts.require("./ControllerCreator.sol"); - - - export class UpgradeSchemeParams { constructor() { } } - +var registration; const setupUpgradeSchemeParams = async function( - upgradeScheme, avatarAddress ) { - var upgradeSchemeParams = new UpgradeSchemeParams(); - upgradeSchemeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50,upgradeScheme.address); - await upgradeScheme.initialize(avatarAddress, - upgradeSchemeParams.votingMachine.absoluteVote.address, - upgradeSchemeParams.votingMachine.params); - upgradeSchemeParams.paramsHash = helpers.NULL_HASH; - return upgradeSchemeParams; + var upgradeSchemeParams = new UpgradeSchemeParams(); + + upgradeSchemeParams.votingMachine = await helpers.setupAbsoluteVote(helpers.NULL_ADDRESS,50); + upgradeSchemeParams.initdata = await new web3.eth.Contract(registration.upgradeScheme.abi) + .methods + .initialize(avatarAddress, + upgradeSchemeParams.votingMachine.absoluteVote.address, + upgradeSchemeParams.votingMachine.params) + .encodeABI(); + return upgradeSchemeParams; }; @@ -56,24 +53,32 @@ const setupNewController = async function (accounts,permission='0x00000000') { const setup = async function (accounts) { - var testSetup = new helpers.TestSetup(); - testSetup.fee = 10; - testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); - testSetup.upgradeScheme = await UpgradeScheme.new(); - var controllerCreator = await ControllerCreator.new({gas: constants.ARC_GAS_LIMIT}); - - testSetup.daoCreator = await DaoCreator.new(controllerCreator.address,{gas:constants.ARC_GAS_LIMIT}); - testSetup.reputationArray = [20,40,70]; - testSetup.org = await helpers.setupOrganizationWithArrays(testSetup.daoCreator,[accounts[0],accounts[1],accounts[2]],[1000,0,0],testSetup.reputationArray); - testSetup.upgradeSchemeParams= await setupUpgradeSchemeParams(testSetup.upgradeScheme,testSetup.org.avatar.address); - - var permissions = "0x0000000a"; - - await testSetup.daoCreator.setSchemes(testSetup.org.avatar.address,[testSetup.upgradeScheme.address],[permissions],"metaData"); - - return testSetup; + var testSetup = new helpers.TestSetup(); + testSetup.standardTokenMock = await ERC20Mock.new(accounts[1],100); + registration = await helpers.registerImplementation(); + testSetup.reputationArray = [20,40,70]; + testSetup.proxyAdmin = accounts[5]; + testSetup.org = await helpers.setupOrganizationWithArraysDAOFactory(testSetup.proxyAdmin, + accounts, + registration, + [accounts[0], + accounts[1], + accounts[2]], + [1000,0,0], + testSetup.reputationArray); + testSetup.upgradeSchemeParams= await setupUpgradeSchemeParams( + testSetup.org.avatar.address); + var permissions = "0x0000000a"; + var tx = await registration.daoFactory.setSchemes( + testSetup.org.avatar.address, + [web3.utils.fromAscii("UpgradeScheme")], + testSetup.upgradeSchemeParams.initdata, + [helpers.getBytesLength(testSetup.upgradeSchemeParams.initdata)], + [permissions], + "metaData",{from:testSetup.proxyAdmin}); + testSetup.upgradeScheme = await UpgradeScheme.at(tx.logs[1].args._scheme); + return testSetup; }; - contract('UpgradeScheme', accounts => { before(function() { helpers.etherForEveryone(accounts); From 00a813d57d30d6f7754881ff9e9cda097edbf95e Mon Sep 17 00:00:00 2001 From: Oren Sokolowsky Date: Mon, 2 Mar 2020 21:16:20 +0200 Subject: [PATCH 7/7] bump v to 0.1.1-rc.4 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f730a6f9..0290cc93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@daostack/arc-experimental", - "version": "0.1.1-rc.3", + "version": "0.1.1-rc.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -5897,9 +5897,9 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-Z2EICWNJou7Tr9Bd2M2UqDJq3A9F2ePG9w3lIpjoyuSyXFP9QbniJVu3XQYytuw5ebmG7dXSXO9PgAjJG8DDKA==" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" }, "http-errors": { "version": "1.7.2", @@ -7354,9 +7354,9 @@ "dev": true }, "needle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.2.tgz", - "integrity": "sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.3.3.tgz", + "integrity": "sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==", "dev": true, "requires": { "debug": "^3.2.6", diff --git a/package.json b/package.json index 404d1d3b..08ff1c12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@daostack/arc-experimental", - "version": "0.1.1-rc.3", + "version": "0.1.1-rc.4", "description": "A platform for building DAOs", "files": [ "contracts/",