From a9ebdbb53e2eb583752a9aa9cdcfaaf77d6daab3 Mon Sep 17 00:00:00 2001 From: zjubfd <296179868@qq.com> Date: Wed, 6 Apr 2022 11:44:24 +0800 Subject: [PATCH 01/48] Update init_holders.js --- init_holders.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init_holders.js b/init_holders.js index 8f4351bd..d2674baa 100644 --- a/init_holders.js +++ b/init_holders.js @@ -3,7 +3,7 @@ const init_holders = [ { // private key is 0x9b28f36fbd67381120752d6172ecdcf10e06ab2d9a1367aac00cdcd6ac7855d3, only use in dev address: "0x9fB29AAc15b9A4B7F17c3385939b007540f4d791", - balance: web3.utils.toBN("10000000000000000000000").toString("hex") + balance: web3.utils.toBN("10000000000000000000000000").toString("hex") } // { // address: "0x6c468CF8c9879006E22EC4029696E005C2319C9D", From db8bb560ac5a1265c685b719c7e976dced162310 Mon Sep 17 00:00:00 2001 From: Ethan Hu Date: Thu, 28 Apr 2022 18:06:59 +0800 Subject: [PATCH 02/48] Implement bep-127 and bep-131 (#131) (#138) * Implement bep-127 and bep-131 (#131) * [R4R]: new implement of BEP-127 (#3) * feat: new implement of bep-127 and test * fix: review comments * fix: add re-init for validatorExtraSet * fix: template file sync * fix: validatorExtraSet should init at the same time as `maxNumOfMaintaining` init * modify config * fix: maintainInfo leak at next 24-hours * chores: add comment * fix: `isCurrentValidator` error before `validatorExtraSet` init * chore * test: add test case for BSCValidatorSet * test: add view test case for BSCValidatorSet * chore: modify comments * fix: numOfMaintaining modification on edge case * fix: review comments * test: add code size log * chore: optimize new ValidatorExtra * fix: numOfMaintaining edge case * fix: add exitMaintenance event * fix: add exitMaintenance event * chore * fix: remove unused code * chore * implement bep-131 * update ut * update logic of felony function * update the getMiningValidators function * update logic of the update maxNumOfCandidates function * fix calculating epoch number * update _exitMaintenance * fix comments * update readme * fix testcase on slash and validator contract * fix update maxNumOfMaintaining * fix: bug that validatorSet order was changed incorrectly while _felony in _forceMaintainingValidatorsExit, using numOfCabinets not init * feat: modify slots number * chore: rename var in loop * Fix audit report of BEP-127 and BEP-131 (#17) * fix: issue #BSC-007, add more comment to explain `enterMaintenanceHeight` check * fix: issue #BSC-001 and #BSC-002, #BSC-003, improve code to save gas * fix: issue #BSC-008, add comment to explain this * feat: sync template code with origin code * feat: rename len to validatorsNum * chore: modify comment for check * chore: sync template code * chore: add more comments to explain `24-hour period` * fix: k = 0 => k * fix: j = 0 => j * feat: sync template code for SlashIndicator.template Co-authored-by: gothery001 * fix: Bug fix that incorrectly modification of fixing audit report (#18) * fix: incorrectly modified `initValidatorExtraSet` * chore: sync template code Co-authored-by: gothery001 * fix: bug that slash count calculation problem while update validator set (#19) * feat: add more test case to test slashCount calc problem * fix: fix workValidatorCount calc incorrectly changed while updateValidatorSet * chores: sync tmeplate code * feat: add generate-qa script * feat: close gas report as default * feat: modify tests * chores: add more comments * chores: add more comments Co-authored-by: gothery001 Co-authored-by: dean65 Co-authored-by: dean <97718205+dean65@users.noreply.github.com> Co-authored-by: realuncle Co-authored-by: realuncle <90668111+realuncle@users.noreply.github.com> Co-authored-by: realuncle Co-authored-by: gothery001 * chore: modify generate script line in package.json (#139) * chore: modify generate script line in package.json, generate latest genesis.json for mainnet * chore: modify readme Co-authored-by: cosinlink Co-authored-by: Gothery <90246878+gothery001@users.noreply.github.com> Co-authored-by: dean65 Co-authored-by: dean <97718205+dean65@users.noreply.github.com> Co-authored-by: realuncle Co-authored-by: realuncle <90668111+realuncle@users.noreply.github.com> Co-authored-by: realuncle --- .gitignore | 11 +- .prettierignore | 3 + .prettierrc | 16 + README.md | 14 +- contracts/BSCValidatorSet.sol | 472 +- contracts/BSCValidatorSet.template | 494 +- contracts/SlashIndicator.sol | 15 +- contracts/SlashIndicator.template | 15 +- contracts/interface/IBSCValidatorSet.sol | 3 +- contracts/interface/ISlashIndicator.sol | 4 +- genesis.json | 22 +- hardhat.config.ts | 66 + package.json | 44 +- test/BSCValidatorSet.js | 130 + test/Slash.js | 144 +- test/test-maintenance/BSCValidatorSet.spec.ts | 784 ++ test/test-maintenance/helper.ts | 97 + tsconfig.json | 13 + yarn.lock | 10826 ++++++++++++++++ 19 files changed, 12938 insertions(+), 235 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 hardhat.config.ts create mode 100644 test/test-maintenance/BSCValidatorSet.spec.ts create mode 100644 test/test-maintenance/helper.ts create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index d0bf13c1..ba50d26e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,13 @@ build/ pids logs .idea/ -contracts/flattened/*.sol \ No newline at end of file +contracts/flattened/*.sol + +#Hardhat files +cache +artifacts + +.env + +types +typechain-types diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..ba025543 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +artifacts +cache +node_modules diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..2caa9822 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "printWidth": 100, + "trailingComma": "es5", + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "overrides": [ + { + "files": "*.sol", + "options": { + "semi": true, + "printWidth": 100 + } + } + ] +} diff --git a/README.md b/README.md index f10b0dae..dfe2f3ca 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,12 @@ Install dependency: npm install ``` +Node: v12.18.3 +Truffle: Truffle v5.1.31 +Solc: 0.6.4+commit.1dca32f3.Darwin.appleclang +Ganache-cli: v6.10.1 + + ## unit test Generate contracts for testing: @@ -27,7 +33,7 @@ node generate-relayerincentivizecontract.js --roundSize 30 --maximumWeight 3 --m Start ganache: ```shell script -ganache-cli --mnemonic 'clock radar mass judge dismiss just intact mind resemble fringe diary casino' --gasLimit 13000000 -e 10000 +ganache-cli --mnemonic 'clock radar mass judge dismiss just intact mind resemble fringe diary casino' --gasLimit 100000000 -e 10000 --allowUnlimitedContractSize ``` Run truffle test: @@ -37,6 +43,12 @@ truffle migrate truffle test ``` +Run hardhat test: +```shell script +npx hardhat compile +npx hardhat test +``` + Flatten all system contracts: ```shell script npm run flatten diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index a1ca3c17..e625c318 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -39,6 +39,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint32 public constant ERROR_LEN_OF_VAL_MISMATCH = 103; uint32 public constant ERROR_RELAYFEE_TOO_LARGE = 104; + uint256 public constant INIT_NUM_OF_CABINETS = 21; + uint256 public constant EPOCH = 200; /*********************** state of the contract **************************/ Validator[] public currentValidatorSet; @@ -56,6 +58,22 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public burnRatio; bool public burnRatioInitialized; + // BEP-127 Temporary Maintenance + uint256 public constant INIT_MAX_NUM_OF_MAINTAINING = 3; + uint256 public constant INIT_MAINTAIN_SLASH_SCALE = 2; + + uint256 public maxNumOfMaintaining; + uint256 public numOfMaintaining; + uint256 public maintainSlashScale; + + // Corresponds strictly to currentValidatorSet + // validatorExtraSet[index] = the `ValidatorExtra` info of currentValidatorSet[index] + ValidatorExtra[] public validatorExtraSet; + // BEP-131 candidate validator + uint256 public numOfCabinets; + uint256 public maxNumOfCandidates; + uint256 public maxNumOfWorkingCandidates; + struct Validator{ address consensusAddress; address payable feeAddress; @@ -67,6 +85,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 incoming; } + struct ValidatorExtra { + // BEP-127 Temporary Maintenance + uint256 enterMaintenanceHeight; // the height from where the validator enters Maintenance + bool isMaintaining; + + // reserve for future use + uint256[20] slots; + } + /*********************** cross chain package **************************/ struct IbcValidatorSetPackage { uint8 packageType; @@ -79,6 +106,19 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica _; } + modifier initValidatorExtraSet() { + if (validatorExtraSet.length == 0) { + ValidatorExtra memory validatorExtra; + // init validatorExtraSet + uint256 validatorsNum = currentValidatorSet.length; + for (uint i; i < validatorsNum; ++i) { + validatorExtraSet.push(validatorExtra); + } + } + + _; + } + /*********************** events **************************/ event validatorSetUpdated(); event validatorJailed(address indexed validator); @@ -97,12 +137,14 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event unexpectedPackage(uint8 channelId, bytes msgBytes); event paramChange(string key, bytes value); event feeBurned(uint256 amount); + event validatorEnterMaintenance(address indexed validator); + event validatorExitMaintenance(address indexed validator); /*********************** init **************************/ function init() external onlyNotInit{ (IbcValidatorSetPackage memory validatorSetPkg, bool valid)= decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); require(valid, "failed to parse init validatorSet"); - for (uint i = 0;i= DUSTY_INCOMING) { crossSize ++; } else if (currentValidatorSet[i].incoming > 0) { @@ -230,13 +281,12 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256[] memory directAmounts = new uint256[](directSize); crossSize = 0; directSize = 0; - Validator[] memory validatorSetTemp = validatorSet; // fix error: stack too deep, try removing local variables uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); if (relayFee > DUSTY_INCOMING) { emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); return ERROR_RELAYFEE_TOO_LARGE; } - for (uint i = 0;i= DUSTY_INCOMING) { crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; @@ -271,7 +321,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } if (failCross) { - for (uint i = 0; i< crossIndexes.length;i++) { + for (uint i; i< crossIndexes.length;++i) { uint idx = crossIndexes[i]; bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); if (success) { @@ -284,7 +334,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // step 3: direct transfer if (directAddrs.length>0) { - for (uint i = 0;i 0) { + uint256 epochNumber = block.number / EPOCH; + shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length-_numOfCabinets+_maxNumOfWorkingCandidates); + } + address[] memory miningValidators = new address[](_numOfCabinets); + for (uint i; i<_numOfCabinets; ++i) { + miningValidators[i] = validators[i]; + } + return miningValidators; + } + + function getValidators() public view returns(address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; - for (uint i = 0;i= currentValidatorSet.length) { + return false; + } + + // validatorExtraSet[index] should not be used before it has been init. + if (index >= validatorExtraSet.length) { + return !currentValidatorSet[index].jailed; + } + + return !currentValidatorSet[index].jailed && !validatorExtraSet[index].isMaintaining; + } + function getIncoming(address validator)external view returns(uint256) { uint256 index = currentValidatorSetMap[validator]; if (index<=0) { @@ -339,65 +441,100 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return currentValidatorSet[index-1].incoming; } - /*********************** For slash **************************/ - function misdemeanor(address validator)external onlySlash override{ + function isCurrentValidator(address validator) external view override returns (bool) { uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { - return; + return false; } - // the actually index + + // the actual index index = index - 1; - uint256 income = currentValidatorSet[index].incoming; - currentValidatorSet[index].incoming = 0; - uint256 rest = currentValidatorSet.length - 1; - emit validatorMisdemeanor(validator,income); - if (rest==0) { - // should not happen, but still protect - return; + return isWorkingValidator(index); + } + + function getWorkingValidatorCount() public view returns(uint256 workingValidatorCount) { + workingValidatorCount = getValidators().length; + uint256 _numOfCabinets = numOfCabinets > 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; + if (workingValidatorCount > _numOfCabinets) { + workingValidatorCount = _numOfCabinets; } - uint256 averageDistribute = income/rest; - if (averageDistribute!=0) { - for (uint i=0;i 0, "only current validators"); + + // the actual index + return index - 1; + } + + function canEnterMaintenance(uint256 index) public view returns (bool) { + if (index >= currentValidatorSet.length) { + return false; } - currentValidatorSet.pop(); - uint256 averageDistribute = income/rest; - if (averageDistribute!=0) { - uint n = currentValidatorSet.length; - for (uint i=0;i= maxNumOfMaintaining // - 2. check if reached upper limit + || !isWorkingValidator(index) // - 3. check if not working(not jailed and not maintaining) + || validatorExtraSet[index].enterMaintenanceHeight > 0 // - 5. check if has Maintained during current 24-hour period + // current validators are selected every 24 hours(from 00:00:00 UTC to 23:59:59 UTC) + // for more details, refer to https://github.com/bnb-chain/docs-site/blob/master/docs/smart-chain/validator/Binance%20Smart%20Chain%20Validator%20FAQs%20-%20Updated.md + || getValidators().length <= 1 // - 6. check num of remaining working validators + ) { + return false; } - // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. + + return true; + } + + function enterMaintenance() external initValidatorExtraSet { + // check maintain config + if (maxNumOfMaintaining == 0) { + maxNumOfMaintaining = INIT_MAX_NUM_OF_MAINTAINING; + } + if (maintainSlashScale == 0) { + maintainSlashScale = INIT_MAINTAIN_SLASH_SCALE; + } + + uint256 index = getCurrentValidatorIndex(msg.sender); + require(canEnterMaintenance(index), "can not enter Temporary Maintenance"); + _enterMaintenance(msg.sender, index); + } + + function exitMaintenance() external { + uint256 index = getCurrentValidatorIndex(msg.sender); + + // jailed validators are allowed to exit maintenance + require(validatorExtraSet[index].isMaintaining, "not in maintenance"); + uint256 workingValidatorCount = getWorkingValidatorCount(); + _exitMaintenance(msg.sender, index, workingValidatorCount); } /*********************** Param update ********************************/ @@ -413,6 +550,38 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica require(newBurnRatio <= BURN_RATIO_SCALE, "the burnRatio must be no greater than 10000"); burnRatio = newBurnRatio; burnRatioInitialized = true; + } else if (Memory.compareStrings(key, "maxNumOfMaintaining")) { + require(value.length == 32, "length of maxNumOfMaintaining mismatch"); + uint256 newMaxNumOfMaintaining = BytesToTypes.bytesToUint256(32, value); + uint256 _numOfCabinets = numOfCabinets; + if (_numOfCabinets == 0) { + _numOfCabinets = INIT_NUM_OF_CABINETS; + } + require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCaninates"); + maxNumOfMaintaining = newMaxNumOfMaintaining; + } else if (Memory.compareStrings(key, "maintainSlashScale")) { + require(value.length == 32, "length of maintainSlashScale mismatch"); + uint256 newMaintainSlashScale = BytesToTypes.bytesToUint256(32, value); + require(newMaintainSlashScale > 0, "the maintainSlashScale must be greater than 0"); + maintainSlashScale = newMaintainSlashScale; + } else if (Memory.compareStrings(key, "maxNumOfWorkingCandidates")) { + require(value.length == 32, "length of maxNumOfWorkingCandidates mismatch"); + uint256 newMaxNumOfWorkingCandidates = BytesToTypes.bytesToUint256(32, value); + require(newMaxNumOfWorkingCandidates <= maxNumOfCandidates, "the maxNumOfWorkingCandidates must be not greater than maxNumOfCandidates"); + maxNumOfWorkingCandidates = newMaxNumOfWorkingCandidates; + } else if (Memory.compareStrings(key, "maxNumOfCandidates")) { + require(value.length == 32, "length of maxNumOfCandidates mismatch"); + uint256 newMaxNumOfCandidates = BytesToTypes.bytesToUint256(32, value); + maxNumOfCandidates = newMaxNumOfCandidates; + if (maxNumOfWorkingCandidates > maxNumOfCandidates) { + maxNumOfWorkingCandidates = maxNumOfCandidates; + } + } else if (Memory.compareStrings(key, "numOfCabinets")) { + require(value.length == 32, "length of numOfCabinets mismatch"); + uint256 newNumOfCabinets = BytesToTypes.bytesToUint256(32, value); + require(newNumOfCabinets > 0, "the numOfCabinets must be greater than 0"); + require(newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS"); + numOfCabinets = newNumOfCabinets; } else { require(false, "unknown param"); } @@ -425,8 +594,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (validatorSet.length > MAX_NUM_OF_VALIDATORS){ return (false, "the number of validators exceed the limit"); } - for (uint i = 0;im) { - for (uint i = m;in) { - for (uint i = n;i 0; --index) { + i = index - 1; // the actual index + if (!validatorExtraSet[i].isMaintaining) { + continue; + } + + // only maintaining validators + validator = currentValidatorSet[i].consensusAddress; + + // exit maintenance + isFelony = _exitMaintenance(validator, i, workingValidatorCount); + if (!isFelony || numOfFelony >= _validatorSet.length - 1) { + continue; + } + + // record the jailed validator in validatorSet + for (uint k; k < _validatorSet.length; ++k) { + if (_validatorSet[k].consensusAddress == validator) { + _validatorSet[k].jailed = true; + numOfFelony++; + break; + } + } + } + + // 2. get unjailed validators from validatorSet + unjailedValidatorSet = new Validator[](_validatorSet.length - numOfFelony); + i = 0; + for (uint index; index < _validatorSet.length; ++index) { + if (!_validatorSet[index].jailed) { + unjailedValidatorSet[i] = _validatorSet[index]; + i++; + } + } + + return unjailedValidatorSet; + } + + function _enterMaintenance(address validator, uint256 index) private { + numOfMaintaining++; + validatorExtraSet[index].isMaintaining = true; + validatorExtraSet[index].enterMaintenanceHeight = block.number; + emit validatorEnterMaintenance(validator); + } + + function _exitMaintenance(address validator, uint index, uint256 workingValidatorCount) private returns (bool isFelony){ + if (maintainSlashScale == 0 || workingValidatorCount == 0 || numOfMaintaining == 0) { + // should not happen, still protect + return false; + } + + // step 0: modify numOfMaintaining + numOfMaintaining--; + + // step 1: calculate slashCount + uint256 slashCount = + block.number + .sub(validatorExtraSet[index].enterMaintenanceHeight) + .div(workingValidatorCount) + .div(maintainSlashScale); + + // step 2: clear maintaining info of the validator + validatorExtraSet[index].isMaintaining = false; + + // step3: slash the validator + (uint256 misdemeanorThreshold, uint256 felonyThreshold) = ISlashIndicator(SLASH_CONTRACT_ADDR).getSlashThresholds(); + isFelony = false; + if (slashCount >= felonyThreshold) { + _felony(validator, index); + ISlashIndicator(SLASH_CONTRACT_ADDR).sendFelonyPackage(validator); + isFelony = true; + } else if (slashCount >= misdemeanorThreshold) { + _misdemeanor(validator); + } + + emit validatorExitMaintenance(validator); + } + //rlp encode & decode function function decodeValidatorSetSynPackage(bytes memory msgBytes) internal pure returns (IbcValidatorSetPackage memory, bool) { IbcValidatorSetPackage memory validatorSetPkg; @@ -492,7 +826,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (idx == 1) { RLPDecode.RLPItem[] memory items = iter.next().toList(); validatorSetPkg.validatorSet =new Validator[](items.length); - for (uint j = 0;j= DUSTY_INCOMING) { crossSize ++; } else if (currentValidatorSet[i].incoming > 0) { @@ -230,13 +281,12 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256[] memory directAmounts = new uint256[](directSize); crossSize = 0; directSize = 0; - Validator[] memory validatorSetTemp = validatorSet; // fix error: stack too deep, try removing local variables uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); if (relayFee > DUSTY_INCOMING) { emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); return ERROR_RELAYFEE_TOO_LARGE; } - for (uint i = 0;i= DUSTY_INCOMING) { crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; @@ -271,7 +321,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } if (failCross) { - for (uint i = 0; i< crossIndexes.length;i++) { + for (uint i; i< crossIndexes.length;++i) { uint idx = crossIndexes[i]; bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); if (success) { @@ -284,7 +334,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // step 3: direct transfer if (directAddrs.length>0) { - for (uint i = 0;i 0) { + uint256 epochNumber = block.number / EPOCH; + shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length-_numOfCabinets+_maxNumOfWorkingCandidates); + } + address[] memory miningValidators = new address[](_numOfCabinets); + for (uint i; i<_numOfCabinets; ++i) { + miningValidators[i] = validators[i]; + } + return miningValidators; + } + + function getValidators() public view returns(address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; - for (uint i = 0;i= currentValidatorSet.length) { return false; } - return true; + + // validatorExtraSet[index] should not be used before it has been init. + if (index >= validatorExtraSet.length) { + return !currentValidatorSet[index].jailed; + } + + return !currentValidatorSet[index].jailed && !validatorExtraSet[index].isMaintaining; } - {% endif %} + function getIncoming(address validator)external view returns(uint256) { uint256 index = currentValidatorSetMap[validator]; if (index<=0) { @@ -348,65 +441,100 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return currentValidatorSet[index-1].incoming; } - /*********************** For slash **************************/ - function misdemeanor(address validator)external onlySlash override{ + function isCurrentValidator(address validator) external view override returns (bool) { uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { - return; + return false; } - // the actually index + + // the actual index index = index - 1; - uint256 income = currentValidatorSet[index].incoming; - currentValidatorSet[index].incoming = 0; - uint256 rest = currentValidatorSet.length - 1; - emit validatorMisdemeanor(validator,income); - if (rest==0) { - // should not happen, but still protect - return; + return isWorkingValidator(index); + } + + function getWorkingValidatorCount() public view returns(uint256 workingValidatorCount) { + workingValidatorCount = getValidators().length; + uint256 _numOfCabinets = numOfCabinets > 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; + if (workingValidatorCount > _numOfCabinets) { + workingValidatorCount = _numOfCabinets; } - uint256 averageDistribute = income/rest; - if (averageDistribute!=0) { - for (uint i=0;i 0, "only current validators"); + + // the actual index + return index - 1; + } + + function canEnterMaintenance(uint256 index) public view returns (bool) { + if (index >= currentValidatorSet.length) { + return false; } - currentValidatorSet.pop(); - uint256 averageDistribute = income/rest; - if (averageDistribute!=0) { - uint n = currentValidatorSet.length; - for (uint i=0;i= maxNumOfMaintaining // - 2. check if reached upper limit + || !isWorkingValidator(index) // - 3. check if not working(not jailed and not maintaining) + || validatorExtraSet[index].enterMaintenanceHeight > 0 // - 5. check if has Maintained during current 24-hour period + // current validators are selected every 24 hours(from 00:00:00 UTC to 23:59:59 UTC) + // for more details, refer to https://github.com/bnb-chain/docs-site/blob/master/docs/smart-chain/validator/Binance%20Smart%20Chain%20Validator%20FAQs%20-%20Updated.md + || getValidators().length <= 1 // - 6. check num of remaining working validators + ) { + return false; } - // averageDistribute*rest may less than income, but it is ok, the dust income will go to system reward eventually. + + return true; + } + + function enterMaintenance() external initValidatorExtraSet { + // check maintain config + if (maxNumOfMaintaining == 0) { + maxNumOfMaintaining = INIT_MAX_NUM_OF_MAINTAINING; + } + if (maintainSlashScale == 0) { + maintainSlashScale = INIT_MAINTAIN_SLASH_SCALE; + } + + uint256 index = getCurrentValidatorIndex(msg.sender); + require(canEnterMaintenance(index), "can not enter Temporary Maintenance"); + _enterMaintenance(msg.sender, index); + } + + function exitMaintenance() external { + uint256 index = getCurrentValidatorIndex(msg.sender); + + // jailed validators are allowed to exit maintenance + require(validatorExtraSet[index].isMaintaining, "not in maintenance"); + uint256 workingValidatorCount = getWorkingValidatorCount(); + _exitMaintenance(msg.sender, index, workingValidatorCount); } /*********************** Param update ********************************/ @@ -422,6 +550,38 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica require(newBurnRatio <= BURN_RATIO_SCALE, "the burnRatio must be no greater than 10000"); burnRatio = newBurnRatio; burnRatioInitialized = true; + } else if (Memory.compareStrings(key, "maxNumOfMaintaining")) { + require(value.length == 32, "length of maxNumOfMaintaining mismatch"); + uint256 newMaxNumOfMaintaining = BytesToTypes.bytesToUint256(32, value); + uint256 _numOfCabinets = numOfCabinets; + if (_numOfCabinets == 0) { + _numOfCabinets = INIT_NUM_OF_CABINETS; + } + require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCaninates"); + maxNumOfMaintaining = newMaxNumOfMaintaining; + } else if (Memory.compareStrings(key, "maintainSlashScale")) { + require(value.length == 32, "length of maintainSlashScale mismatch"); + uint256 newMaintainSlashScale = BytesToTypes.bytesToUint256(32, value); + require(newMaintainSlashScale > 0, "the maintainSlashScale must be greater than 0"); + maintainSlashScale = newMaintainSlashScale; + } else if (Memory.compareStrings(key, "maxNumOfWorkingCandidates")) { + require(value.length == 32, "length of maxNumOfWorkingCandidates mismatch"); + uint256 newMaxNumOfWorkingCandidates = BytesToTypes.bytesToUint256(32, value); + require(newMaxNumOfWorkingCandidates <= maxNumOfCandidates, "the maxNumOfWorkingCandidates must be not greater than maxNumOfCandidates"); + maxNumOfWorkingCandidates = newMaxNumOfWorkingCandidates; + } else if (Memory.compareStrings(key, "maxNumOfCandidates")) { + require(value.length == 32, "length of maxNumOfCandidates mismatch"); + uint256 newMaxNumOfCandidates = BytesToTypes.bytesToUint256(32, value); + maxNumOfCandidates = newMaxNumOfCandidates; + if (maxNumOfWorkingCandidates > maxNumOfCandidates) { + maxNumOfWorkingCandidates = maxNumOfCandidates; + } + } else if (Memory.compareStrings(key, "numOfCabinets")) { + require(value.length == 32, "length of numOfCabinets mismatch"); + uint256 newNumOfCabinets = BytesToTypes.bytesToUint256(32, value); + require(newNumOfCabinets > 0, "the numOfCabinets must be greater than 0"); + require(newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS"); + numOfCabinets = newNumOfCabinets; } else { require(false, "unknown param"); } @@ -434,8 +594,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (validatorSet.length > MAX_NUM_OF_VALIDATORS){ return (false, "the number of validators exceed the limit"); } - for (uint i = 0;im) { - for (uint i = m;in) { - for (uint i = n;i 0; --index) { + i = index - 1; // the actual index + if (!validatorExtraSet[i].isMaintaining) { + continue; + } + + // only maintaining validators + validator = currentValidatorSet[i].consensusAddress; + + // exit maintenance + isFelony = _exitMaintenance(validator, i, workingValidatorCount); + if (!isFelony || numOfFelony >= _validatorSet.length - 1) { + continue; + } + + // record the jailed validator in validatorSet + for (uint k; k < _validatorSet.length; ++k) { + if (_validatorSet[k].consensusAddress == validator) { + _validatorSet[k].jailed = true; + numOfFelony++; + break; + } + } + } + + // 2. get unjailed validators from validatorSet + unjailedValidatorSet = new Validator[](_validatorSet.length - numOfFelony); + i = 0; + for (uint index; index < _validatorSet.length; ++index) { + if (!_validatorSet[index].jailed) { + unjailedValidatorSet[i] = _validatorSet[index]; + i++; + } + } + + return unjailedValidatorSet; + } + + function _enterMaintenance(address validator, uint256 index) private { + numOfMaintaining++; + validatorExtraSet[index].isMaintaining = true; + validatorExtraSet[index].enterMaintenanceHeight = block.number; + emit validatorEnterMaintenance(validator); + } + + function _exitMaintenance(address validator, uint index, uint256 workingValidatorCount) private returns (bool isFelony){ + if (maintainSlashScale == 0 || workingValidatorCount == 0 || numOfMaintaining == 0) { + // should not happen, still protect + return false; + } + + // step 0: modify numOfMaintaining + numOfMaintaining--; + + // step 1: calculate slashCount + uint256 slashCount = + block.number + .sub(validatorExtraSet[index].enterMaintenanceHeight) + .div(workingValidatorCount) + .div(maintainSlashScale); + + // step 2: clear maintaining info of the validator + validatorExtraSet[index].isMaintaining = false; + + // step3: slash the validator + (uint256 misdemeanorThreshold, uint256 felonyThreshold) = ISlashIndicator(SLASH_CONTRACT_ADDR).getSlashThresholds(); + isFelony = false; + if (slashCount >= felonyThreshold) { + _felony(validator, index); + ISlashIndicator(SLASH_CONTRACT_ADDR).sendFelonyPackage(validator); + isFelony = true; + } else if (slashCount >= misdemeanorThreshold) { + _misdemeanor(validator); + } + + emit validatorExitMaintenance(validator); + } + //rlp encode & decode function function decodeValidatorSetSynPackage(bytes memory msgBytes) internal pure returns (IbcValidatorSetPackage memory, bool) { IbcValidatorSetPackage memory validatorSetPkg; @@ -501,7 +826,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (idx == 1) { RLPDecode.RLPItem[] memory items = iter.next().toList(); validatorSetPkg.validatorSet =new Validator[](items.length); - for (uint j = 0;j Indicator) public indicators; uint256 public previousHeight; + + // The BSC validators assign proper values for `misdemeanorThreshold` and `felonyThreshold` through governance. + // The proper values depends on BSC network's tolerance for continuous missing blocks. uint256 public misdemeanorThreshold; uint256 public felonyThreshold; @@ -80,6 +83,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication /*********************** External func ********************************/ function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ + if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { + return; + } Indicator memory indicator = indicators[validator]; if (indicator.exist) { indicator.count++; @@ -155,6 +161,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit indicatorCleaned(); } + function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); + } /*********************** Param update ********************************/ function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ @@ -188,4 +197,8 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication elements[3] = uint256(block.timestamp).encodeUint(); return elements.encodeList(); } -} \ No newline at end of file + + function getSlashThresholds() override(ISlashIndicator) external view returns (uint256, uint256) { + return (misdemeanorThreshold, felonyThreshold); + } +} diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index f1e9ad32..41bed361 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -22,6 +22,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication address[] public validators; mapping(address => Indicator) public indicators; uint256 public previousHeight; + + // The BSC validators assign proper values for `misdemeanorThreshold` and `felonyThreshold` through governance. + // The proper values depends on BSC network's tolerance for continuous missing blocks. uint256 public misdemeanorThreshold; uint256 public felonyThreshold; @@ -85,6 +88,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication /*********************** External func ********************************/ function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ + if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { + return; + } Indicator memory indicator = indicators[validator]; if (indicator.exist) { indicator.count++; @@ -160,6 +166,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit indicatorCleaned(); } + function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); + } /*********************** Param update ********************************/ function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ @@ -193,4 +202,8 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication elements[3] = uint256(block.timestamp).encodeUint(); return elements.encodeList(); } -} \ No newline at end of file + + function getSlashThresholds() override(ISlashIndicator) external view returns (uint256, uint256) { + return (misdemeanorThreshold, felonyThreshold); + } +} diff --git a/contracts/interface/IBSCValidatorSet.sol b/contracts/interface/IBSCValidatorSet.sol index 9f7f0c0d..513c9289 100644 --- a/contracts/interface/IBSCValidatorSet.sol +++ b/contracts/interface/IBSCValidatorSet.sol @@ -3,4 +3,5 @@ pragma solidity 0.6.4; interface IBSCValidatorSet { function misdemeanor(address validator) external; function felony(address validator)external; -} \ No newline at end of file + function isCurrentValidator(address validator) external view returns (bool); +} diff --git a/contracts/interface/ISlashIndicator.sol b/contracts/interface/ISlashIndicator.sol index eb0f6f02..04f12b7d 100644 --- a/contracts/interface/ISlashIndicator.sol +++ b/contracts/interface/ISlashIndicator.sol @@ -2,4 +2,6 @@ pragma solidity 0.6.4; interface ISlashIndicator { function clean() external; -} \ No newline at end of file + function sendFelonyPackage(address validator) external; + function getSlashThresholds() external view returns (uint256, uint256); +} diff --git a/genesis.json b/genesis.json index 897fbd00..44ae7fce 100644 --- a/genesis.json +++ b/genesis.json @@ -1,6 +1,6 @@ { "config": { - "chainId": 714, + "chainId": 56, "homesteadBlock": 0, "eip150Block": 0, "eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -31,43 +31,43 @@ }, "0x0000000000000000000000000000000000001000": { "balance": "0x0", - "code": "0x6080604052600436106102e45760003560e01c80638624988211610190578063c8509d81116100dc578063eb57e20211610095578063f9a2bbc71161006f578063f9a2bbc714610a69578063fc3e590814610a7e578063fccc281314610a93578063fd6a687914610aa8576102e4565b8063eb57e202146109fb578063eda5868c14610a2e578063f340fa0114610a43576102e4565b8063c8509d81146106d8578063d86222d514610992578063daacdb66146109a7578063dc927faf146109bc578063e086c7b1146109d1578063e1c7392a146109e6576102e4565b8063aaf5eb6811610149578063ad3c9da611610123578063ad3c9da6146108e5578063b7ab4db514610918578063bf9f4995146104c0578063c81b16621461097d576102e4565b8063aaf5eb68146107f0578063ab51bb9614610805578063ac4317511461081a576102e4565b8063862498821461077257806396713da9146107875780639dc092621461079c578063a1a11bf5146107b1578063a5422d5c146107c6578063a78abc16146107db576102e4565b806351e806721161024f57806370fd5bad116102085780637942fd05116101e25780637942fd05146106ae57806381650b62146106c3578063831d65d1146106d8578063853230aa1461075d576102e4565b806370fd5bad1461066f57806375d47a0a1461068457806378dfed4a14610699576102e4565b806351e8067214610572578063565c56b3146105875780635667515a146105ba5780635d77156c146105cf5780636969a25c146105e45780636e47b4821461065a576102e4565b80633de0f0d8116102a15780633de0f0d8146104ab5780633dffc387146104c057806343756e5c146104eb578063493279b11461051c5780634bf6c882146105485780635192c82c1461055d576102e4565b80630bee7a67146102e95780631182b87514610317578063152ad3b8146104115780631ff180691461043a578063219f22d51461046157806335409f7f14610476575b600080fd5b3480156102f557600080fd5b506102fe610abd565b6040805163ffffffff9092168252519081900360200190f35b34801561032357600080fd5b5061039c6004803603604081101561033a57600080fd5b60ff8235169190810190604081016020820135600160201b81111561035e57600080fd5b82018360208201111561037057600080fd5b803590602001918460018302840111600160201b8311171561039157600080fd5b509092509050610ac2565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103d65781810151838201526020016103be565b50505050905090810190601f1680156104035780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561041d57600080fd5b50610426610caf565b604080519115158252519081900360200190f35b34801561044657600080fd5b5061044f610cb8565b60408051918252519081900360200190f35b34801561046d57600080fd5b506102fe610cbe565b34801561048257600080fd5b506104a96004803603602081101561049957600080fd5b50356001600160a01b0316610cc3565b005b3480156104b757600080fd5b5061044f610fd7565b3480156104cc57600080fd5b506104d5610fdd565b6040805160ff9092168252519081900360200190f35b3480156104f757600080fd5b50610500610fe2565b604080516001600160a01b039092168252519081900360200190f35b34801561052857600080fd5b50610531610fe8565b6040805161ffff9092168252519081900360200190f35b34801561055457600080fd5b506104d5610fed565b34801561056957600080fd5b5061044f610ff2565b34801561057e57600080fd5b50610500610ff8565b34801561059357600080fd5b5061044f600480360360208110156105aa57600080fd5b50356001600160a01b0316610ffe565b3480156105c657600080fd5b506104d5611050565b3480156105db57600080fd5b506102fe611055565b3480156105f057600080fd5b5061060e6004803603602081101561060757600080fd5b503561105a565b604080516001600160a01b039788168152958716602087015293909516848401526001600160401b0390911660608401521515608083015260a082019290925290519081900360c00190f35b34801561066657600080fd5b506105006110be565b34801561067b57600080fd5b506104d56110c4565b34801561069057600080fd5b506105006110c9565b3480156106a557600080fd5b5061044f611050565b3480156106ba57600080fd5b506104d56110cf565b3480156106cf57600080fd5b506102fe6110d4565b3480156106e457600080fd5b506104a9600480360360408110156106fb57600080fd5b60ff8235169190810190604081016020820135600160201b81111561071f57600080fd5b82018360208201111561073157600080fd5b803590602001918460018302840111600160201b8311171561075257600080fd5b5090925090506110d9565b34801561076957600080fd5b5061044f61118c565b34801561077e57600080fd5b5061044f611192565b34801561079357600080fd5b506104d5611198565b3480156107a857600080fd5b5061050061119d565b3480156107bd57600080fd5b506105006111a3565b3480156107d257600080fd5b5061039c6111a9565b3480156107e757600080fd5b506104266111c5565b3480156107fc57600080fd5b5061044f6111ce565b34801561081157600080fd5b506102fe611050565b34801561082657600080fd5b506104a96004803603604081101561083d57600080fd5b810190602081018135600160201b81111561085757600080fd5b82018360208201111561086957600080fd5b803590602001918460018302840111600160201b8311171561088a57600080fd5b919390929091602081019035600160201b8111156108a757600080fd5b8201836020820111156108b957600080fd5b803590602001918460018302840111600160201b831117156108da57600080fd5b5090925090506111d7565b3480156108f157600080fd5b5061044f6004803603602081101561090857600080fd5b50356001600160a01b03166115ce565b34801561092457600080fd5b5061092d6115e0565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610969578181015183820152602001610951565b505050509050019250505060405180910390f35b34801561098957600080fd5b50610500611706565b34801561099e57600080fd5b5061044f61170c565b3480156109b357600080fd5b5061044f611718565b3480156109c857600080fd5b5061050061171e565b3480156109dd57600080fd5b5061044f611724565b3480156109f257600080fd5b506104a9611729565b348015610a0757600080fd5b506104a960048036036020811015610a1e57600080fd5b50356001600160a01b0316611929565b348015610a3a57600080fd5b506102fe611af8565b6104a960048036036020811015610a5957600080fd5b50356001600160a01b0316611afd565b348015610a7557600080fd5b50610500611dfe565b348015610a8a57600080fd5b506104d5611e04565b348015610a9f57600080fd5b50610500611e09565b348015610ab457600080fd5b50610500611e0f565b606481565b60005460609060ff16610b18576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b3361200014610b585760405162461bcd60e51b815260040180806020018281038252602f8152602001806143b4602f913960400191505060405180910390fd5b610b60614163565b6000610ba185858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e1592505050565b9150915080610bbd57610bb46064611f6e565b92505050610ca8565b815160009060ff16610bdd57610bd68360200151611fcf565b9050610c74565b825160ff1660011415610c7057826020015151600114610c4a577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb26040518080602001828103825260258152602001806142916025913960400191505060405180910390a1506067610c6b565b610bd68360200151600081518110610c5e57fe5b6020026020010151612dd5565b610c74565b5060655b63ffffffff8116610c995750506040805160008152602081019091529150610ca89050565b610ca281611f6e565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b3361100114610d035760405162461bcd60e51b81526004018080602001828103825260298152602001806144106029913960400191505060405180910390fd5b6001600160a01b03811660009081526004602052604090205480610d275750610fd4565b600181039050600060018281548110610d3c57fe5b60009182526020909120600360049092020101546001549091506000190180610d8b57600060018481548110610d6e57fe5b906000526020600020906004020160030181905550505050610fd4565b6040805183815290516001600160a01b038616917f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70919081900360200190a26001600160a01b038416600090815260046020526040812055600154600019018314610f0d57600180546000198101908110610e0257fe5b906000526020600020906004020160018481548110610e1d57fe5b6000918252602082208354600492830290910180546001600160a01b03199081166001600160a01b0393841617825560018087015481840180548416918616919091179055600280880180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b199094169390931790556003948501549401939093558254868401939192919087908110610ee257fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020555b6001805480610f1857fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b03191690556003018190559155818381610f6b57fe5b0490508015610fcf5760015460005b81811015610fcc578260018281548110610f9057fe5b9060005260206000209060040201600301540160018281548110610fb057fe5b6000918252602090912060036004909202010155600101610f7a565b50505b505050505b50565b61271081565b600181565b61100181565b606081565b600881565b60065481565b61200081565b6001600160a01b0381166000908152600460205260408120548061102657600091505061104b565b60018082038154811061103557fe5b9060005260206000209060040201600301549150505b919050565b600081565b606781565b6001818154811061106757fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b61100881565b600b81565b606681565b33612000146111195760405162461bcd60e51b815260040180806020018281038252602f8152602001806143b4602f913960400191505060405180910390fd5b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b6103e881565b60025481565b600981565b61100781565b61100681565b60405180608001604052806047815260200161434c6047913981565b60005460ff1681565b6402540be40081565b60005460ff1661122a576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b336110071461126a5760405162461bcd60e51b815260040180806020018281038252602e8152602001806142d7602e913960400191505060405180910390fd5b6112d484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b60208201529150612f4c9050565b156113af57602081146113185760405162461bcd60e51b81526004018080602001828103825260268152602001806143266026913960400191505060405180910390fd5b604080516020601f84018190048102820181019092528281526000916113569185858083850183828082843760009201919091525061303492505050565b90506064811015801561136c5750620186a08111155b6113a75760405162461bcd60e51b815260040180806020018281038252602781526020018061426a6027913960400191505060405180910390fd5b60025561153c565b61140f84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b60208201529150612f4c9050565b156114ff5760208114611469576040805162461bcd60e51b815260206004820152601c60248201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604482015290519081900360640190fd5b604080516020601f84018190048102820181019092528281526000916114a79185858083850183828082843760009201919091525061303492505050565b90506127108111156114ea5760405162461bcd60e51b815260040180806020018281038252602b815260200180614214602b913960400191505060405180910390fd5b6006556007805460ff1916600117905561153c565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60046020526000908152604090205481565b6001546060906000805b8281101561163157600181815481106115ff57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611629576001909101905b6001016115ea565b5060608160405190808252806020026020018201604052801561165e578160200160208202803683370190505b50600092509050815b838110156116fe576001818154811061167c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff166116f657600181815481106116ac57fe5b600091825260209091206004909102015482516001600160a01b03909116908390859081106116d757fe5b6001600160a01b03909216602092830291909101909101526001909201915b600101611667565b509250505090565b61100281565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff1615611781576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b611789614163565b60006117ac60405180608001604052806047815260200161434c60479139611e15565b91509150806117ec5760405162461bcd60e51b81526004018080602001828103825260218152602001806143936021913960400191505060405180910390fd5b60005b8260200151518110156119115760018360200151828151811061180e57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a0909301516003909301929092559186015180519185019391859081106118e457fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016117ef565b50506103e8600255506000805460ff19166001179055565b33611001146119695760405162461bcd60e51b81526004018080602001828103825260298152602001806144106029913960400191505060405180910390fd5b6001600160a01b0381166000908152600460205260409020548061198d5750610fd4565b6001810390506000600182815481106119a257fe5b90600052602060002090600402016003015490506000600183815481106119c557fe5b906000526020600020906004020160030181905550600060018080549050039050836001600160a01b03167f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d836040518082815260200191505060405180910390a280611a3457505050610fd4565b6000818381611a3f57fe5b0490508015610fcf5760005b84811015611a9d578160018281548110611a6157fe5b9060005260206000209060040201600301540160018281548110611a8157fe5b6000918252602090912060036004909202010155600101611a4b565b50600180549085015b81811015610fcc578260018281548110611abc57fe5b9060005260206000209060040201600301540160018281548110611adc57fe5b6000918252602090912060036004909202010155600101611aa6565b606581565b334114611b3b5760405162461bcd60e51b815260040180806020018281038252602d8152602001806143e3602d913960400191505060405180910390fd5b60005460ff16611b8e576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b60003411611bdb576040805162461bcd60e51b81526020600482015260156024820152746465706f7369742076616c7565206973207a65726f60581b604482015290519081900360640190fd5b6001600160a01b03811660009081526004602052604081205460075434929060ff1615611c0757506006545b600083118015611c175750600081115b15611cc0576000611c40612710611c34868563ffffffff61303916565b9063ffffffff61309216565b90508015611cbe5760405161dead9082156108fc029083906000818181858888f19350505050158015611c77573d6000803e3d6000fd5b506040805182815290517f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee59181900360200190a1611cbb848263ffffffff6130d416565b93505b505b8115611db8576000600180840381548110611cd757fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615611d42576040805185815290516001600160a01b038716917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a2611db2565b600354611d55908563ffffffff61311616565b6003908155810154611d6d908563ffffffff61311616565b60038201556040805185815290516001600160a01b038716917f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc055919081900360200190a25b50611df8565b6040805184815290516001600160a01b038616917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a25b50505050565b61100081565b600381565b61dead81565b61100481565b611e1d614163565b6000611e27614163565b611e2f61417b565b611e40611e3b86613170565b613195565b90506000805b611e4f836131df565b15611f605780611e7457611e6a611e6584613200565b61324e565b60ff168452611f58565b8060011415611f53576060611e90611e8b85613200565b613305565b90508051604051908082528060200260200182016040528015611ecd57816020015b611eba61419b565b815260200190600190039081611eb25790505b50602086015260005b8151811015611f4857611ee761419b565b6000611f05848481518110611ef857fe5b60200260200101516133d6565b9150915080611f2257876000995099505050505050505050611f69565b8188602001518481518110611f3357fe5b60209081029190910101525050600101611ed6565b506001925050611f58565b611f60565b600101611e46565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081611f88579050509050611fae8363ffffffff166134b3565b81600081518110611fbb57fe5b6020026020010181905250610ca8816134c6565b6000806060611fdd84613550565b915091508161208a577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b8381101561204557818101518382015260200161202d565b50505050905090810190601f1680156120725780820380516001836020036101000a031916815260200191505b509250505060405180910390a160669250505061104b565b600080805b6001548110156121075767016345785d8a0000600182815481106120af57fe5b906000526020600020906004020160030154106120d1576001909201916120ff565b6000600182815481106120e057fe5b90600052602060002090600402016003015411156120ff576001909101905b60010161208f565b50606082604051908082528060200260200182016040528015612134578160200160208202803683370190505b509050606083604051908082528060200260200182016040528015612163578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015612192578160200160208202803683370190505b5090506060856040519080825280602002602001820160405280156121c1578160200160208202803683370190505b50905060006060866040519080825280602002602001820160405280156121f2578160200160208202803683370190505b509050606087604051908082528060200260200182016040528015612221578160200160208202803683370190505b509050600098506000975060608d905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561226e57600080fd5b505afa158015612282573d6000803e3d6000fd5b505050506040513d602081101561229857600080fd5b5051905067016345785d8a000081111561230d577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb26040518080602001828103825260218152602001806143056021913960400191505060405180910390a160689d505050505050505050505050505061104b565b60005b6001548110156125805767016345785d8a00006001828154811061233057fe5b906000526020600020906004020160030154106124b6576001818154811061235457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b03168a8d8151811061238557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be400600183815481106123ba57fe5b906000526020600020906004020160030154816123d357fe5b06600183815481106123e157fe5b90600052602060002090600402016003015403905061240983826130d490919063ffffffff16565b8a8e8151811061241557fe5b6020026020010181815250506001828154811061242e57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316888e8151811061245f57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081898e8151811061248c57fe5b60209081029190910101526124a7878263ffffffff61311616565b6001909d019c96506125789050565b6000600182815481106124c557fe5b906000526020600020906004020160030154111561257857600181815481106124ea57fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316858c8151811061251b57fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061254857fe5b906000526020600020906004020160030154848c8151811061256657fe5b60209081029190910101526001909a01995b600101612310565b50600085156129be576110046001600160a01b0316636e056520878c8c8b60025442016040518663ffffffff1660e01b815260040180806020018060200180602001856001600160401b03166001600160401b03168152602001848103845288818151815260200191508051906020019060200280838360005b838110156126125781810151838201526020016125fa565b50505050905001848103835287818151815260200191508051906020019060200280838360005b83811015612651578181015183820152602001612639565b50505050905001848103825286818151815260200191508051906020019060200280838360005b83811015612690578181015183820152602001612678565b505050509050019750505050505050506020604051808303818588803b1580156126b957600080fd5b505af1935050505080156126df57506040513d60208110156126da57600080fd5b505160015b61291a576040516000815260443d10156126fb57506000612796565b60046000803e60005160e01c6308c379a0811461271c576000915050612796565b60043d036004833e81513d60248201116001600160401b038211171561274757600092505050612796565b80830180516001600160401b03811115612768576000945050505050612796565b8060208301013d860181111561278657600095505050505050612796565b601f01601f191660405250925050505b806127a15750612845565b60019150867fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280826040518080602001828103825283818151815260200191508051906020019080838360005b838110156128055781810151838201526020016127ed565b50505050905090810190601f1680156128325780820380516001836020036101000a031916815260200191505b509250505060405180910390a250612915565b3d80801561286f576040519150601f19603f3d011682016040523d82523d6000602084013e612874565b606091505b5060019150867fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040518080602001828103825283818151815260200191508051906020019080838360005b838110156128d95781810151838201526020016128c1565b50505050905090810190601f1680156129065780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6129be565b8015612958576040805188815290517fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b709181900360200190a16129bc565b604080516020808252601b908201527f6261746368207472616e736665722072657475726e2066616c7365000000000081830152905188917fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280919081900360600190a25b505b8015612b745760005b8851811015612b725760008982815181106129de57fe5b602002602001015190506000600182815481106129f757fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc9185908110612a2857fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015612ae45760018281548110612a6957fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110612ab857fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a2612b68565b60018281548110612af157fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110612b4057fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a25b50506001016129c7565b505b845115612cbe5760005b8551811015612cbc576000868281518110612b9557fe5b60200260200101516001600160a01b03166108fc878481518110612bb557fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015612c4b57868281518110612beb57fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d878481518110612c2957fe5b60200260200101516040518082815260200191505060405180910390a2612cb3565b868281518110612c5757fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d878481518110612c9557fe5b60200260200101516040518082815260200191505060405180910390a25b50600101612b7e565b505b4715612d27576040805147815290517f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d9181900360200190a1604051611002904780156108fc02916000818181858888f19350505050158015612d25573d6000803e3d6000fd5b505b60006003819055600555825115612d4157612d4183613632565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015612d7e57600080fd5b505af1158015612d92573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a15060009f9e505050505050505050505050505050565b80516001600160a01b0316600090815260046020526040812054801580612e265750600180820381548110612e0657fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15612e6c5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600091505061104b565b600154600554600019820111801590612ec25784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000935050505061104b565b600580546001908101909155805481906000198601908110612ee057fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000816040516020018082805190602001908083835b60208310612f815780518252601f199092019160209182019101612f62565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310612fef5780518252601f199092019160209182019101612fd0565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490505b92915050565b015190565b6000826130485750600061302e565b8282028284828161305557fe5b0414610ca85760405162461bcd60e51b81526004018080602001828103825260218152602001806142b66021913960400191505060405180910390fd5b6000610ca883836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613af3565b6000610ca883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613b95565b600082820183811015610ca8576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6131786141d0565b506040805180820190915281518152602082810190820152919050565b61319d61417b565b6131a682613bef565b6131af57600080fd5b60006131be8360200151613c29565b60208085015160408051808201909152868152920190820152915050919050565b60006131e96141d0565b505080518051602091820151919092015191011190565b6132086141d0565b613211826131df565b61321a57600080fd5b6020820151600061322a82613c8c565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061326357508151602110155b61326c57600080fd5b600061327b8360200151613c29565b905080836000015110156132d6576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b8251602080850151830180519284900392918310156132fc57826020036101000a820491505b50949350505050565b606061331082613bef565b61331957600080fd5b600061332483613dbf565b905060608160405190808252806020026020018201604052801561336257816020015b61334f6141d0565b8152602001906001900390816133475790505b50905060006133748560200151613c29565b60208601510190506000805b848110156133cb5761339183613c8c565b91506040518060400160405280838152602001848152508482815181106133b457fe5b602090810291909101015291810191600101613380565b509195945050505050565b6133de61419b565b60006133e861419b565b6133f061417b565b6133f985613195565b90506000805b613408836131df565b15611f6057806134335761342361341e84613200565b613e1b565b6001600160a01b031684526134ab565b806001141561345b5761344861341e84613200565b6001600160a01b031660208501526134ab565b80600214156134835761347061341e84613200565b6001600160a01b031660408501526134ab565b8060031415611f5357613498611e6584613200565b6001600160401b03166060850152600191505b6001016133ff565b606061302e6134c183613e35565b613f1b565b60608151600014156134e7575060408051600081526020810190915261104b565b6060826000815181106134f657fe5b602002602001015190506000600190505b83518110156135375761352d8285838151811061352057fe5b6020026020010151613f6d565b9150600101613507565b50610ca861354a825160c060ff16613fea565b82613f6d565b600060606029835111156135825760006040518060600160405280602981526020016141eb6029913991509150611f69565b60005b83518110156136185760005b8181101561360f578481815181106135a557fe5b6020026020010151600001516001600160a01b03168583815181106135c657fe5b6020026020010151600001516001600160a01b031614156136075760006040518060600160405280602b815260200161423f602b9139935093505050611f69565b600101613591565b50600101613585565b505060408051602081019091526000815260019150915091565b600154815160005b8281101561374f57600161364c61419b565b6001838154811061365957fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015613723578681815181106136e957fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b0316141561371b5760009250613723565b6001016136d5565b5081156137455780516001600160a01b03166000908152600460205260408120555b505060010161363a565b50808211156137c457805b828110156137c257600180548061376d57fe5b60008281526020812060046000199093019283020180546001600160a01b03199081168255600182810180549092169091556002820180546001600160e81b031916905560039091019190915591550161375a565b505b60008183106137d357816137d5565b825b905060005b818110156139cf576138878582815181106137f157fe5b60200260200101516001838154811061380657fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a08201526140e2565b6139a257806001016004600087848151811061389f57fe5b6020026020010151600001516001600160a01b03166001600160a01b03168152602001908152602001600020819055508481815181106138db57fe5b6020026020010151600182815481106138f057fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a0909101516003909101556139c7565b6000600182815481106139b157fe5b9060005260206000209060040201600301819055505b6001016137da565b5082821115611df857825b82811015610fcf5760018582815181106139f057fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782559585015181840180549184169188169190911790556040850151600282018054606088015160808901511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590971692909a169190911792909216939093171695909517905560a09092015160039093019290925587519084019290889085908110613ac657fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016139da565b60008183613b7f5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613b44578181015183820152602001613b2c565b50505050905090810190601f168015613b715780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581613b8b57fe5b0495945050505050565b60008184841115613be75760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613b44578181015183820152602001613b2c565b505050900390565b8051600090613c005750600061104b565b6020820151805160001a9060c0821015613c1f5760009250505061104b565b5060019392505050565b8051600090811a6080811015613c4357600091505061104b565b60b8811080613c5e575060c08110801590613c5e575060f881105b15613c6d57600191505061104b565b60c0811015613c815760b51901905061104b565b60f51901905061104b565b80516000908190811a6080811015613ca75760019150613db8565b60b8811015613cbc57607e1981019150613db8565b60c0811015613d3657600060b78203600186019550806020036101000a865104915060018101820193505080831015613d30576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50613db8565b60f8811015613d4b5760be1981019150613db8565b600060f78203600186019550806020036101000a865104915060018101820193505080831015613db6576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b8051600090613dd05750600061104b565b60008090506000613de48460200151613c29565b602085015185519181019250015b80821015613e1257613e0382613c8c565b60019093019290910190613df2565b50909392505050565b8051600090601514613e2c57600080fd5b61302e8261324e565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416613e7957506018613e9d565b6fffffffffffffffffffffffffffffffff198416613e9957506010613e9d565b5060005b6020811015613ed357818181518110613eb257fe5b01602001516001600160f81b03191615613ecb57613ed3565b600101613e9d565b60008160200390506060816040519080825280601f01601f191660200182016040528015613f08576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613f4d5750607f60f81b82600081518110613f3b57fe5b01602001516001600160f81b03191611155b15613f5957508061104b565b61302e613f6b8351608060ff16613fea565b835b6060806040519050835180825260208201818101602087015b81831015613f9e578051835260209283019201613f86565b50855184518101855292509050808201602086015b81831015613fcb578051835260209283019201613fb3565b508651929092011591909101601f01601f191660405250905092915050565b606068010000000000000000831061403a576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116140945782840160f81b8160008151811061407657fe5b60200101906001600160f81b031916908160001a905350905061302e565b606061409f85613e35565b90508381510160370160f81b826000815181106140b857fe5b60200101906001600160f81b031916908160001a9053506140d98282613f6d565b95945050505050565b805182516000916001600160a01b03918216911614801561411c575081602001516001600160a01b031683602001516001600160a01b0316145b8015614141575081604001516001600160a01b031683604001516001600160a01b0316145b8015610ca85750506060908101519101516001600160401b0390811691161490565b60408051808201909152600081526060602082015290565b604051806040016040528061418e6141d0565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60405180604001604052806000815260200160008152509056fe746865206e756d626572206f662076616c696461746f72732065786365656420746865206c696d6974746865206275726e526174696f206d757374206265206e6f2067726561746572207468616e2031303030306475706c696361746520636f6e73656e7375732061646472657373206f662076616c696461746f725365747468652065787069726554696d655365636f6e64476170206973206f7574206f662072616e67656c656e677468206f66206a61696c2076616c696461746f7273206d757374206265206f6e65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374666565206973206c6172676572207468616e2044555354595f494e434f4d494e476c656e677468206f662065787069726554696d655365636f6e64476170206d69736d61746368f84580f842f840949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791646661696c656420746f20706172736520696e69742076616c696461746f72536574746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d6573736167652073656e646572206d7573742062652074686520626c6f636b2070726f6475636572746865206d6573736167652073656e646572206d75737420626520736c61736820636f6e7472616374a26469706673582212208e73e8b8f527f30b4a7ae766d39f2d53a0ff4e36ee760d714ba23d5fe7b5714064736f6c63430006040033" + "code": "0x6080604052600436106104055760003560e01c80638d19a41011610213578063c81b166211610123578063eb57e202116100ab578063f9a2bbc71161007a578063f9a2bbc714610d55578063fc3e590814610d6a578063fccc281314610d7f578063fd4ad81f14610d94578063fd6a687914610dd757610405565b8063eb57e20214610cd2578063eda5868c14610d05578063f340fa0114610d1a578063f92eb86b14610d4057610405565b8063daacdb66116100f2578063daacdb6614610c69578063dc927faf14610c7e578063e086c7b114610c93578063e1c7392a14610ca8578063e40716a114610cbd57610405565b8063c81b166214610c2a578063c8509d8114610939578063d68fb56a14610c3f578063d86222d514610c5457610405565b8063a78abc16116101a6578063ad3c9da611610175578063ad3c9da614610bb8578063b7ab4db514610beb578063b8cf4ef114610c00578063bf9f49951461065f578063c6d3394514610c1557610405565b8063a78abc1614610aae578063aaf5eb6814610ac3578063ab51bb9614610ad8578063ac43175114610aed57610405565b80639fe0f816116101e25780639fe0f81614610a5a578063a0dc275814610a6f578063a1a11bf514610a84578063a5422d5c14610a9957610405565b80638d19a410146109e85780639369d7de14610a1b57806396713da914610a305780639dc0926214610a4557610405565b80635192c82c1161031957806375d47a0a116102a157806381650b621161027057806381650b6214610924578063831d65d114610939578063853230aa146108e557806386249882146109be5780638b5ad0c9146109d357610405565b806375d47a0a146108d057806378dfed4a146108e55780637942fd05146108fa5780637a84ca2a1461090f57610405565b80635667515a116102e85780635667515a146108065780635d77156c1461081b5780636969a25c146108305780636e47b482146108a657806370fd5bad146108bb57610405565b80635192c82c1461077657806351e806721461078b57806355614fcc146107a0578063565c56b3146107d357610405565b80633365af3a1161039c57806343756e5c1161036b57806343756e5c1461068a57806345cf9daf146106bb578063493279b1146106d05780634bf6c882146106fc5780634df6e0c31461071157610405565b80633365af3a146105ed57806335409f7f146106175780633de0f0d81461064a5780633dffc3871461065f57610405565b8063152ad3b8116103d8578063152ad3b8146105705780631ff1806914610599578063219f22d5146105ae578063321d398a146105c357610405565b806304c4fec61461040a57806307a56847146104215780630bee7a67146104485780631182b87514610476575b600080fd5b34801561041657600080fd5b5061041f610dec565b005b34801561042d57600080fd5b50610436610e7f565b60408051918252519081900360200190f35b34801561045457600080fd5b5061045d610e85565b6040805163ffffffff9092168252519081900360200190f35b34801561048257600080fd5b506104fb6004803603604081101561049957600080fd5b60ff8235169190810190604081016020820135600160201b8111156104bd57600080fd5b8201836020820111156104cf57600080fd5b803590602001918460018302840111600160201b831117156104f057600080fd5b509092509050610e8a565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561053557818101518382015260200161051d565b50505050905090810190601f1680156105625780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561057c57600080fd5b5061058561111c565b604080519115158252519081900360200190f35b3480156105a557600080fd5b50610436611125565b3480156105ba57600080fd5b5061045d61112b565b3480156105cf57600080fd5b50610585600480360360208110156105e657600080fd5b5035611130565b3480156105f957600080fd5b506105856004803603602081101561061057600080fd5b50356111ff565b34801561062357600080fd5b5061041f6004803603602081101561063a57600080fd5b50356001600160a01b03166112b0565b34801561065657600080fd5b5061043661140f565b34801561066b57600080fd5b50610674611415565b6040805160ff9092168252519081900360200190f35b34801561069657600080fd5b5061069f61141a565b604080516001600160a01b039092168252519081900360200190f35b3480156106c757600080fd5b50610436611420565b3480156106dc57600080fd5b506106e5611426565b6040805161ffff9092168252519081900360200190f35b34801561070857600080fd5b5061067461142b565b34801561071d57600080fd5b50610726611430565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561076257818101518382015260200161074a565b505050509050019250505060405180910390f35b34801561078257600080fd5b5061043661152b565b34801561079757600080fd5b5061069f611531565b3480156107ac57600080fd5b50610585600480360360208110156107c357600080fd5b50356001600160a01b0316611537565b3480156107df57600080fd5b50610436600480360360208110156107f657600080fd5b50356001600160a01b031661156c565b34801561081257600080fd5b506106746115bd565b34801561082757600080fd5b5061045d6115c2565b34801561083c57600080fd5b5061085a6004803603602081101561085357600080fd5b50356115c7565b604080516001600160a01b039788168152958716602087015293909516848401526001600160401b0390911660608401521515608083015260a082019290925290519081900360c00190f35b3480156108b257600080fd5b5061069f61162b565b3480156108c757600080fd5b50610674611631565b3480156108dc57600080fd5b5061069f611636565b3480156108f157600080fd5b5061043661163c565b34801561090657600080fd5b50610674611642565b34801561091b57600080fd5b50610436611647565b34801561093057600080fd5b5061045d61164d565b34801561094557600080fd5b5061041f6004803603604081101561095c57600080fd5b60ff8235169190810190604081016020820135600160201b81111561098057600080fd5b82018360208201111561099257600080fd5b803590602001918460018302840111600160201b831117156109b357600080fd5b509092509050611652565b3480156109ca57600080fd5b50610436611705565b3480156109df57600080fd5b5061043661170b565b3480156109f457600080fd5b5061043660048036036020811015610a0b57600080fd5b50356001600160a01b0316611711565b348015610a2757600080fd5b5061041f611786565b348015610a3c57600080fd5b506106746118a0565b348015610a5157600080fd5b5061069f6118a5565b348015610a6657600080fd5b506104366118ab565b348015610a7b57600080fd5b506104366118b0565b348015610a9057600080fd5b5061069f6118b5565b348015610aa557600080fd5b506104fb6118bb565b348015610aba57600080fd5b506105856118da565b348015610acf57600080fd5b506104366118e3565b348015610ae457600080fd5b5061045d6115bd565b348015610af957600080fd5b5061041f60048036036040811015610b1057600080fd5b810190602081018135600160201b811115610b2a57600080fd5b820183602082011115610b3c57600080fd5b803590602001918460018302840111600160201b83111715610b5d57600080fd5b919390929091602081019035600160201b811115610b7a57600080fd5b820183602082011115610b8c57600080fd5b803590602001918460018302840111600160201b83111715610bad57600080fd5b5090925090506118ec565b348015610bc457600080fd5b5061043660048036036020811015610bdb57600080fd5b50356001600160a01b0316612329565b348015610bf757600080fd5b5061072661233b565b348015610c0c57600080fd5b5061043661241e565b348015610c2157600080fd5b50610436611631565b348015610c3657600080fd5b5061069f612423565b348015610c4b57600080fd5b50610436612429565b348015610c6057600080fd5b50610436612468565b348015610c7557600080fd5b50610436612474565b348015610c8a57600080fd5b5061069f61247a565b348015610c9f57600080fd5b50610436612480565b348015610cb457600080fd5b5061041f612485565b348015610cc957600080fd5b50610436612688565b348015610cde57600080fd5b5061041f60048036036020811015610cf557600080fd5b50356001600160a01b031661268e565b348015610d1157600080fd5b5061045d61279c565b61041f60048036036020811015610d3057600080fd5b50356001600160a01b03166127a1565b348015610d4c57600080fd5b50610436612aa6565b348015610d6157600080fd5b5061069f612aac565b348015610d7657600080fd5b506106746118ab565b348015610d8b57600080fd5b5061069f612ab2565b348015610da057600080fd5b50610dbe60048036036020811015610db757600080fd5b5035612ab8565b6040805192835290151560208301528051918290030190f35b348015610de357600080fd5b5061069f612ae6565b6000610df733611711565b9050600b8181548110610e0657fe5b600091825260209091206001601690920201015460ff16610e63576040805162461bcd60e51b81526020600482015260126024820152716e6f7420696e206d61696e74656e616e636560701b604482015290519081900360640190fd5b6000610e6d612429565b9050610e7a338383612aec565b505050565b60095481565b606481565b60005460609060ff16610ee0576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b3361200014610f205760405162461bcd60e51b815260040180806020018281038252602f81526020018061648b602f913960400191505060405180910390fd5b600b54610fc557610f2f6159e0565b60015460005b81811015610fc157600b80546001810182556000919091528351600080516020615e15833981519152601690920291820190815560208501516000805160206165148339815191528301805460ff191691151591909117905560408501518592610fb391600080516020615e5b833981519152909101906014615a04565b505050806001019050610f35565b5050505b610fcd615a3e565b600061100e85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ce092505050565b915091508061102a576110216064612e39565b92505050611115565b815160009060ff1661104a576110438360200151612e9a565b90506110e1565b825160ff16600114156110dd578260200151516001146110b7577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2604051808060200182810382526025815260200180615d5b6025913960400191505060405180910390a15060676110d8565b61104383602001516000815181106110cb57fe5b6020026020010151613caa565b6110e1565b5060655b63ffffffff811661110657505060408051600081526020810190915291506111159050565b61110f81612e39565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b6001546000908210611144575060006111fa565b60006001600160a01b03166001838154811061115c57fe5b60009182526020909120600490910201546001600160a01b0316148061118c5750600854158061118c5750600a54155b8061119b575060085460095410155b806111ac57506111aa826111ff565b155b806111d557506000600b83815481106111c157fe5b906000526020600020906016020160000154115b806111e9575060016111e561233b565b5111155b156111f6575060006111fa565b5060015b919050565b6001546000908210611213575060006111fa565b600b548210611250576001828154811061122957fe5b9060005260206000209060040201600201601c9054906101000a900460ff161590506111fa565b6001828154811061125d57fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156112aa5750600b828154811061129157fe5b600091825260209091206001601690920201015460ff16155b92915050565b33611001146112f05760405162461bcd60e51b81526004018080602001828103825260298152602001806165346029913960400191505060405180910390fd5b600b54611395576112ff6159e0565b60015460005b8181101561139157600b80546001810182556000919091528351600080516020615e15833981519152601690920291820190815560208501516000805160206165148339815191528301805460ff19169115159190911790556040850151859261138391600080516020615e5b833981519152909101906014615a04565b505050806001019050611305565b5050505b6001600160a01b038116600090815260046020526040902054806113b9575061140c565b6001810390506000600b82815481106113ce57fe5b600091825260209091206001601690920201015460ff1690506113f18383613e21565b80156113fa5750805b15610e7a576009805460001901905550505b50565b61271081565b600181565b61100181565b60085481565b603881565b600881565b600e54600c546060919080611443575060155b606061144d61233b565b905081815111611461579250611528915050565b82828251031015611473578181510392505b82156114a75760c8430461148e82828686036000888861419d565b6114a582828686038787038889898951030161419d565b505b6060826040519080825280602002602001820160405280156114d3578160200160208202803683370190505b50905060005b83811015611521578281815181106114ed57fe5b602002602001015182828151811061150157fe5b6001600160a01b03909216602092830291909101909101526001016114d9565b5093505050505b90565b60065481565b61200081565b6001600160a01b0381166000908152600460205260408120548061155f5760009150506111fa565b60001901611115816111ff565b6001600160a01b038116600090815260046020526040812054806115945760009150506111fa565b6001808203815481106115a357fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b600181815481106115d457fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b61100881565b6103e881565b600b81565b600c5481565b606681565b33612000146116925760405162461bcd60e51b815260040180806020018281038252602f81526020018061648b602f913960400191505060405180910390fd5b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1505050565b60025481565b600a5481565b6001600160a01b0381166000908152600460205260408120548061177c576040805162461bcd60e51b815260206004820152601760248201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604482015290519081900360640190fd5b6000190192915050565b600b5461182b576117956159e0565b60015460005b8181101561182757600b80546001810182556000919091528351600080516020615e15833981519152601690920291820190815560208501516000805160206165148339815191528301805460ff19169115159190911790556040850151859261181991600080516020615e5b833981519152909101906014615a04565b50505080600101905061179b565b5050505b6008546118385760036008555b600a54611845576002600a555b600061185033611711565b905061185b81611130565b6118965760405162461bcd60e51b8152600401808060200182810382526023815260200180615d386023913960400191505060405180910390fd5b61140c338261428c565b600981565b61100781565b600381565b60c881565b61100681565b6040518061062001604052806105ef8152602001615e9c6105ef913981565b60005460ff1681565b6402540be40081565b60005460ff1661193f576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b336110071461197f5760405162461bcd60e51b815260040180806020018281038252602e815260200180615da1602e913960400191505060405180910390fd5b6119e984848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506143249050565b15611ac45760208114611a2d5760405162461bcd60e51b8152600401808060200182810382526026815260200180615e356026913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091611a6b9185858083850183828082843760009201919091525061440b92505050565b905060648110158015611a815750620186a08111155b611abc5760405162461bcd60e51b8152600401808060200182810382526027815260200180615cc86027913960400191505060405180910390fd5b600255612297565b611b2484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506143249050565b15611c145760208114611b7e576040805162461bcd60e51b815260206004820152601c60248201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091611bbc9185858083850183828082843760009201919091525061440b92505050565b9050612710811115611bff5760405162461bcd60e51b815260040180806020018281038252602b815260200180615c72602b913960400191505060405180910390fd5b6006556007805460ff19166001179055612297565b611c7e84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506143249050565b15611d565760208114611cc25760405162461bcd60e51b8152600401808060200182810382526026815260200180615b396026913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091611d009185858083850183828082843760009201919091525061440b92505050565b600c5490915080611d0f575060155b808210611d4d5760405162461bcd60e51b8152600401808060200182810382526038815260200180615bb06038913960400191505060405180910390fd5b50600855612297565b611dbf84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506143249050565b15611e8a5760208114611e035760405162461bcd60e51b8152600401808060200182810382526025815260200180615b8b6025913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091611e419185858083850183828082843760009201919091525061440b92505050565b905060008111611e825760405162461bcd60e51b815260040180806020018281038252602d8152602001806164e7602d913960400191505060405180910390fd5b600a55612297565b611efe84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506143249050565b15611fcb5760208114611f425760405162461bcd60e51b815260040180806020018281038252602c815260200180615b5f602c913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091611f809185858083850183828082843760009201919091525061440b92505050565b9050600d54811115611fc35760405162461bcd60e51b8152600401808060200182810382526049815260200180615cef6049913960600191505060405180910390fd5b600e55612297565b61203484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506143249050565b156120d557602081146120785760405162461bcd60e51b8152600401808060200182810382526025815260200180615dcf6025913960400191505060405180910390fd5b604080516020601f84018190048102820181019092528281526000916120b69185858083850183828082843760009201919091525061440b92505050565b600d819055600e549091508110156120cf57600d54600e555b50612297565b61213984848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506143249050565b1561225a5760208114612193576040805162461bcd60e51b815260206004820181905260248201527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604482015290519081900360640190fd5b604080516020601f84018190048102820181019092528281526000916121d19185858083850183828082843760009201919091525061440b92505050565b9050600081116122125760405162461bcd60e51b8152600401808060200182810382526028815260200180615be86028913960400191505060405180910390fd5b60298111156122525760405162461bcd60e51b8152600401808060200182810382526039815260200180615c106039913960400191505060405180910390fd5b600c55612297565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60046020526000908152604090205481565b6001546060906000805b8281101561236a57612356816111ff565b15612362576001909101905b600101612345565b50606081604051908082528060200260200182016040528015612397578160200160208202803683370190505b5090506000915060005b83811015612416576123b2816111ff565b1561240e57600181815481106123c457fe5b600091825260209091206004909102015482516001600160a01b03909116908390859081106123ef57fe5b6001600160a01b03909216602092830291909101909101526001909201915b6001016123a1565b509250505090565b601581565b61100281565b600061243361233b565b519050600080600c541161244857601561244c565b600c545b90508082111561245a578091505b8161246457600191505b5090565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff16156124dd576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b6124e5615a3e565b600061250b6040518061062001604052806105ef8152602001615e9c6105ef9139612ce0565b915091508061254b5760405162461bcd60e51b8152600401808060200182810382526021815260200180615e7b6021913960400191505060405180910390fd5b60005b8260200151518110156126705760018360200151828151811061256d57fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061264357fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161254e565b50506103e8600255506000805460ff19166001179055565b600d5481565b33611001146126ce5760405162461bcd60e51b81526004018080602001828103825260298152602001806165346029913960400191505060405180910390fd5b600b54612773576126dd6159e0565b60015460005b8181101561276f57600b80546001810182556000919091528351600080516020615e15833981519152601690920291820190815560208501516000805160206165148339815191528301805460ff19169115159190911790556040850151859261276191600080516020615e5b833981519152909101906014615a04565b5050508060010190506126e3565b5050505b600061277e82614410565b905061278981611130565b1561279857612798828261428c565b5050565b606581565b3341146127df5760405162461bcd60e51b815260040180806020018281038252602d8152602001806164ba602d913960400191505060405180910390fd5b60005460ff16612832576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b6000341161287f576040805162461bcd60e51b81526020600482015260156024820152746465706f7369742076616c7565206973207a65726f60581b604482015290519081900360640190fd5b6001600160a01b0381166000908152600460205260409020546007543491906103e89060ff16156128af57506006545b6000831180156128bf5750600081115b156129685760006128e86127106128dc868563ffffffff6145b416565b9063ffffffff61460d16565b905080156129665760405161dead9082156108fc029083906000818181858888f1935050505015801561291f573d6000803e3d6000fd5b506040805182815290517f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee59181900360200190a1612963848263ffffffff61464f16565b93505b505b8115612a6057600060018084038154811061297f57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff16156129ea576040805185815290516001600160a01b038716917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a2612a5a565b6003546129fd908563ffffffff61469116565b6003908155810154612a15908563ffffffff61469116565b60038201556040805185815290516001600160a01b038716917f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc055919081900360200190a25b50612aa0565b6040805184815290516001600160a01b038616917ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b4919081900360200190a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110612ac557fe5b60009182526020909120601690910201805460019091015490915060ff1682565b61100481565b6000600a5460001480612afd575081155b80612b085750600954155b15612b1557506000611115565b600960008154809291906001900391905055506000612b62600a546128dc856128dc600b8981548110612b4457fe5b6000918252602090912060169091020154439063ffffffff61464f16565b90506000600b8581548110612b7357fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015612bd857600080fd5b505afa158015612bec573d6000803e3d6000fd5b505050506040513d6040811015612c0257600080fd5b508051602090910151600095509092509050808310612c9057612c258787613e21565b50604080516305bfb49960e41b81526001600160a01b0389166004820152905161100191635bfb499091602480830192600092919082900301818387803b158015612c6f57600080fd5b505af1158015612c83573d6000803e3d6000fd5b5050505060019350612ca2565b818310612ca257612ca087614410565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b612ce8615a3e565b6000612cf2615a3e565b612cfa615a56565b612d0b612d06866146eb565b614710565b90506000805b612d1a8361475a565b15612e2b5780612d3f57612d35612d308461477b565b6147c9565b60ff168452612e23565b8060011415612e1e576060612d5b612d568561477b565b614880565b90508051604051908082528060200260200182016040528015612d9857816020015b612d85615a76565b815260200190600190039081612d7d5790505b50602086015260005b8151811015612e1357612db2615a76565b6000612dd0848481518110612dc357fe5b6020026020010151614951565b9150915080612ded57876000995099505050505050505050612e34565b8188602001518481518110612dfe57fe5b60209081029190910101525050600101612da1565b506001925050612e23565b612e2b565b600101612d11565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b6060815260200190600190039081612e53579050509050612e798363ffffffff16614a2e565b81600081518110612e8657fe5b602002602001018190525061111581614a41565b6000806060612ea884614acb565b9150915081612f55577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015612f10578181015183820152602001612ef8565b50505050905090810190601f168015612f3d5780820380516001836020036101000a031916815260200191505b509250505060405180910390a16066925050506111fa565b50506060612f6283614bad565b6001549091506000908190815b81811015612fe55767016345785d8a000060018281548110612f8d57fe5b90600052602060002090600402016003015410612faf57600190930192612fdd565b600060018281548110612fbe57fe5b9060005260206000209060040201600301541115612fdd576001909201915b600101612f6f565b50606083604051908082528060200260200182016040528015613012578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015613041578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015613070578160200160208202803683370190505b50905060608660405190808252806020026020018201604052801561309f578160200160208202803683370190505b50905060006060876040519080825280602002602001820160405280156130d0578160200160208202803683370190505b5090506060886040519080825280602002602001820160405280156130ff578160200160208202803683370190505b509050600099506000985060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561314757600080fd5b505afa15801561315b573d6000803e3d6000fd5b505050506040513d602081101561317157600080fd5b5051905067016345785d8a00008111156131e5577f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2604051808060200182810382526021815260200180615df46021913960400191505060405180910390a160689c505050505050505050505050506111fa565b60005b898110156134565767016345785d8a00006001828154811061320657fe5b9060005260206000209060040201600301541061338c576001818154811061322a57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898d8151811061325b57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be4006001838154811061329057fe5b906000526020600020906004020160030154816132a957fe5b06600183815481106132b757fe5b9060005260206000209060040201600301540390506132df838261464f90919063ffffffff16565b898e815181106132eb57fe5b6020026020010181815250506001828154811061330457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316878e8151811061333557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888e8151811061336257fe5b602090810291909101015261337d868263ffffffff61469116565b6001909d019c955061344e9050565b60006001828154811061339b57fe5b906000526020600020906004020160030154111561344e57600181815481106133c057fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848c815181106133f157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506001818154811061341e57fe5b906000526020600020906004020160030154838c8151811061343c57fe5b60209081029190910101526001909a01995b6001016131e8565b5060008415613894576110046001600160a01b0316636e056520868b8b8a60025442016040518663ffffffff1660e01b815260040180806020018060200180602001856001600160401b03166001600160401b03168152602001848103845288818151815260200191508051906020019060200280838360005b838110156134e85781810151838201526020016134d0565b50505050905001848103835287818151815260200191508051906020019060200280838360005b8381101561352757818101518382015260200161350f565b50505050905001848103825286818151815260200191508051906020019060200280838360005b8381101561356657818101518382015260200161354e565b505050509050019750505050505050506020604051808303818588803b15801561358f57600080fd5b505af1935050505080156135b557506040513d60208110156135b057600080fd5b505160015b6137f0576040516000815260443d10156135d15750600061366c565b60046000803e60005160e01c6308c379a081146135f257600091505061366c565b60043d036004833e81513d60248201116001600160401b038211171561361d5760009250505061366c565b80830180516001600160401b0381111561363e57600094505050505061366c565b8060208301013d860181111561365c5760009550505050505061366c565b601f01601f191660405250925050505b80613677575061371b565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280826040518080602001828103825283818151815260200191508051906020019080838360005b838110156136db5781810151838201526020016136c3565b50505050905090810190601f1680156137085780820380516001836020036101000a031916815260200191505b509250505060405180910390a2506137eb565b3d808015613745576040519150601f19603f3d011682016040523d82523d6000602084013e61374a565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040518080602001828103825283818151815260200191508051906020019080838360005b838110156137af578181015183820152602001613797565b50505050905090810190601f1680156137dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b613894565b801561382e576040805187815290517fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b709181900360200190a1613892565b604080516020808252601b908201527f6261746368207472616e736665722072657475726e2066616c7365000000000081830152905187917fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf280919081900360600190a25b505b8015613a4a5760005b8751811015613a485760008882815181106138b457fe5b602002602001015190506000600182815481106138cd57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc91859081106138fe57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f19350505050905080156139ba576001828154811061393f57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d918590811061398e57fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a2613a3e565b600182815481106139c757fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110613a1657fe5b9060005260206000209060040201600301546040518082815260200191505060405180910390a25b505060010161389d565b505b835115613b945760005b8451811015613b92576000858281518110613a6b57fe5b60200260200101516001600160a01b03166108fc868481518110613a8b57fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015613b2157858281518110613ac157fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110613aff57fe5b60200260200101516040518082815260200191505060405180910390a2613b89565b858281518110613b2d57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110613b6b57fe5b60200260200101516040518082815260200191505060405180910390a25b50600101613a54565b505b4715613bfd576040805147815290517f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d9181900360200190a1604051611002904780156108fc02916000818181858888f19350505050158015613bfb573d6000803e3d6000fd5b505b600060038190556005558c5115613c1757613c178d614d7d565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613c5457600080fd5b505af1158015613c68573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a15060009e9d5050505050505050505050505050565b80516001600160a01b0316600090815260046020526040812054801580613cfb5750600180820381548110613cdb57fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15613d415782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a260009150506111fa565b600154600554600019820111801590613d975784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600093505050506111fa565b600580546001908101909155805481906000198601908110613db557fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b60008060018381548110613e3157fe5b90600052602060002090600402016003015490506000600180805490500390506001613e5b61233b565b5111613e9057600060018581548110613e7057fe5b9060005260206000209060040201600301819055506000925050506112aa565b6040805183815290516001600160a01b038716917f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70919081900360200190a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561408d5760018160010181548110613f0857fe5b906000526020600020906004020160018281548110613f2357fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b805490918301908110613fe457fe5b9060005260206000209060160201600b8281548110613fff57fe5b600091825260209091208254601690920201908155600180830154908201805460ff191660ff909216151591909117905561404260028083019084016014615aab565b5090505080600101600460006001848154811061405b57fe5b600091825260208083206004909202909101546001600160a01b03168352820192909252604001902055600101613eea565b50600180548061409957fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806140ec57fe5b60008281526020812060166000199093019283020181815560018101805460ff191690559061411e6002830182615ad6565b50509055600081838161412d57fe5b04905080156141915760015460005b8181101561418e57826001828154811061415257fe5b906000526020600020906004020160030154016001828154811061417257fe5b600091825260209091206003600490920201015560010161413c565b50505b50600195945050505050565b60005b828110156142835760408051602080820189905287840182840152825180830384018152606090920190925280519101206000908390816141dd57fe5b0690508085018287011461427a57600088838801815181106141fb57fe5b60200260200101519050888287018151811061421357fe5b6020026020010151898489018151811061422957fe5b60200260200101906001600160a01b031690816001600160a01b03168152505080898388018151811061425857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050505b506001016141a0565b50505050505050565b600980546001908101909155600b8054839081106142a657fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b82815481106142dc57fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b6000816040516020018082805190602001908083835b602083106143595780518252601f19909201916020918201910161433a565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106143c75780518252601f1990920191602091820191016143a8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b6001600160a01b03811660009081526004602052604081205480614439575060001990506111fa565b60018103905060006001828154811061444e57fe5b906000526020600020906004020160030154905060006001838154811061447157fe5b906000526020600020906004020160030181905550600060018080549050039050846001600160a01b03167f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d836040518082815260200191505060405180910390a2806144e3578293505050506111fa565b60008183816144ee57fe5b04905080156145aa5760005b8481101561454c57816001828154811061451057fe5b906000526020600020906004020160030154016001828154811061453057fe5b60009182526020909120600360049092020101556001016144fa565b50600180549085015b818110156145a757826001828154811061456b57fe5b906000526020600020906004020160030154016001828154811061458b57fe5b6000918252602090912060036004909202010155600101614555565b50505b5091949350505050565b6000826145c3575060006112aa565b828202828482816145d057fe5b04146111155760405162461bcd60e51b8152600401808060200182810382526021815260200180615d806021913960400191505060405180910390fd5b600061111583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250615370565b600061111583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615412565b600082820183811015611115576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6146f3615ae5565b506040805180820190915281518152602082810190820152919050565b614718615a56565b6147218261546c565b61472a57600080fd5b600061473983602001516154a6565b60208085015160408051808201909152868152920190820152915050919050565b6000614764615ae5565b505080518051602091820151919092015191011190565b614783615ae5565b61478c8261475a565b61479557600080fd5b602082015160006147a582615509565b80830160209586015260408051808201909152908152938401919091525090919050565b8051600090158015906147de57508151602110155b6147e757600080fd5b60006147f683602001516154a6565b90508083600001511015614851576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b82516020808501518301805192849003929183101561487757826020036101000a820491505b50949350505050565b606061488b8261546c565b61489457600080fd5b600061489f8361563c565b90506060816040519080825280602002602001820160405280156148dd57816020015b6148ca615ae5565b8152602001906001900390816148c25790505b50905060006148ef85602001516154a6565b60208601510190506000805b848110156149465761490c83615509565b915060405180604001604052808381526020018481525084828151811061492f57fe5b6020908102919091010152918101916001016148fb565b509195945050505050565b614959615a76565b6000614963615a76565b61496b615a56565b61497485614710565b90506000805b6149838361475a565b15612e2b57806149ae5761499e6149998461477b565b615698565b6001600160a01b03168452614a26565b80600114156149d6576149c36149998461477b565b6001600160a01b03166020850152614a26565b80600214156149fe576149eb6149998461477b565b6001600160a01b03166040850152614a26565b8060031415612e1e57614a13612d308461477b565b6001600160401b03166060850152600191505b60010161497a565b60606112aa614a3c836156b2565b615798565b6060815160001415614a6257506040805160008152602081019091526111fa565b606082600081518110614a7157fe5b602002602001015190506000600190505b8351811015614ab257614aa882858381518110614a9b57fe5b60200260200101516157ea565b9150600101614a82565b50611115614ac5825160c060ff16615867565b826157ea565b60006060602983511115614afd576000604051806060016040528060298152602001615c496029913991509150612e34565b60005b8351811015614b935760005b81811015614b8a57848181518110614b2057fe5b6020026020010151600001516001600160a01b0316858381518110614b4157fe5b6020026020010151600001516001600160a01b03161415614b825760006040518060600160405280602b8152602001615c9d602b9139935093505050612e34565b600101614b0c565b50600101614b00565b505060408051602081019091526000815260019150915091565b6060600080808080614bbd612429565b6001549091505b8015614ccb57600181039250600b8381548110614bdd57fe5b600091825260209091206001601690920201015460ff16614bfd57614cc2565b60018381548110614c0a57fe5b60009182526020909120600490910201546001600160a01b03169450614c31858484612aec565b9350831580614c44575060018851038610155b15614c4e57614cc2565b60005b8851811015614cc057856001600160a01b0316898281518110614c7057fe5b6020026020010151600001516001600160a01b03161415614cb8576001898281518110614c9957fe5b6020908102919091010151901515608090910152600190960195614cc0565b600101614c51565b505b60001901614bc4565b5084875103604051908082528060200260200182016040528015614d0957816020015b614cf6615a76565b815260200190600190039081614cee5790505b5095506000915060005b8751811015614d7257878181518110614d2857fe5b602002602001015160800151614d6a57878181518110614d4457fe5b6020026020010151878481518110614d5857fe5b60209081029190910101526001909201915b600101614d13565b505050505050919050565b600154815160005b82811015614e9a576001614d97615a76565b60018381548110614da457fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b84811015614e6e57868181518110614e3457fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415614e665760009250614e6e565b600101614e20565b508115614e905780516001600160a01b03166000908152600460205260408120555b5050600101614d85565b5080821115614f4b57805b82811015614f49576001805480614eb857fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b805480614f0b57fe5b60008281526020812060166000199093019283020181815560018101805460ff1916905590614f3d6002830182615ad6565b50509055600101614ea5565b505b6000818310614f5a5781614f5c565b825b905060005b818110156151565761500e858281518110614f7857fe5b602002602001015160018381548110614f8d57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a082015261595f565b61512957806001016004600087848151811061502657fe5b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555084818151811061506257fe5b60200260200101516001828154811061507757fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015561514e565b60006001828154811061513857fe5b9060005260206000209060040201600301819055505b600101614f61565b50828211156152fb576151676159e0565b835b838110156152f857600186828151811061517f57fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020615e158339815191528101918255918501516000805160206165148339815191528301805491151560ff19909216919091179055918401518492916152b491600080516020615e5b833981519152909101906014615a04565b50505080600101600460008884815181106152cb57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101615169565b50505b6000600981905560015493505b83811015615369576000600b828154811061531f57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061535057fe5b6000918252602090912060169091020155600101615308565b5050505050565b600081836153fc5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156153c15781810151838201526020016153a9565b50505050905090810190601f1680156153ee5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161540857fe5b0495945050505050565b600081848411156154645760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156153c15781810151838201526020016153a9565b505050900390565b805160009061547d575060006111fa565b6020820151805160001a9060c082101561549c576000925050506111fa565b5060019392505050565b8051600090811a60808110156154c05760009150506111fa565b60b88110806154db575060c081108015906154db575060f881105b156154ea5760019150506111fa565b60c08110156154fe5760b5190190506111fa565b60f5190190506111fa565b80516000908190811a60808110156155245760019150615635565b60b881101561553957607e1981019150615635565b60c08110156155b357600060b78203600186019550806020036101000a8651049150600181018201935050808310156155ad576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50615635565b60f88110156155c85760be1981019150615635565b600060f78203600186019550806020036101000a865104915060018101820193505080831015615633576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b805160009061564d575060006111fa565b6000809050600061566184602001516154a6565b602085015185519181019250015b8082101561568f5761568082615509565b6001909301929091019061566f565b50909392505050565b80516000906015146156a957600080fd5b6112aa826147c9565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166156f65750601861571a565b6fffffffffffffffffffffffffffffffff1984166157165750601061571a565b5060005b60208110156157505781818151811061572f57fe5b01602001516001600160f81b0319161561574857615750565b60010161571a565b60008160200390506060816040519080825280601f01601f191660200182016040528015615785576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156157ca5750607f60f81b826000815181106157b857fe5b01602001516001600160f81b03191611155b156157d65750806111fa565b6112aa6157e88351608060ff16615867565b835b6060806040519050835180825260208201818101602087015b8183101561581b578051835260209283019201615803565b50855184518101855292509050808201602086015b81831015615848578051835260209283019201615830565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106158b7576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116159115782840160f81b816000815181106158f357fe5b60200101906001600160f81b031916908160001a90535090506112aa565b606061591c856156b2565b90508381510160370160f81b8260008151811061593557fe5b60200101906001600160f81b031916908160001a90535061595682826157ea565b95945050505050565b805182516000916001600160a01b039182169116148015615999575081602001516001600160a01b031683602001516001600160a01b0316145b80156159be575081604001516001600160a01b031683604001516001600160a01b0316145b80156111155750506060908101519101516001600160401b0390811691161490565b60408051606081018252600080825260208201529081016159ff615aff565b905290565b8260148101928215615a32579160200282015b82811115615a32578251825591602001919060010190615a17565b50612464929150615b1e565b60408051808201909152600081526060602082015290565b6040518060400160405280615a69615ae5565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b8260148101928215615a32579182015b82811115615a32578254825591600101919060010190615abb565b5061140c906014810190615b1e565b604051806040016040528060008152602001600081525090565b6040518061028001604052806014906020820280368337509192915050565b61152891905b808211156124645760008155600101615b2456fe6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d69736d617463686c656e677468206f66206d61784e756d4f66576f726b696e6743616e64696461746573206d69736d617463686c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736d61746368746865206d61784e756d4f664d61696e7461696e696e67206d757374206265206c657373207468616e206e756d4f6643616e696e61746573746865206e756d4f66436162696e657473206d7573742062652067726561746572207468616e2030746865206e756d4f66436162696e657473206d757374206265206c657373207468616e204d41585f4e554d5f4f465f56414c494441544f5253746865206e756d626572206f662076616c696461746f72732065786365656420746865206c696d6974746865206275726e526174696f206d757374206265206e6f2067726561746572207468616e2031303030306475706c696361746520636f6e73656e7375732061646472657373206f662076616c696461746f725365747468652065787069726554696d655365636f6e64476170206973206f7574206f662072616e6765746865206d61784e756d4f66576f726b696e6743616e64696461746573206d757374206265206e6f742067726561746572207468616e206d61784e756d4f6643616e6469646174657363616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616e63656c656e677468206f66206a61696c2076616c696461746f7273206d757374206265206f6e65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736d61746368666565206973206c6172676572207468616e2044555354595f494e434f4d494e470175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db96c656e677468206f662065787069726554696d655365636f6e64476170206d69736d617463680175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb6661696c656420746f20706172736520696e69742076616c696461746f72536574f905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a2000746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d6573736167652073656e646572206d7573742062652074686520626c6f636b2070726f6475636572746865206d61696e7461696e536c6173685363616c65206d7573742062652067726561746572207468616e20300175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dba746865206d6573736167652073656e646572206d75737420626520736c61736820636f6e7472616374a264697066735822122091dd90b1dd27923c787e9f55bd1bebe31e8416465e6ce432022dfeb252e6701e64736f6c63430006040033" }, "0x0000000000000000000000000000000000001001": { "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106102275760003560e01c8063831d65d111610130578063c80d4b8f116100b8578063e1c7392a1161007c578063e1c7392a146106d9578063f9a2bbc7146106e1578063fc3e5908146106e9578063fc4333cd146106f1578063fd6a6879146106f957610227565b8063c80d4b8f14610623578063c81b16621461062b578063c8509d8114610633578063c96be4cb146106ab578063dc927faf146106d157610227565b8063a1a11bf5116100ff578063a1a11bf514610531578063a78abc1614610539578063ab51bb9614610555578063ac0af6291461055d578063ac4317511461056557610227565b8063831d65d11461049f57806396713da9146105195780639bc8e4f2146105215780639dc092621461052957610227565b80634bf6c882116101b35780636e47b482116101825780636e47b4821461047757806370fd5bad1461047f57806375d47a0a146104875780637912a65d1461048f5780637942fd051461049757610227565b80634bf6c8821461045757806351e806721461045f578063567a372d1461046757806362b72cf51461046f57610227565b806337c8dab9116101fa57806337c8dab9146103b9578063389f4f71146103f85780633dffc3871461041257806343756e5c14610430578063493279b11461043857610227565b80630bee7a671461022c5780631182b8751461024d57806323bac5a21461033a57806335aa2e4414610380575b600080fd5b610234610701565b6040805163ffffffff9092168252519081900360200190f35b6102c56004803603604081101561026357600080fd5b60ff8235169190810190604081016020820135600160201b81111561028757600080fd5b82018360208201111561029957600080fd5b803590602001918460018302840111600160201b831117156102ba57600080fd5b509092509050610706565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102ff5781810151838201526020016102e7565b50505050905090810190601f16801561032c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103606004803603602081101561035057600080fd5b50356001600160a01b03166107da565b604080519384526020840192909252151582820152519081900360600190f35b61039d6004803603602081101561039657600080fd5b50356107fd565b604080516001600160a01b039092168252519081900360200190f35b6103df600480360360208110156103cf57600080fd5b50356001600160a01b0316610824565b6040805192835260208301919091528051918290030190f35b61040061087b565b60408051918252519081900360200190f35b61041a610881565b6040805160ff9092168252519081900360200190f35b61039d610886565b61044061088c565b6040805161ffff9092168252519081900360200190f35b61041a610891565b61039d610896565b61040061089c565b6104006108a2565b61039d6108a8565b61041a6108ae565b61039d6108b3565b6104006108b9565b61041a6108be565b610517600480360360408110156104b557600080fd5b60ff8235169190810190604081016020820135600160201b8111156104d957600080fd5b8201836020820111156104eb57600080fd5b803590602001918460018302840111600160201b8311171561050c57600080fd5b5090925090506108c3565b005b61041a610a1e565b610400610a23565b61039d610a2e565b61039d610a34565b610541610a3a565b604080519115158252519081900360200190f35b610234610a43565b610400610a48565b6105176004803603604081101561057b57600080fd5b810190602081018135600160201b81111561059557600080fd5b8201836020820111156105a757600080fd5b803590602001918460018302840111600160201b831117156105c857600080fd5b919390929091602081019035600160201b8111156105e557600080fd5b8201836020820111156105f757600080fd5b803590602001918460018302840111600160201b8311171561061857600080fd5b509092509050610a4d565b610400610e3b565b61039d610e40565b6105176004803603604081101561064957600080fd5b60ff8235169190810190604081016020820135600160201b81111561066d57600080fd5b82018360208201111561067f57600080fd5b803590602001918460018302840111600160201b831117156106a057600080fd5b509092509050610e46565b610517600480360360208110156106c157600080fd5b50356001600160a01b0316610ef9565b61039d61131e565b610517611324565b61039d611395565b61041a61139b565b6105176113a0565b61039d61182b565b606481565b606033612000146107485760405162461bcd60e51b815260040180806020018281038252602f815260200180612282602f913960400191505060405180910390fd5b60005460ff1661078d576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642073796e207061636b6167650000604482015290519081900360640190fd5b600260208190526000918252604090912080546001820154919092015460ff1683565b6001818154811061080a57fe5b6000918252602090912001546001600160a01b0316905081565b60008061082f612146565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b600181565b61100181565b606081565b600881565b61200081565b60045481565b60035481565b61100581565b600281565b61100881565b603281565b600b81565b33612000146109035760405162461bcd60e51b815260040180806020018281038252602f815260200180612282602f913960400191505060405180910390fd5b60005460ff16610948576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b610950612169565b600061099184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061183192505050565b9150915080156109db5781516040805163ffffffff9092168252517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e6299679181900360200190a1610a17565b81516040805163ffffffff9092168252517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e79181900360200190a15b5050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff16610a92576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b3361100714610ad25760405162461bcd60e51b815260040180806020018281038252602e81526020018061220d602e913960400191505060405180910390fd5b610b3d84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b602082015291506118b19050565b15610c165760208114610b815760405162461bcd60e51b81526004018080602001828103825260278152602001806121b66027913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610bbf9185858083850183828082843760009201919091525061199992505050565b905060018110158015610bd3575060055481105b610c0e5760405162461bcd60e51b815260040180806020018281038252602581526020018061225d6025913960400191505060405180910390fd5b600455610da9565b610c7c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b602082015291506118b19050565b15610d6c5760208114610cc05760405162461bcd60e51b815260040180806020018281038252602281526020018061223b6022913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610cfe9185858083850183828082843760009201919091525061199992505050565b90506103e88111158015610d13575060045481115b610d64576040805162461bcd60e51b815260206004820181905260248201527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604482015290519081900360640190fd5b600555610da9565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b609681565b61100281565b3361200014610e865760405162461bcd60e51b815260040180806020018281038252602f815260200180612282602f913960400191505060405180910390fd5b60005460ff16610ecb576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b334114610f375760405162461bcd60e51b815260040180806020018281038252602d8152602001806122b1602d913960400191505060405180910390fd5b60005460ff16610f7c576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b6003544311610fd2576040805162461bcd60e51b815260206004820181905260248201527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604482015290519081900360640190fd5b3a1561101c576040805162461bcd60e51b81526020600482015260146024820152736761737072696365206973206e6f74207a65726f60601b604482015290519081900360640190fd5b611024612146565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff16158015928201929092529061107f5760208101805160010190526110d8565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b4381526005546020820151816110ea57fe5b0661123c57600060208201819052604080516335409f7f60e01b81526001600160a01b03851660048201529051611000926335409f7f926024808201939182900301818387803b15801561113d57600080fd5b505af1158015611151573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b6111718561199e565b60006040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156111d15781810151838201526020016111b9565b50505050905090810190601f1680156111fe5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561121f57600080fd5b505af1158015611233573d6000803e3d6000fd5b505050506112b2565b60045481602001518161124b57fe5b066112b257604080516375abf10160e11b81526001600160a01b038416600482015290516110009163eb57e20291602480830192600092919082900301818387803b15801561129957600080fd5b505af11580156112ad573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505043600355565b61100381565b60005460ff161561137c576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b603260045560966005556000805460ff19166001179055565b61100081565b600381565b33611000146113e05760405162461bcd60e51b81526004018080602001828103825260308152602001806121dd6030913960400191505060405180910390fd5b60005460ff16611425576040805162461bcd60e51b815260206004820152601960248201526000805160206122de833981519152604482015290519081900360640190fd5b60015461143157611829565b600154600090600019015b8082116117fd576000805b8284101561156057611457612146565b600260006001878154811061146857fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff16151590820152600554909150600490048160200151111561154a576004600554816114d557fe5b048160200151038160200181815250508060026000600188815481106114f757fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff1916911515919091179055611554565b6001925050611560565b50600190930192611447565b8284116116f75761156f612146565b600260006001868154811061158057fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff161515908201526005549091506004900481602001511115611668576004600554816115ed57fe5b0481602001510381602001818152505080600260006001878154811061160f57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506116f79050565b600260006001868154811061167957fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054806116bd57fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836116ea57506116f7565b5060001990920191611560565b8180156117015750805b156117e057600260006001868154811061171757fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548490811061175e57fe5b600091825260209091200154600180546001600160a01b03909216918690811061178457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060018054806117bd57fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b826117ec5750506117fd565b50506001909101906000190161143c565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b611839612169565b6000611843612169565b61184b61217b565b61185c61185786611a70565b611a95565b90506000805b61186b83611adf565b156118a457806118975761188661188184611b00565b611b4e565b63ffffffff1684526001915061189c565b6118a4565b600101611862565b5091935090915050915091565b6000816040516020018082805190602001908083835b602083106118e65780518252601f1990920191602091820191016118c7565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106119545780518252601f199092019160209182019101611935565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490505b92915050565b015190565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816119b95790505090506119e2836001600160a01b0316611c05565b816000815181106119ef57fe5b6020026020010181905250611a0343611c28565b81600181518110611a1057fe5b6020908102919091010152611a256060611c28565b81600281518110611a3257fe5b6020026020010181905250611a4642611c28565b81600381518110611a5357fe5b6020026020010181905250611a6781611c3b565b9150505b919050565b611a7861219b565b506040805180820190915281518152602082810190820152919050565b611a9d61217b565b611aa682611cc5565b611aaf57600080fd5b6000611abe8360200151611cff565b60208085015160408051808201909152868152920190820152915050919050565b6000611ae961219b565b505080518051602091820151919092015191011190565b611b0861219b565b611b1182611adf565b611b1a57600080fd5b60208201516000611b2a82611d62565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590611b6357508151602110155b611b6c57600080fd5b6000611b7b8360200151611cff565b90508083600001511015611bd6576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015611bfc57826020036101000a820491505b50949350505050565b60408051600560a21b8318601482015260348101909152606090611a6781611e95565b6060611993611c3683611eeb565b611e95565b6060815160001415611c5c5750604080516000815260208101909152611a6b565b606082600081518110611c6b57fe5b602002602001015190506000600190505b8351811015611cac57611ca282858381518110611c9557fe5b6020026020010151611fd1565b9150600101611c7c565b50611a67611cbf825160c060ff1661204e565b82611fd1565b8051600090611cd657506000611a6b565b6020820151805160001a9060c0821015611cf557600092505050611a6b565b5060019392505050565b8051600090811a6080811015611d19576000915050611a6b565b60b8811080611d34575060c08110801590611d34575060f881105b15611d43576001915050611a6b565b60c0811015611d575760b519019050611a6b565b60f519019050611a6b565b80516000908190811a6080811015611d7d5760019150611e8e565b60b8811015611d9257607e1981019150611e8e565b60c0811015611e0c57600060b78203600186019550806020036101000a865104915060018101820193505080831015611e06576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50611e8e565b60f8811015611e215760be1981019150611e8e565b600060f78203600186019550806020036101000a865104915060018101820193505080831015611e8c576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b606081516001148015611ec75750607f60f81b82600081518110611eb557fe5b01602001516001600160f81b03191611155b15611ed3575080611a6b565b611993611ee58351608060ff1661204e565b83611fd1565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416611f2f57506018611f53565b6fffffffffffffffffffffffffffffffff198416611f4f57506010611f53565b5060005b6020811015611f8957818181518110611f6857fe5b01602001516001600160f81b03191615611f8157611f89565b600101611f53565b60008160200390506060816040519080825280601f01601f191660200182016040528015611fbe576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b81831015612002578051835260209283019201611fea565b50855184518101855292509050808201602086015b8183101561202f578051835260209283019201612017565b508651929092011591909101601f01601f191660405250905092915050565b606068010000000000000000831061209e576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116120f85782840160f81b816000815181106120da57fe5b60200101906001600160f81b031916908160001a9053509050611993565b606061210385611eeb565b90508381510160370160f81b8260008151811061211c57fe5b60200101906001600160f81b031916908160001a90535061213d8282611fd1565b95945050505050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b604051806040016040528061218e61219b565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d69736d61746368746865206d6573736167652073656e646572206d7573742062652076616c696461746f7253657420636f6e7472616374746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746368746865206d697364656d65616e6f725468726573686f6c64206f7574206f662072616e6765746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d6573736167652073656e646572206d7573742062652074686520626c6f636b2070726f647563657274686520636f6e7472616374206e6f7420696e69742079657400000000000000a26469706673582212204ff575d7be356d691e7b7eae41716a4ccc366ec84f8235486e935261df61a18a64736f6c63430006040033" + "code": "0x608060405234801561001057600080fd5b506004361061023d5760003560e01c80638256ace61161013b578063c80d4b8f116100b8578063e1c7392a1161007c578063e1c7392a1461071d578063f9a2bbc714610725578063fc3e59081461072d578063fc4333cd14610735578063fd6a68791461073d5761023d565b8063c80d4b8f14610667578063c81b16621461066f578063c8509d8114610677578063c96be4cb146106ef578063dc927faf146107155761023d565b8063a1a11bf5116100ff578063a1a11bf514610575578063a78abc161461057d578063ab51bb9614610599578063ac0af629146105a1578063ac431751146105a95761023d565b80638256ace6146104dd578063831d65d1146104e557806396713da91461055d5780639bc8e4f2146105655780639dc092621461056d5761023d565b80634bf6c882116101c95780636e47b4821161018d5780636e47b482146104b557806370fd5bad146104bd57806375d47a0a146104c55780637912a65d146104cd5780637942fd05146104d55761023d565b80634bf6c8821461046d57806351e8067214610475578063567a372d1461047d5780635bfb49901461048557806362b72cf5146104ad5761023d565b806337c8dab91161021057806337c8dab9146103cf578063389f4f711461040e5780633dffc3871461042857806343756e5c14610446578063493279b11461044e5761023d565b80630bee7a67146102425780631182b8751461026357806323bac5a21461035057806335aa2e4414610396575b600080fd5b61024a610745565b6040805163ffffffff9092168252519081900360200190f35b6102db6004803603604081101561027957600080fd5b60ff8235169190810190604081016020820135600160201b81111561029d57600080fd5b8201836020820111156102af57600080fd5b803590602001918460018302840111600160201b831117156102d057600080fd5b50909250905061074a565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103155781810151838201526020016102fd565b50505050905090810190601f1680156103425780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103766004803603602081101561036657600080fd5b50356001600160a01b031661081e565b604080519384526020840192909252151582820152519081900360600190f35b6103b3600480360360208110156103ac57600080fd5b5035610841565b604080516001600160a01b039092168252519081900360200190f35b6103f5600480360360208110156103e557600080fd5b50356001600160a01b0316610868565b6040805192835260208301919091528051918290030190f35b6104166108bf565b60408051918252519081900360200190f35b6104306108c5565b6040805160ff9092168252519081900360200190f35b6103b36108ca565b6104566108d0565b6040805161ffff9092168252519081900360200190f35b6104306108d5565b6103b36108da565b6104166108e0565b6104ab6004803603602081101561049b57600080fd5b50356001600160a01b03166108e6565b005b610416610a47565b6103b3610a4d565b610430610a53565b6103b3610a58565b610416610a5e565b610430610a63565b6103f5610a68565b6104ab600480360360408110156104fb57600080fd5b60ff8235169190810190604081016020820135600160201b81111561051f57600080fd5b82018360208201111561053157600080fd5b803590602001918460018302840111600160201b8311171561055257600080fd5b509092509050610a72565b610430610bcc565b610416610bd1565b6103b3610bdc565b6103b3610be2565b610585610be8565b604080519115158252519081900360200190f35b61024a610bf1565b610416610bf6565b6104ab600480360360408110156105bf57600080fd5b810190602081018135600160201b8111156105d957600080fd5b8201836020820111156105eb57600080fd5b803590602001918460018302840111600160201b8311171561060c57600080fd5b919390929091602081019035600160201b81111561062957600080fd5b82018360208201111561063b57600080fd5b803590602001918460018302840111600160201b8311171561065c57600080fd5b509092509050610bfb565b610416610fe9565b6103b3610fee565b6104ab6004803603604081101561068d57600080fd5b60ff8235169190810190604081016020820135600160201b8111156106b157600080fd5b8201836020820111156106c357600080fd5b803590602001918460018302840111600160201b831117156106e457600080fd5b509092509050610ff4565b6104ab6004803603602081101561070557600080fd5b50356001600160a01b03166110a7565b6103b361154a565b6104ab611550565b6103b36115c1565b6104306115c7565b6104ab6115cc565b6103b3611a57565b606481565b6060336120001461078c5760405162461bcd60e51b815260040180806020018281038252602f8152602001806124ae602f913960400191505060405180910390fd5b60005460ff166107d1576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642073796e207061636b6167650000604482015290519081900360640190fd5b600260208190526000918252604090912080546001820154919092015460ff1683565b6001818154811061084e57fe5b6000918252602090912001546001600160a01b0316905081565b600080610873612372565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b600181565b61100181565b603881565b600881565b61200081565b60045481565b33611000146109265760405162461bcd60e51b81526004018080602001828103825260308152602001806124096030913960400191505060405180910390fd5b60005460ff1661096b576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b61200063f7a251d7600b61097e84611a5d565b60006040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156109de5781810151838201526020016109c6565b50505050905090810190601f168015610a0b5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015610a2c57600080fd5b505af1158015610a40573d6000803e3d6000fd5b5050505050565b60035481565b61100581565b600281565b61100881565b603281565b600b81565b6004546005549091565b3361200014610ab25760405162461bcd60e51b815260040180806020018281038252602f8152602001806124ae602f913960400191505060405180910390fd5b60005460ff16610af7576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b610aff612395565b6000610b4084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b2f92505050565b915091508015610b8a5781516040805163ffffffff9092168252517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e6299679181900360200190a1610a40565b81516040805163ffffffff9092168252517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e79181900360200190a15050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff16610c40576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b3361100714610c805760405162461bcd60e51b815260040180806020018281038252602e815260200180612439602e913960400191505060405180910390fd5b610ceb84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b60208201529150611baf9050565b15610dc45760208114610d2f5760405162461bcd60e51b81526004018080602001828103825260278152602001806123e26027913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610d6d91858580838501838280828437600092019190915250611c9792505050565b905060018110158015610d81575060055481105b610dbc5760405162461bcd60e51b81526004018080602001828103825260258152602001806124896025913960400191505060405180910390fd5b600455610f57565b610e2a84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b60208201529150611baf9050565b15610f1a5760208114610e6e5760405162461bcd60e51b81526004018080602001828103825260228152602001806124676022913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610eac91858580838501838280828437600092019190915250611c9792505050565b90506103e88111158015610ec1575060045481115b610f12576040805162461bcd60e51b815260206004820181905260248201527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604482015290519081900360640190fd5b600555610f57565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b609681565b61100281565b33612000146110345760405162461bcd60e51b815260040180806020018281038252602f8152602001806124ae602f913960400191505060405180910390fd5b60005460ff16611079576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b3341146110e55760405162461bcd60e51b815260040180806020018281038252602d8152602001806124dd602d913960400191505060405180910390fd5b60005460ff1661112a576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b6003544311611180576040805162461bcd60e51b815260206004820181905260248201527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604482015290519081900360640190fd5b3a156111ca576040805162461bcd60e51b81526020600482015260146024820152736761737072696365206973206e6f74207a65726f60601b604482015290519081900360640190fd5b6040805163155853f360e21b81526001600160a01b03831660048201529051611000916355614fcc916024808301926020929190829003018186803b15801561121257600080fd5b505afa158015611226573d6000803e3d6000fd5b505050506040513d602081101561123c57600080fd5b505161124757611543565b61124f612372565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff1615801592820192909252906112aa576020810180516001019052611303565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b43815260055460208201518161131557fe5b0661146757600060208201819052604080516335409f7f60e01b81526001600160a01b03851660048201529051611000926335409f7f926024808201939182900301818387803b15801561136857600080fd5b505af115801561137c573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b61139c85611a5d565b60006040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156113fc5781810151838201526020016113e4565b50505050905090810190601f1680156114295780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561144a57600080fd5b505af115801561145e573d6000803e3d6000fd5b505050506114dd565b60045481602001518161147657fe5b066114dd57604080516375abf10160e11b81526001600160a01b038416600482015290516110009163eb57e20291602480830192600092919082900301818387803b1580156114c457600080fd5b505af11580156114d8573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b61100381565b60005460ff16156115a8576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b603260045560966005556000805460ff19166001179055565b61100081565b600381565b336110001461160c5760405162461bcd60e51b81526004018080602001828103825260308152602001806124096030913960400191505060405180910390fd5b60005460ff16611651576040805162461bcd60e51b8152602060048201526019602482015260008051602061250a833981519152604482015290519081900360640190fd5b60015461165d57611a55565b600154600090600019015b808211611a29576000805b8284101561178c57611683612372565b600260006001878154811061169457fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156117765760046005548161170157fe5b0481602001510381602001818152505080600260006001888154811061172357fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff1916911515919091179055611780565b600192505061178c565b50600190930192611673565b8284116119235761179b612372565b60026000600186815481106117ac57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156118945760046005548161181957fe5b0481602001510381602001818152505080600260006001878154811061183b57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506119239050565b60026000600186815481106118a557fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054806118e957fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836119165750611923565b506000199092019161178c565b81801561192d5750805b15611a0c57600260006001868154811061194357fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548490811061198a57fe5b600091825260209091200154600180546001600160a01b0390921691869081106119b057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060018054806119e957fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82611a18575050611a29565b505060019091019060001901611668565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60408051600480825260a08201909252606091829190816020015b6060815260200190600190039081611a78579050509050611aa1836001600160a01b0316611c9c565b81600081518110611aae57fe5b6020026020010181905250611ac243611cbf565b81600181518110611acf57fe5b6020908102919091010152611ae46038611cbf565b81600281518110611af157fe5b6020026020010181905250611b0542611cbf565b81600381518110611b1257fe5b6020026020010181905250611b2681611cd2565b9150505b919050565b611b37612395565b6000611b41612395565b611b496123a7565b611b5a611b5586611d5c565b611d81565b90506000805b611b6983611dcb565b15611ba25780611b9557611b84611b7f84611dec565b611e3a565b63ffffffff16845260019150611b9a565b611ba2565b600101611b60565b5091935090915050915091565b6000816040516020018082805190602001908083835b60208310611be45780518252601f199092019160209182019101611bc5565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310611c525780518252601f199092019160209182019101611c33565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490505b92915050565b015190565b60408051600560a21b8318601482015260348101909152606090611b2681611ef1565b6060611c91611ccd83611f47565b611ef1565b6060815160001415611cf35750604080516000815260208101909152611b2a565b606082600081518110611d0257fe5b602002602001015190506000600190505b8351811015611d4357611d3982858381518110611d2c57fe5b602002602001015161202d565b9150600101611d13565b50611b26611d56825160c060ff166120aa565b8261202d565b611d646123c7565b506040805180820190915281518152602082810190820152919050565b611d896123a7565b611d92826121a2565b611d9b57600080fd5b6000611daa83602001516121dc565b60208085015160408051808201909152868152920190820152915050919050565b6000611dd56123c7565b505080518051602091820151919092015191011190565b611df46123c7565b611dfd82611dcb565b611e0657600080fd5b60208201516000611e168261223f565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590611e4f57508151602110155b611e5857600080fd5b6000611e6783602001516121dc565b90508083600001511015611ec2576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015611ee857826020036101000a820491505b50949350505050565b606081516001148015611f235750607f60f81b82600081518110611f1157fe5b01602001516001600160f81b03191611155b15611f2f575080611b2a565b611c91611f418351608060ff166120aa565b8361202d565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416611f8b57506018611faf565b6fffffffffffffffffffffffffffffffff198416611fab57506010611faf565b5060005b6020811015611fe557818181518110611fc457fe5b01602001516001600160f81b03191615611fdd57611fe5565b600101611faf565b60008160200390506060816040519080825280601f01601f19166020018201604052801561201a576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b8183101561205e578051835260209283019201612046565b50855184518101855292509050808201602086015b8183101561208b578051835260209283019201612073565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106120fa576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116121545782840160f81b8160008151811061213657fe5b60200101906001600160f81b031916908160001a9053509050611c91565b606061215f85611f47565b90508381510160370160f81b8260008151811061217857fe5b60200101906001600160f81b031916908160001a905350612199828261202d565b95945050505050565b80516000906121b357506000611b2a565b6020820151805160001a9060c08210156121d257600092505050611b2a565b5060019392505050565b8051600090811a60808110156121f6576000915050611b2a565b60b8811080612211575060c08110801590612211575060f881105b15612220576001915050611b2a565b60c08110156122345760b519019050611b2a565b60f519019050611b2a565b80516000908190811a608081101561225a576001915061236b565b60b881101561226f57607e198101915061236b565b60c08110156122e957600060b78203600186019550806020036101000a8651049150600181018201935050808310156122e3576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b5061236b565b60f88110156122fe5760be198101915061236b565b600060f78203600186019550806020036101000a865104915060018101820193505080831015612369576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b60405180604001604052806123ba6123c7565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d69736d61746368746865206d6573736167652073656e646572206d7573742062652076616c696461746f7253657420636f6e7472616374746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746368746865206d697364656d65616e6f725468726573686f6c64206f7574206f662072616e6765746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d6573736167652073656e646572206d7573742062652074686520626c6f636b2070726f647563657274686520636f6e7472616374206e6f7420696e69742079657400000000000000a264697066735822122018b8714d9e81a204e6cb56a28d2122ac3178937ed053b34fef2460106855598d64736f6c63430006040033" }, "0x0000000000000000000000000000000000001002": { "balance": "0x0", - "code": "0x60806040526004361061014f5760003560e01c806396713da9116100b6578063c81b16621161006f578063c81b1662146103dc578063dc927faf146103f1578063f9a2bbc714610406578063fb5478b31461041b578063fc3e590814610430578063fd6a68791461044557610193565b806396713da91461033a5780639a99b4f01461034f5780639dc0926214610388578063a1a11bf51461039d578063a78abc16146103b2578063ab51bb96146103c757610193565b806351e806721161010857806351e806721461028a5780636d70f7ae1461029f5780636e47b482146102e657806370fd5bad146102fb57806375d47a0a146103105780637942fd051461032557610193565b80630bee7a67146101985780633a0b0eff146101c65780633dffc387146101ed57806343756e5c14610218578063493279b1146102495780634bf6c8821461027557610193565b366101935734156101915760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b3480156101a457600080fd5b506101ad61045a565b6040805163ffffffff9092168252519081900360200190f35b3480156101d257600080fd5b506101db61045f565b60408051918252519081900360200190f35b3480156101f957600080fd5b50610202610465565b6040805160ff9092168252519081900360200190f35b34801561022457600080fd5b5061022d61046a565b604080516001600160a01b039092168252519081900360200190f35b34801561025557600080fd5b5061025e610470565b6040805161ffff9092168252519081900360200190f35b34801561028157600080fd5b50610202610475565b34801561029657600080fd5b5061022d61047a565b3480156102ab57600080fd5b506102d2600480360360208110156102c257600080fd5b50356001600160a01b0316610480565b604080519115158252519081900360200190f35b3480156102f257600080fd5b5061022d61049e565b34801561030757600080fd5b506102026104a4565b34801561031c57600080fd5b5061022d6104a9565b34801561033157600080fd5b506102026104af565b34801561034657600080fd5b506102026104b4565b34801561035b57600080fd5b506101db6004803603604081101561037257600080fd5b506001600160a01b0381351690602001356104b9565b34801561039457600080fd5b5061022d610664565b3480156103a957600080fd5b5061022d61066a565b3480156103be57600080fd5b506102d2610670565b3480156103d357600080fd5b506101ad610679565b3480156103e857600080fd5b5061022d61067e565b3480156103fd57600080fd5b5061022d610684565b34801561041257600080fd5b5061022d61068a565b34801561042757600080fd5b506101db610690565b34801561043c57600080fd5b5061020261069c565b34801561045157600080fd5b5061022d6106a1565b606481565b60015481565b600181565b61100181565b606081565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b61100881565b600b81565b600981565b6000805460ff1661053657600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166105845760405162461bcd60e51b815260040180806020018281038252602b8152602001806106a8602b913960400191505060405180910390fd5b60004783106105935747610595565b825b9050670de0b6b3a76400008111156105b25750670de0b6b3a76400005b8015610633576040516001600160a01b0385169082156108fc029083906000818181858888f193505050501580156105ee573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a261065d565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b61100781565b61100681565b60005460ff1681565b600081565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b6110048156fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f64a2646970667358221220d0a7618a32d393c0757994fad066c9aaf7342a982498e0748019ec232f5dc86764736f6c63430006040033" + "code": "0x60806040526004361061014f5760003560e01c806396713da9116100b6578063c81b16621161006f578063c81b1662146103dc578063dc927faf146103f1578063f9a2bbc714610406578063fb5478b31461041b578063fc3e590814610430578063fd6a68791461044557610193565b806396713da91461033a5780639a99b4f01461034f5780639dc0926214610388578063a1a11bf51461039d578063a78abc16146103b2578063ab51bb96146103c757610193565b806351e806721161010857806351e806721461028a5780636d70f7ae1461029f5780636e47b482146102e657806370fd5bad146102fb57806375d47a0a146103105780637942fd051461032557610193565b80630bee7a67146101985780633a0b0eff146101c65780633dffc387146101ed57806343756e5c14610218578063493279b1146102495780634bf6c8821461027557610193565b366101935734156101915760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b3480156101a457600080fd5b506101ad61045a565b6040805163ffffffff9092168252519081900360200190f35b3480156101d257600080fd5b506101db61045f565b60408051918252519081900360200190f35b3480156101f957600080fd5b50610202610465565b6040805160ff9092168252519081900360200190f35b34801561022457600080fd5b5061022d61046a565b604080516001600160a01b039092168252519081900360200190f35b34801561025557600080fd5b5061025e610470565b6040805161ffff9092168252519081900360200190f35b34801561028157600080fd5b50610202610475565b34801561029657600080fd5b5061022d61047a565b3480156102ab57600080fd5b506102d2600480360360208110156102c257600080fd5b50356001600160a01b0316610480565b604080519115158252519081900360200190f35b3480156102f257600080fd5b5061022d61049e565b34801561030757600080fd5b506102026104a4565b34801561031c57600080fd5b5061022d6104a9565b34801561033157600080fd5b506102026104af565b34801561034657600080fd5b506102026104b4565b34801561035b57600080fd5b506101db6004803603604081101561037257600080fd5b506001600160a01b0381351690602001356104b9565b34801561039457600080fd5b5061022d610664565b3480156103a957600080fd5b5061022d61066a565b3480156103be57600080fd5b506102d2610670565b3480156103d357600080fd5b506101ad610679565b3480156103e857600080fd5b5061022d61067e565b3480156103fd57600080fd5b5061022d610684565b34801561041257600080fd5b5061022d61068a565b34801561042757600080fd5b506101db610690565b34801561043c57600080fd5b5061020261069c565b34801561045157600080fd5b5061022d6106a1565b606481565b60015481565b600181565b61100181565b603881565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b61100881565b600b81565b600981565b6000805460ff1661053657600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166105845760405162461bcd60e51b815260040180806020018281038252602b8152602001806106a8602b913960400191505060405180910390fd5b60004783106105935747610595565b825b9050670de0b6b3a76400008111156105b25750670de0b6b3a76400005b8015610633576040516001600160a01b0385169082156108fc029083906000818181858888f193505050501580156105ee573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a261065d565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b61100781565b61100681565b60005460ff1681565b600081565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b6110048156fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f64a2646970667358221220c09e2c37549a0aef291c4f977743d3cea839c669624a8cfae895b3979a32800764736f6c63430006040033" }, "0x0000000000000000000000000000000000001003": { "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106102115760003560e01c8063a78abc1611610125578063dda83148116100ad578063e405bbc31161007c578063e405bbc314610681578063ea54b2aa14610689578063f9a2bbc714610691578063fc3e590814610699578063fd6a6879146106a157610211565b8063dda8314814610609578063df5fe7041461062f578063e1c7392a14610655578063e2761af01461065d57610211565b8063c81b1662116100f4578063c81b166214610534578063cba510a91461053c578063d816987914610562578063da8d08f0146105db578063dc927faf1461060157610211565b8063a78abc1614610444578063ab51bb9614610460578063ac43175114610468578063adc879e91461052c57610211565b8063564b81ef116101a857806375d47a0a1161017757806375d47a0a1461041c5780637942fd051461042457806396713da91461042c5780639dc0926214610434578063a1a11bf51461043c57610211565b8063564b81ef146102ca5780635c5ae8db146103475780636e47b4821461040c57806370fd5bad1461041457610211565b806343756e5c116101e457806343756e5c14610277578063493279b11461029b5780634bf6c882146102ba57806351e80672146102c257610211565b80630bee7a67146102165780632657e9b61461023757806333f7798d146102515780633dffc38714610259575b600080fd5b61021e6106a9565b6040805163ffffffff9092168252519081900360200190f35b61023f6106ae565b60408051918252519081900360200190f35b61023f6106b9565b6102616106bf565b6040805160ff9092168252519081900360200190f35b61027f6106c4565b604080516001600160a01b039092168252519081900360200190f35b6102a36106ca565b6040805161ffff9092168252519081900360200190f35b6102616106cf565b61027f6106d4565b6102d26106da565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561030c5781810151838201526020016102f4565b50505050905090810190601f1680156103395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61036d6004803603602081101561035d57600080fd5b50356001600160401b03166107e6565b60405180856001600160401b03166001600160401b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103ce5781810151838201526020016103b6565b50505050905090810190601f1680156103fb5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b61027f6108a1565b6102616108a7565b61027f6108ac565b6102616108b2565b6102616108b7565b61027f6108bc565b61027f6108c2565b61044c6108c8565b604080519115158252519081900360200190f35b61021e6108d1565b61052a6004803603604081101561047e57600080fd5b81019060208101813564010000000081111561049957600080fd5b8201836020820111156104ab57600080fd5b803590602001918460018302840111640100000000831117156104cd57600080fd5b9193909290916020810190356401000000008111156104eb57600080fd5b8201836020820111156104fd57600080fd5b8035906020019184600183028401116401000000008311171561051f57600080fd5b5090925090506108d6565b005b61023f610b8f565b61027f610b95565b61023f6004803603602081101561055257600080fd5b50356001600160401b0316610b9b565b61044c6004803603604081101561057857600080fd5b81019060208101813564010000000081111561059357600080fd5b8201836020820111156105a557600080fd5b803590602001918460018302840111640100000000831117156105c757600080fd5b9193509150356001600160401b0316610bba565b61027f600480360360208110156105f157600080fd5b50356001600160401b031661139b565b61027f6113b6565b61027f6004803603602081101561061f57600080fd5b50356001600160401b03166113bc565b61044c6004803603602081101561064557600080fd5b50356001600160401b03166113e0565b61052a611422565b6106656115c6565b604080516001600160401b039092168252519081900360200190f35b6106656115d5565b6102d26115eb565b61027f611607565b61026161160d565b61027f611612565b606481565b662386f26fc1000081565b60055481565b600181565b61100181565b606081565b600881565b61200081565b604080516020808252818301909252606091829190602082018180368337505060045460208301525090506000805b60208160ff16101561075057828160ff168151811061072457fe5b01602001516001600160f81b0319161561074357600190910190610748565b610750565b600101610709565b5060608160ff166040519080825280601f01601f191660200182016040528015610781576020820181803683370190505b50905060005b8260ff168160ff1610156107dd57838160ff16815181106107a457fe5b602001015160f81c60f81b828260ff16815181106107be57fe5b60200101906001600160f81b031916908160001a905350600101610787565b50925050505b90565b60016020818152600092835260409283902080548184015460028084015460038501805489516101009982161599909902600019011692909204601f81018790048702880187019098528787526001600160401b0390931696919592949091908301828280156108975780601f1061086c57610100808354040283529160200191610897565b820191906000526020600020905b81548152906001019060200180831161087a57829003601f168201915b5050505050905084565b61100581565b600281565b61100881565b600b81565b600981565b61100781565b61100681565b60005460ff1681565b600081565b60005460ff1661092d576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b336110071461096d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806119e4602e913960400191505060405180910390fd5b6109e184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601b81527f726577617264466f7256616c696461746f725365744368616e67650000000000602082015291506116189050565b15610ac05760208114610a255760405162461bcd60e51b815260040180806020018281038252602e815260200180611983602e913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610a63918585808385018382808284376000920191909152506116ff92505050565b9050600081118015610a7d5750670de0b6b3a76400008111155b610ab85760405162461bcd60e51b815260040180806020018281038252602f815260200180611a12602f913960400191505060405180910390fd5b600555610afd565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60045481565b61100281565b6001600160401b03166000908152600160208190526040909120015490565b60408051630a83aaa960e31b815233600482015290516000916110069163541d554891602480820192602092909190829003018186803b158015610bfd57600080fd5b505afa158015610c11573d6000803e3d6000fd5b505050506040513d6020811015610c2757600080fd5b5051610c7a576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b6001600160401b0382166000908152600260205260409020546001600160a01b031615610cee576040805162461bcd60e51b815260206004820152601c60248201527f63616e27742073796e63206475706c6963617465642068656164657200000000604482015290519081900360640190fd5b6003546001600160401b0390811690831611610d3b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611ad16026913960400191505060405180910390fd5b600354600160401b90046001600160401b0316610d56611861565b6001600160401b0382811660009081526001602081815260409283902083516080810185528154909516855280830154858301526002808201548686015260038201805486516101009682161596909602600019011691909104601f81018490048402850184019095528484529093606086019392830182828015610e1c5780601f10610df157610100808354040283529160200191610e1c565b820191906000526020600020905b815481529060010190602001808311610dff57829003601f168201915b50505050508152505090505b836001600160401b0316826001600160401b031610158015610e5957506003546001600160401b0390811690831610155b15610f3a5780516001600160401b0380821660009081526001602081815260409283902083516080810185528154909516855280830154858301526002808201548686015260038201805486516101009682161596909602600019011691909104601f8101849004840285018401909552848452959750939460608601939091830182828015610f2a5780601f10610eff57610100808354040283529160200191610f2a565b820191906000526020600020905b815481529060010190602001808311610f0d57829003601f168201915b5050505050815250509050610e28565b6060810151516110315780516001600160401b03811660009081526001602081815260409283902060030180548451600294821615610100026000190190911693909304601f810183900483028401830190945283835293955090929190830182828015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b505050506060830182905250516110315760405162461bcd60e51b81526004018080602001828103825260218152602001806119626021913960400191505060405180910390fd5b6000816060015151608801905060608787905082016040519080825280601f01601f191660200182016040528015611070576020820181803683370190505b509050600061107e82611704565b905061108c8486838661170a565b6110c75760405162461bcd60e51b815260040180806020018281038252602381526020018061193f6023913960400191505060405180910390fd5b6000838201915061110d8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177692505050565b9450905061111c818386611780565b8251602001935061112b611887565b6110008186866064600019fa61114057600080fd5b805194506000600160f81b8616156111cf5750600554604080516309a99b4f60e41b815233600482015260248101929092525160019161100291639a99b4f0916044808201926020929091908290030181600087803b1580156111a257600080fd5b505af11580156111b6573d6000803e3d6000fd5b505050506040513d60208110156111cc57600080fd5b50505b856001600160401b0316955060208201935060006111ef858884156117c1565b90985090506001600160401b03808216908c161461123e5760405162461bcd60e51b81526004018080602001828103825260338152602001806119b16033913960400191505060405180910390fd5b6001600160401b03808c16600081815260026020818152604080842080546001600160a01b031916331790558e86168e529383526001808252928490208d518154961667ffffffffffffffff199096169590951785558c81015192850192909255918b01519183019190915560608a015180518b93926112c59260038501929101906118a6565b50506003546001600160401b03600160401b9091048116908d161115905061130d576003805467ffffffffffffffff60401b1916600160401b6001600160401b038e16021790555b7f4042c1020a8f410fb1c8859d276ab436aeb2c3074960e48467299cf1c966d3b48b8a8a602001518560405180856001600160401b03166001600160401b03168152602001846001600160401b03166001600160401b031681526020018381526020018215151515815260200194505050505060405180910390a15060019c9b505050505050505050505050565b6002602052600090815260409020546001600160a01b031681565b61100381565b6001600160401b03166000908152600260205260409020546001600160a01b031690565b6001600160401b0381166000908152600260205260408120546001600160a01b031615158061141c57506003546001600160401b038381169116145b92915050565b60005460ff161561147a576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b60008061149e6040518060c0016040528060908152602001611a4160909139611776565b815160045590925090506114b0611861565b60006114be848460006117c1565b60008083526001600160401b038281168252600160208181526040938490208651815467ffffffffffffffff191694169390931783558086015191830191909155918401516002820155606084015180519496509294508593909261152a9260038501929101906118a6565b50506003805467ffffffffffffffff19166001600160401b0384811691821767ffffffffffffffff60401b1916600160401b9290920291909117918290556000805460ff19166001179055662386f26fc10000600555602085810151604080519490931684529083015280517f5ac9b37d571677b80957ca05693f371526c602fd08042b416a29fdab7efefa499350918290030190a150505050565b6003546001600160401b031681565b600354600160401b90046001600160401b031681565b6040518060c0016040528060908152602001611a416090913981565b61100081565b600381565b61100481565b6000816040516020018082805190602001908083835b6020831061164d5780518252601f19909201916020918201910161162e565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106116bb5780518252601f19909201916020918201910161169c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b60200190565b60008460600151518284010392506000806117288760600151611776565b9092509050611738828683611780565b5050506040840151601f1983810191909152602090940151603f19830152605f19820192909252600454606719820152910160871990910152600190565b8051602090910191565b5b602081106117a0578251825260209283019290910190601f1901611781565b915181516020939093036101000a6000190180199091169216919091179052565b6117c9611861565b60088401516028850151604890950180519095600092916117e8611861565b6020810183905260408101829052866118535760008060688a036040519080825280601f01601f19166020018201604052801561182c576020820181803683370190505b506060840181905261183d90611776565b909250905061185060208c018383611780565b50505b989297509195505050505050565b604080516080810182526000808252602082018190529181019190915260608082015290565b6040518061100001604052806080906020820280368337509192915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106118e757805160ff1916838001178555611914565b82800160010185558215611914579182015b828111156119145782518255916020019190600101906118f9565b50611920929150611924565b5090565b6107e391905b80821115611920576000815560010161192a56fe6661696c656420746f2073657269616c697a6520636f6e73656e7375732073746174656661696c656420746f206c6f61642076616c696461746f722073657420646174616c656e677468206f6620726577617264466f7256616c696461746f725365744368616e6765206d69736d617463686865616465722068656967687420646f65736e277420657175616c20746f207468652073706563696669656420686569676874746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374746865206e6577526577617264466f7256616c696461746f725365744368616e6765206f7574206f662072616e676542696e616e63652d436861696e2d4e696c650000000000000000000000000000000000000000000229eca254b3859bffefaf85f4c95da9fbd26527766b784272789c30ec56b380b6eb96442aaab207bc59978ba3dd477690f5c5872334fc39e627723daa97e441e88ba4515150ec3182bc82593df36f8abb25a619187fcfab7e552b94e64ed2deed000000e8d4a5100063616e27742073796e6320686561646572206265666f726520696e697469616c486569676874a2646970667358221220dea4b59b6b1f87bcf2e2fcaabe5efd443de06a15ee0c510636cd66f03a6f47cc64736f6c63430006040033" + "code": "0x608060405234801561001057600080fd5b50600436106102115760003560e01c8063a78abc1611610125578063dda83148116100ad578063e405bbc31161007c578063e405bbc314610681578063ea54b2aa14610689578063f9a2bbc714610691578063fc3e590814610699578063fd6a6879146106a157610211565b8063dda8314814610609578063df5fe7041461062f578063e1c7392a14610655578063e2761af01461065d57610211565b8063c81b1662116100f4578063c81b166214610534578063cba510a91461053c578063d816987914610562578063da8d08f0146105db578063dc927faf1461060157610211565b8063a78abc1614610444578063ab51bb9614610460578063ac43175114610468578063adc879e91461052c57610211565b8063564b81ef116101a857806375d47a0a1161017757806375d47a0a1461041c5780637942fd051461042457806396713da91461042c5780639dc0926214610434578063a1a11bf51461043c57610211565b8063564b81ef146102ca5780635c5ae8db146103475780636e47b4821461040c57806370fd5bad1461041457610211565b806343756e5c116101e457806343756e5c14610277578063493279b11461029b5780634bf6c882146102ba57806351e80672146102c257610211565b80630bee7a67146102165780632657e9b61461023757806333f7798d146102515780633dffc38714610259575b600080fd5b61021e6106a9565b6040805163ffffffff9092168252519081900360200190f35b61023f6106ae565b60408051918252519081900360200190f35b61023f6106b9565b6102616106bf565b6040805160ff9092168252519081900360200190f35b61027f6106c4565b604080516001600160a01b039092168252519081900360200190f35b6102a36106ca565b6040805161ffff9092168252519081900360200190f35b6102616106cf565b61027f6106d4565b6102d26106da565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561030c5781810151838201526020016102f4565b50505050905090810190601f1680156103395780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61036d6004803603602081101561035d57600080fd5b50356001600160401b03166107e6565b60405180856001600160401b03166001600160401b0316815260200184815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103ce5781810151838201526020016103b6565b50505050905090810190601f1680156103fb5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390f35b61027f6108a1565b6102616108a7565b61027f6108ac565b6102616108b2565b6102616108b7565b61027f6108bc565b61027f6108c2565b61044c6108c8565b604080519115158252519081900360200190f35b61021e6108d1565b61052a6004803603604081101561047e57600080fd5b81019060208101813564010000000081111561049957600080fd5b8201836020820111156104ab57600080fd5b803590602001918460018302840111640100000000831117156104cd57600080fd5b9193909290916020810190356401000000008111156104eb57600080fd5b8201836020820111156104fd57600080fd5b8035906020019184600183028401116401000000008311171561051f57600080fd5b5090925090506108d6565b005b61023f610b8f565b61027f610b95565b61023f6004803603602081101561055257600080fd5b50356001600160401b0316610b9b565b61044c6004803603604081101561057857600080fd5b81019060208101813564010000000081111561059357600080fd5b8201836020820111156105a557600080fd5b803590602001918460018302840111640100000000831117156105c757600080fd5b9193509150356001600160401b0316610bba565b61027f600480360360208110156105f157600080fd5b50356001600160401b031661139b565b61027f6113b6565b61027f6004803603602081101561061f57600080fd5b50356001600160401b03166113bc565b61044c6004803603602081101561064557600080fd5b50356001600160401b03166113e0565b61052a611422565b6106656115c9565b604080516001600160401b039092168252519081900360200190f35b6106656115d8565b6102d26115ee565b61027f61160d565b610261611613565b61027f611618565b606481565b662386f26fc1000081565b60055481565b600181565b61100181565b603881565b600881565b61200081565b604080516020808252818301909252606091829190602082018180368337505060045460208301525090506000805b60208160ff16101561075057828160ff168151811061072457fe5b01602001516001600160f81b0319161561074357600190910190610748565b610750565b600101610709565b5060608160ff166040519080825280601f01601f191660200182016040528015610781576020820181803683370190505b50905060005b8260ff168160ff1610156107dd57838160ff16815181106107a457fe5b602001015160f81c60f81b828260ff16815181106107be57fe5b60200101906001600160f81b031916908160001a905350600101610787565b50925050505b90565b60016020818152600092835260409283902080548184015460028084015460038501805489516101009982161599909902600019011692909204601f81018790048702880187019098528787526001600160401b0390931696919592949091908301828280156108975780601f1061086c57610100808354040283529160200191610897565b820191906000526020600020905b81548152906001019060200180831161087a57829003601f168201915b5050505050905084565b61100581565b600281565b61100881565b600b81565b600981565b61100781565b61100681565b60005460ff1681565b600081565b60005460ff1661092d576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b336110071461096d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806119ea602e913960400191505060405180910390fd5b6109e184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601b81527f726577617264466f7256616c696461746f725365744368616e676500000000006020820152915061161e9050565b15610ac05760208114610a255760405162461bcd60e51b815260040180806020018281038252602e815260200180611989602e913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610a639185858083850183828082843760009201919091525061170592505050565b9050600081118015610a7d5750670de0b6b3a76400008111155b610ab85760405162461bcd60e51b815260040180806020018281038252602f815260200180611a18602f913960400191505060405180910390fd5b600555610afd565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60045481565b61100281565b6001600160401b03166000908152600160208190526040909120015490565b60408051630a83aaa960e31b815233600482015290516000916110069163541d554891602480820192602092909190829003018186803b158015610bfd57600080fd5b505afa158015610c11573d6000803e3d6000fd5b505050506040513d6020811015610c2757600080fd5b5051610c7a576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b6001600160401b0382166000908152600260205260409020546001600160a01b031615610cee576040805162461bcd60e51b815260206004820152601c60248201527f63616e27742073796e63206475706c6963617465642068656164657200000000604482015290519081900360640190fd5b6003546001600160401b0390811690831611610d3b5760405162461bcd60e51b8152600401808060200182810382526026815260200180611a476026913960400191505060405180910390fd5b600354600160401b90046001600160401b0316610d56611867565b6001600160401b0382811660009081526001602081815260409283902083516080810185528154909516855280830154858301526002808201548686015260038201805486516101009682161596909602600019011691909104601f81018490048402850184019095528484529093606086019392830182828015610e1c5780601f10610df157610100808354040283529160200191610e1c565b820191906000526020600020905b815481529060010190602001808311610dff57829003601f168201915b50505050508152505090505b836001600160401b0316826001600160401b031610158015610e5957506003546001600160401b0390811690831610155b15610f3a5780516001600160401b0380821660009081526001602081815260409283902083516080810185528154909516855280830154858301526002808201548686015260038201805486516101009682161596909602600019011691909104601f8101849004840285018401909552848452959750939460608601939091830182828015610f2a5780601f10610eff57610100808354040283529160200191610f2a565b820191906000526020600020905b815481529060010190602001808311610f0d57829003601f168201915b5050505050815250509050610e28565b6060810151516110315780516001600160401b03811660009081526001602081815260409283902060030180548451600294821615610100026000190190911693909304601f810183900483028401830190945283835293955090929190830182828015610fe95780601f10610fbe57610100808354040283529160200191610fe9565b820191906000526020600020905b815481529060010190602001808311610fcc57829003601f168201915b505050506060830182905250516110315760405162461bcd60e51b81526004018080602001828103825260218152602001806119686021913960400191505060405180910390fd5b6000816060015151608801905060608787905082016040519080825280601f01601f191660200182016040528015611070576020820181803683370190505b509050600061107e8261170a565b905061108c84868386611710565b6110c75760405162461bcd60e51b81526004018080602001828103825260238152602001806119456023913960400191505060405180910390fd5b6000838201915061110d8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061177c92505050565b9450905061111c818386611786565b8251602001935061112b61188d565b6110008186866064600019fa61114057600080fd5b805194506000600160f81b8616156111cf5750600554604080516309a99b4f60e41b815233600482015260248101929092525160019161100291639a99b4f0916044808201926020929091908290030181600087803b1580156111a257600080fd5b505af11580156111b6573d6000803e3d6000fd5b505050506040513d60208110156111cc57600080fd5b50505b856001600160401b0316955060208201935060006111ef858884156117c7565b90985090506001600160401b03808216908c161461123e5760405162461bcd60e51b81526004018080602001828103825260338152602001806119b76033913960400191505060405180910390fd5b6001600160401b03808c16600081815260026020818152604080842080546001600160a01b031916331790558e86168e529383526001808252928490208d518154961667ffffffffffffffff199096169590951785558c81015192850192909255918b01519183019190915560608a015180518b93926112c59260038501929101906118ac565b50506003546001600160401b03600160401b9091048116908d161115905061130d576003805467ffffffffffffffff60401b1916600160401b6001600160401b038e16021790555b7f4042c1020a8f410fb1c8859d276ab436aeb2c3074960e48467299cf1c966d3b48b8a8a602001518560405180856001600160401b03166001600160401b03168152602001846001600160401b03166001600160401b031681526020018381526020018215151515815260200194505050505060405180910390a15060019c9b505050505050505050505050565b6002602052600090815260409020546001600160a01b031681565b61100381565b6001600160401b03166000908152600260205260409020546001600160a01b031690565b6001600160401b0381166000908152600260205260408120546001600160a01b031615158061141c57506003546001600160401b038381169116145b92915050565b60005460ff161561147a576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b6000806114a16040518061024001604052806102208152602001611a6d610220913961177c565b815160045590925090506114b3611867565b60006114c1848460006117c7565b60008083526001600160401b038281168252600160208181526040938490208651815467ffffffffffffffff191694169390931783558086015191830191909155918401516002820155606084015180519496509294508593909261152d9260038501929101906118ac565b50506003805467ffffffffffffffff19166001600160401b0384811691821767ffffffffffffffff60401b1916600160401b9290920291909117918290556000805460ff19166001179055662386f26fc10000600555602085810151604080519490931684529083015280517f5ac9b37d571677b80957ca05693f371526c602fd08042b416a29fdab7efefa499350918290030190a150505050565b6003546001600160401b031681565b600354600160401b90046001600160401b031681565b6040518061024001604052806102208152602001611a6d610220913981565b61100081565b600381565b61100481565b6000816040516020018082805190602001908083835b602083106116535780518252601f199092019160209182019101611634565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b602083106116c15780518252601f1990920191602091820191016116a2565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b60200190565b600084606001515182840103925060008061172e876060015161177c565b909250905061173e828683611786565b5050506040840151601f1983810191909152602090940151603f19830152605f19820192909252600454606719820152910160871990910152600190565b8051602090910191565b5b602081106117a6578251825260209283019290910190601f1901611787565b915181516020939093036101000a6000190180199091169216919091179052565b6117cf611867565b60088401516028850151604890950180519095600092916117ee611867565b6020810183905260408101829052866118595760008060688a036040519080825280601f01601f191660200182016040528015611832576020820181803683370190505b50606084018190526118439061177c565b909250905061185660208c018383611786565b50505b989297509195505050505050565b604080516080810182526000808252602082018190529181019190915260608082015290565b6040518061100001604052806080906020820280368337509192915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106118ed57805160ff191683800117855561191a565b8280016001018555821561191a579182015b8281111561191a5782518255916020019190600101906118ff565b5061192692915061192a565b5090565b6107e391905b80821115611926576000815560010161193056fe6661696c656420746f2073657269616c697a6520636f6e73656e7375732073746174656661696c656420746f206c6f61642076616c696461746f722073657420646174616c656e677468206f6620726577617264466f7256616c696461746f725365744368616e6765206d69736d617463686865616465722068656967687420646f65736e277420657175616c20746f207468652073706563696669656420686569676874746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374746865206e6577526577617264466f7256616c696461746f725365744368616e6765206f7574206f662072616e676563616e27742073796e6320686561646572206265666f726520696e697469616c48656967687442696e616e63652d436861696e2d5469677269730000000000000000000000000000000006915167cedaf7bbf7df47d932fdda630527ee648562cf3e52c5e5f46156a3a971a4ceb443c53a50d8653ef8cf1e5716da68120fb51b636dc6d111ec3277b098ecd42d49d3769d8a1f78b4c17a965f7a30d4181fabbd1f969f46d3c8e83b5ad4845421d8000000e8d4a510002ba4e81542f437b7ae1f8a35ddb233c789a8dc22734377d9b6d63af1ca403b61000000e8d4a51000df8da8c5abfdb38595391308bb71e5a1e0aabdc1d0cf38315d50d6be939b2606000000e8d4a51000b6619edca4143484800281d698b70c935e9152ad57b31d85c05f2f79f64b39f3000000e8d4a510009446d14ad86c8d2d74780b0847110001a1c2e252eedfea4753ebbbfce3a22f52000000e8d4a510000353c639f80cc8015944436dab1032245d44f912edc31ef668ff9f4a45cd0599000000e8d4a51000e81d3797e0544c3a718e1f05f0fb782212e248e784c1a851be87e77ae0db230e000000e8d4a510005e3fcda30bd19d45c4b73688da35e7da1fce7c6859b2c1f20ed5202d24144e3e000000e8d4a51000b06a59a2d75bf5d014fce7c999b5e71e7a960870f725847d4ba3235baeaa08ef000000e8d4a510000c910e2fe650e4e01406b3310b489fb60a84bc3ff5c5bee3a56d5898b6a8af32000000e8d4a5100071f2d7b8ec1c8b99a653429b0118cd201f794f409d0fea4d65b1b662f2b00063000000e8d4a51000a264697066735822122032fc162aed7c2a4fe0f40397d327efc38d8aaf5dbdd1720f7f5d8101877da61d64736f6c63430006040033" }, "0x0000000000000000000000000000000000001004": { "balance": "176405560900000000000000000", - "code": "0x60806040526004361061031e5760003560e01c80639a99b4f0116101ab578063bd466461116100f7578063f014847211610095578063fc1a598f1161006f578063fc1a598f14610cb3578063fc3e590814610996578063fd6a687914610ce6578063ff9c00271461068657610366565b8063f014847214610c74578063f9a2bbc714610c89578063fa9e915914610c9e57610366565b8063d9e6dae9116100d1578063d9e6dae914610608578063dc927faf14610c35578063e1c7392a14610c4a578063ebf71d5314610c5f57610366565b8063bd46646114610b68578063c81b166214610b9b578063c8509d8114610bb057610366565b8063aa7415f511610164578063b99328c51161013e578063b99328c514610ad2578063b9fd21e314610b0b578063ba35ead614610b20578063bbface1f14610b3557610366565b8063aa7415f5146109ab578063ab51bb96146109f2578063ac43175114610a0757610366565b80639a99b4f0146109095780639dc0926214610942578063a1a11bf514610957578063a496fba21461096c578063a78abc1614610981578063a7c9f02d1461099657610366565b8063613684751161026a57806375d47a0a116102235780638b87b21f116101fd5780638b87b21f146105875780638eff336c146108a057806396713da9146108df5780639a854bbd146108f457610366565b806375d47a0a146107f15780637942fd0514610806578063831d65d11461081b57610366565b8063613684751461060857806366dea52a146106865780636e0565201461069b5780636e47b482146107c757806370fd5bad1461068657806371d30863146107dc57610366565b806343a368b9116102d757806350432d32116102b157806350432d321461061d57806351e806721461063257806359b92789146106475780635d499b1b1461067157610366565b806343a368b9146105c7578063493279b1146105dc5780634bf6c8821461060857610366565b80630bee7a671461036b5780631182b87514610399578063149d14d9146104935780633d713223146104ba5780633dffc3871461058757806343756e5c146105b257610366565b36610366573415610364576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561037757600080fd5b50610380610cfb565b6040805163ffffffff9092168252519081900360200190f35b3480156103a557600080fd5b5061041e600480360360408110156103bc57600080fd5b60ff8235169190810190604081016020820135600160201b8111156103e057600080fd5b8201836020820111156103f257600080fd5b803590602001918460018302840111600160201b8311171561041357600080fd5b509092509050610d00565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610458578181015183820152602001610440565b50505050905090810190601f1680156104855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561049f57600080fd5b506104a8610e2e565b60408051918252519081900360200190f35b3480156104c657600080fd5b5061056b600480360360208110156104dd57600080fd5b810190602081018135600160201b8111156104f757600080fd5b82018360208201111561050957600080fd5b803590602001918460018302840111600160201b8311171561052a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610e34945050505050565b604080516001600160a01b039092168252519081900360200190f35b34801561059357600080fd5b5061059c610e58565b6040805160ff9092168252519081900360200190f35b3480156105be57600080fd5b5061056b610e5d565b3480156105d357600080fd5b506104a8610e63565b3480156105e857600080fd5b506105f1610e6f565b6040805161ffff9092168252519081900360200190f35b34801561061457600080fd5b5061059c610e74565b34801561062957600080fd5b506104a8610e79565b34801561063e57600080fd5b5061056b610e84565b34801561065357600080fd5b5061056b6004803603602081101561066a57600080fd5b5035610e8a565b34801561067d57600080fd5b506104a8610ea5565b34801561069257600080fd5b5061059c610eae565b6107b3600480360360808110156106b157600080fd5b810190602081018135600160201b8111156106cb57600080fd5b8201836020820111156106dd57600080fd5b803590602001918460208302840111600160201b831117156106fe57600080fd5b919390929091602081019035600160201b81111561071b57600080fd5b82018360208201111561072d57600080fd5b803590602001918460208302840111600160201b8311171561074e57600080fd5b919390929091602081019035600160201b81111561076b57600080fd5b82018360208201111561077d57600080fd5b803590602001918460208302840111600160201b8311171561079e57600080fd5b91935091503567ffffffffffffffff16610eb3565b604080519115158252519081900360200190f35b3480156107d357600080fd5b5061056b611388565b3480156107e857600080fd5b506104a861138e565b3480156107fd57600080fd5b5061056b611394565b34801561081257600080fd5b5061059c61139a565b34801561082757600080fd5b506103646004803603604081101561083e57600080fd5b60ff8235169190810190604081016020820135600160201b81111561086257600080fd5b82018360208201111561087457600080fd5b803590602001918460018302840111600160201b8311171561089557600080fd5b50909250905061139f565b3480156108ac57600080fd5b50610364600480360360608110156108c357600080fd5b508035906001600160a01b0360208201351690604001356114e8565b3480156108eb57600080fd5b5061059c61156e565b34801561090057600080fd5b506104a8611573565b34801561091557600080fd5b506104a86004803603604081101561092c57600080fd5b506001600160a01b03813516906020013561157f565b34801561094e57600080fd5b5061056b6116bd565b34801561096357600080fd5b5061056b6116c3565b34801561097857600080fd5b5061059c6116c9565b34801561098d57600080fd5b506107b36116ce565b3480156109a257600080fd5b5061059c6116d7565b6107b3600480360360808110156109c157600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166116dc565b3480156109fe57600080fd5b506103806116c9565b348015610a1357600080fd5b5061036460048036036040811015610a2a57600080fd5b810190602081018135600160201b811115610a4457600080fd5b820183602082011115610a5657600080fd5b803590602001918460018302840111600160201b83111715610a7757600080fd5b919390929091602081019035600160201b811115610a9457600080fd5b820183602082011115610aa657600080fd5b803590602001918460018302840111600160201b83111715610ac757600080fd5b509092509050611d9d565b348015610ade57600080fd5b5061036460048036036040811015610af557600080fd5b50803590602001356001600160a01b031661200c565b348015610b1757600080fd5b506104a8612082565b348015610b2c57600080fd5b506104a861208c565b348015610b4157600080fd5b506104a860048036036020811015610b5857600080fd5b50356001600160a01b0316612092565b348015610b7457600080fd5b506104a860048036036020811015610b8b57600080fd5b50356001600160a01b03166120a4565b348015610ba757600080fd5b5061056b6120bf565b348015610bbc57600080fd5b5061036460048036036040811015610bd357600080fd5b60ff8235169190810190604081016020820135600160201b811115610bf757600080fd5b820183602082011115610c0957600080fd5b803590602001918460018302840111600160201b83111715610c2a57600080fd5b5090925090506120c5565b348015610c4157600080fd5b5061056b612195565b348015610c5657600080fd5b5061036461219b565b348015610c6b57600080fd5b5061059c61223b565b348015610c8057600080fd5b5061059c612240565b348015610c9557600080fd5b5061056b612245565b348015610caa57600080fd5b506104a861224b565b348015610cbf57600080fd5b5061041e60048036036020811015610cd657600080fd5b50356001600160a01b0316612251565b348015610cf257600080fd5b5061056b612378565b606481565b60005460609060ff16610d48576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b3361200014610d885760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff841660021415610dda57610dd383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237e92505050565b9050610e27565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b60015490565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b61100181565b670de0b6b3a764000081565b606081565b600881565b66071afd498d000081565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b600281565b6000805460ff16610ef9576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b868514610f375760405162461bcd60e51b815260040180806020018281038252603b81526020018061471b603b913960400191505060405180910390fd5b868314610f755760405162461bcd60e51b815260040180806020018281038252603f8152602001806145ee603f913960400191505060405180910390fd5b426078018267ffffffffffffffff161015610fc15760405162461bcd60e51b81526004018080602001828103825260248152602001806144de6024913960400191505060405180910390fd5b6402540be4003406156110055760405162461bcd60e51b815260040180806020018281038252604081526020018061481e6040913960400191505060405180910390fd5b60408051868152602080880282010190915285906000908190606090848015611038578160200160208202803683370190505b50905060005b84811015611113576402540be4008b8b8381811061105857fe5b905060200201358161106657fe5b06156110a35760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b6110c88b8b838181106110b257fe5b90506020020135856124a290919063ffffffff16565b93506110f46402540be4008c8c848181106110df57fe5b905060200201356124fc90919063ffffffff16565b82828151811061110057fe5b602090810291909101015260010161103e565b506001546111389061112b908663ffffffff61253e16565b849063ffffffff6124a216565b3410156111765760405162461bcd60e51b81526004018080602001828103825260568152602001806147c86056913960600191505060405180910390fd5b611186348463ffffffff61259716565b9150611190614337565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d76003611254846125d9565b611269876402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156112c75781810151838201526020016112af565b50505050905090810190601f1680156112f45780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561131557600080fd5b505af1158015611329573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b60015481565b61100881565b600b81565b60005460ff166113e4576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b33612000146114245760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061289492505050565b6114e3565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b33611008146115285760405162461bcd60e51b81526004018080602001828103825260238152602001806147856023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b600981565b677ce66c50e284000081565b6000805460ff166115c5576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b33611005146116055760405162461bcd60e51b815260040180806020018281038252602f815260200180614451602f913960400191505060405180910390fd5b60004783106116145747611616565b825b9050670de0b6b3a76400008111156116325760009150506116b7565b80156116b4576040516001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561166e573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60005460ff1681565b600381565b6000805460ff16611722576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b426078018267ffffffffffffffff16101561176e5760405162461bcd60e51b81526004018080602001828103825260248152602001806144de6024913960400191505060405180910390fd5b6402540be4003406156117b25760405162461bcd60e51b815260040180806020018281038252604081526020018061481e6040913960400191505060405180910390fd5b600080806001600160a01b038816611891576001546117d890879063ffffffff6124a216565b3410156118165760405162461bcd60e51b81526004018080602001828103825260618152602001806145686061913960800191505060405180910390fd5b6402540be40086061561185a5760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b61186a348763ffffffff61259716565b9050611881866402540be40063ffffffff6124fc16565b6221272160e91b93509150611b34565b6001600160a01b0388166000908152600360205260409020549250826118e85760405162461bcd60e51b81526004018080602001828103825260318152602001806145376031913960400191505060405180910390fd5b6001543410156119295760405162461bcd60e51b815260040180806020018281038252603f81526020018061468a603f913960400191505060405180910390fd5b506001600160a01b038716600090815260026020526040902054349060088111158061197457506008811180156119745750611972876007198301600a0a63ffffffff6128f016565b155b6119af5760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b6119b98782612932565b92506119c484612972565b15611a0c576305f5e100831015611a0c5760405162461bcd60e51b815260040180806020018281038252603a815260200180614480603a913960400191505060405180910390fd5b600881101580611a265750600881108015611a2657508683115b611a615760405162461bcd60e51b81526004018080602001828103825260258152602001806145c96025913960400191505060405180910390fd5b677ce66c50e2840000831115611aa85760405162461bcd60e51b81526004018080602001828103825260358152602001806145026035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b038b16916323b872dd9160648083019260209291908290030181600087803b158015611afd57600080fd5b505af1158015611b11573d6000803e3d6000fd5b505050506040513d6020811015611b2757600080fd5b5051611b3257600080fd5b505b611b3c614337565b6040805160c0810182528581526001600160a01b038b166020820152815160018082528184018452919283019181602001602082028036833750505081526040805160018082528183019092526020928301929091908083019080368337505050815260408051600180825281830190925260209283019290919080830190803683370190505081526020018767ffffffffffffffff168152509050828160400151600081518110611bea57fe5b602002602001018181525050878160600151600081518110611c0857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110611c3a57fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003611c65846125d9565b611c7a866402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611cd8578181015183820152602001611cc0565b50505050905090810190601f168015611d055780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611d2657600080fd5b505af1158015611d3a573d6000803e3d6000fd5b5050604080516001600160a01b038d1681523360208201528082018b90526060810186905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a150600198975050505050505050565b3361100714611ddd5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146c9602e913960400191505060405180910390fd5b60208114611e32576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b811415611f3a576020820151670de0b6b3a76400008111801590611ee157506402540be4008106155b611f32576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155611f77565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b336110081461204c5760405162461bcd60e51b81526004018080602001828103825260238152602001806147856023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b0392909216835260039052812055565b6221272160e91b81565b61c35081565b60026020526000908152604090205481565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff1661210a576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b336120001461214a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a7892505050565b61100381565b60005460ff16156121f3576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66071afd498d000060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b600481565b600581565b61100081565b61271081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff1610156122e157828160ff16815181106122b557fe5b01602001516001600160f81b031916156122d4576001909101906122d9565b6122e1565b60010161229a565b5060608160ff166040519080825280601f01601f191660200182016040528015612312576020820181803683370190505b50905060005b8260ff168160ff16101561236e57838160ff168151811061233557fe5b602001015160f81c60f81b828260ff168151811061234f57fe5b60200101906001600160f81b031916908160001a905350600101612318565b5095945050505050565b61100481565b6060612388614383565b600061239384612b76565b91509150806123e9576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b60006123f483612cb5565b905063ffffffff811615612488576040808401516020808601516001600160a01b0316600090815260029091529182205461242f9190612932565b90506124396143b8565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061247c81613002565b95505050505050610e53565b50506040805160008152602081019091529150610e539050565b6000828201838110156116b4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006116b483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130de565b60008261254d575060006116b7565b8282028284828161255a57fe5b04146116b45760405162461bcd60e51b81526004018080602001828103825260218152602001806146696021913960400191505060405180910390fd5b60006116b483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613180565b60408051600680825260e08201909252606091829190816020015b60608152602001906001900390816125f45750508351909150612616906131da565b8160008151811061262357fe5b602002602001018190525061264483602001516001600160a01b03166131ed565b8160018151811061265157fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561269c57816020015b60608152602001906001900390816126875790505b50905060005b828110156126e9576126ca866040015182815181106126bd57fe5b60200260200101516131da565b8282815181106126d657fe5b60209081029190910101526001016126a2565b506126f381613210565b8360028151811061270057fe5b602002602001018190525060608260405190808252806020026020018201604052801561274157816020015b606081526020019060019003908161272c5790505b50905060005b83811015612797576127788760600151828151811061276257fe5b60200260200101516001600160a01b03166131ed565b82828151811061278457fe5b6020908102919091010152600101612747565b506127a181613210565b846003815181106127ae57fe5b60200260200101819052506060836040519080825280602002602001820160405280156127ef57816020015b60608152602001906001900390816127da5790505b50905060005b8481101561282f576128108860800151828151811061276257fe5b82828151811061281c57fe5b60209081029190910101526001016127f5565b5061283981613210565b8560048151811061284657fe5b60200260200101819052506128688760a0015167ffffffffffffffff166131da565b8560058151811061287557fe5b602002602001018190525061288985613210565b979650505050505050565b61289c6143df565b60006128a78361329a565b91509150806128e75760405162461bcd60e51b81526004018080602001828103825260248152602001806146f76024913960400191505060405180910390fd5b6114e382613465565b60006116b483836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f00000000000000008152506138e9565b6000600882111561295b57612954836007198401600a0a63ffffffff6124fc16565b90506116b7565b6116b4836008849003600a0a63ffffffff61253e16565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff1610156129e857828160ff16815181106129bc57fe5b01602001516001600160f81b031916156129db576001909101906129e0565b6129e8565b6001016129a1565b50600760ff82161015612a0057600092505050610e53565b816005820360ff1681518110612a1257fe5b6020910101516001600160f81b031916602d60f81b14612a3757600092505050610e53565b816001820360ff1681518110612a4957fe5b6020910101516001600160f81b031916604d60f81b14612a6e57600092505050610e53565b5060019392505050565b612a80614337565b6000612a8b8361394b565b9150915080612acb5760405162461bcd60e51b81526004018080602001828103825260248152602001806144ba6024913960400191505060405180910390fd5b612ad36143df565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015612b5457612b3185604001518281518110612b2357fe5b602002602001015183613baf565b85604001518281518110612b4157fe5b6020908102919091010152600101612b03565b506080840151604083015260056060830152612b6f82613465565b5050505050565b612b7e614383565b6000612b88614383565b612b90614416565b612ba1612b9c86613be8565b613c0d565b90506000805b612bb083613c57565b15612ca85780612bd257612bcb612bc684613c78565b613cc6565b8452612ca0565b8060011415612bff57612bec612be784613c78565b613d7d565b6001600160a01b03166020850152612ca0565b8060021415612c1e57612c14612bc684613c78565b6040850152612ca0565b8060031415612c4657612c33612be784613c78565b6001600160a01b03166060850152612ca0565b8060041415612c6e57612c5b612be784613c78565b6001600160a01b03166080850152612ca0565b8060051415612c9b57612c83612bc684613c78565b67ffffffffffffffff1660a085015260019150612ca0565b612ca8565b600101612ba7565b5091935090915050915091565b60208101516000906001600160a01b0316612dec578160a0015167ffffffffffffffff16421115612ce857506001610e53565b8160400151471015612cfc57506003610e53565b606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d8060008114612d53576040519150601f19603f3d011682016040523d82523d6000602084013e612d58565b606091505b5050905080612d6b575060049050610e53565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009050610e53565b8160a0015167ffffffffffffffff16421115612e0a57506001610e53565b81516020808401516001600160a01b031660009081526003909152604090205414612e3757506002610e53565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015612e8757600080fd5b5086fa158015612e9b573d6000803e3d6000fd5b50505050506040513d6020811015612eb257600080fd5b50516040840151909150811015612ecd575060039050610e53565b600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612f3e57600080fd5b5087f1158015612f52573d6000803e3d6000fd5b50505050506040513d6020811015612f6957600080fd5b505190508015612ff6577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5984602001518560600151866040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009150610e539050565b5060059150610e539050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161301d575050835190915061303f906131da565b8160008151811061304c57fe5b602002602001018190525061306483602001516131da565b8160018151811061307157fe5b602002602001018190525061309283604001516001600160a01b03166131ed565b8160028151811061309f57fe5b60200260200101819052506130bd836060015163ffffffff166131da565b816003815181106130ca57fe5b6020026020010181905250610e2781613210565b6000818361316a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561312f578181015183820152602001613117565b50505050905090810190601f16801561315c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161317657fe5b0495945050505050565b600081848411156131d25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b505050900390565b60606116b76131e883613d97565b613e7d565b60408051600560a21b8318601482015260348101909152606090610e2781613e7d565b60608151600014156132315750604080516000815260208101909152610e53565b60608260008151811061324057fe5b602002602001015190506000600190505b8351811015613281576132778285838151811061326a57fe5b6020026020010151613ecf565b9150600101613251565b50610e27613294825160c060ff16613f4c565b82613ecf565b6132a26143df565b60006132ac6143df565b6132b4614416565b6132c0612b9c86613be8565b90506000805b6132cf83613c57565b15612ca857806132f5576132e5612be784613c78565b6001600160a01b0316845261345d565b806001141561339657606061331161330c85613c78565b614044565b9050805160405190808252806020026020018201604052801561333e578160200160208202803683370190505b50602086015260005b815181101561338f5761336c82828151811061335f57fe5b6020026020010151613cc6565b8660200151828151811061337c57fe5b6020908102919091010152600101613347565b505061345d565b80600214156134385760606133ad61330c85613c78565b905080516040519080825280602002602001820160405280156133da578160200160208202803683370190505b50604086015260005b815181101561338f576134088282815181106133fb57fe5b6020026020010151613d7d565b8660400151828151811061341857fe5b6001600160a01b03909216602092830291909101909101526001016133e3565b8060031415612c9b5761344d612bc684613c78565b63ffffffff166060850152600191505b6001016132c6565b80516001600160a01b031661368f5760005b8160200151518110156136895760008260400151828151811061349657fe5b60200260200101516001600160a01b0316612710846020015184815181106134ba57fe5b60209081029190910101516040516000818181858888f193505050503d8060008114613502576040519150601f19603f3d011682016040523d82523d6000602084013e613507565b606091505b50509050806135ca577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061354657fe5b60200260200101518560200151858151811061355e57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1613680565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061360057fe5b60200260200101518560200151858151811061361857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613477565b506138e6565b60005b8160200151518110156138e457600082600001516001600160a01b031663a9059cbb61c350856040015185815181106136c757fe5b6020026020010151866020015186815181106136df57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561373657600080fd5b5087f115801561374a573d6000803e3d6000fd5b50505050506040513d602081101561376157600080fd5b505190508015613825577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106137a157fe5b6020026020010151856020015185815181106137b957fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16138db565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061385b57fe5b60200260200101518560200151858151811061387357fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613692565b505b50565b600081836139385760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b5082848161394257fe5b06949350505050565b613953614337565b600061395d614337565b613965614416565b613971612b9c86613be8565b90506000805b61398083613c57565b15612ca8578061399d57613996612bc684613c78565b8452613ba7565b80600114156139c5576139b2612be784613c78565b6001600160a01b03166020850152613ba7565b8060021415613a545760606139dc61330c85613c78565b90508051604051908082528060200260200182016040528015613a09578160200160208202803683370190505b50604086015260005b8151811015613a4d57613a2a82828151811061335f57fe5b86604001518281518110613a3a57fe5b6020908102919091010152600101613a12565b5050613ba7565b8060031415613ae9576060613a6b61330c85613c78565b90508051604051908082528060200260200182016040528015613a98578160200160208202803683370190505b50606086015260005b8151811015613a4d57613ab98282815181106133fb57fe5b86606001518281518110613ac957fe5b6001600160a01b0390921660209283029190910190910152600101613aa1565b8060041415613b7e576060613b0061330c85613c78565b90508051604051908082528060200260200182016040528015613b2d578160200160208202803683370190505b50608086015260005b8151811015613a4d57613b4e8282815181106133fb57fe5b86608001518281518110613b5e57fe5b6001600160a01b0390921660209283029190910190910152600101613b36565b8060051415612c9b57613b93612bc684613c78565b67ffffffffffffffff1660a0850152600191505b600101613977565b60006008821115613bd157612954836007198401600a0a63ffffffff61253e16565b6116b4836008849003600a0a63ffffffff6124fc16565b613bf0614436565b506040805180820190915281518152602082810190820152919050565b613c15614416565b613c1e82614115565b613c2757600080fd5b6000613c368360200151614145565b60208085015160408051808201909152868152920190820152915050919050565b6000613c61614436565b505080518051602091820151919092015191011190565b613c80614436565b613c8982613c57565b613c9257600080fd5b60208201516000613ca2826141a8565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590613cdb57508151602110155b613ce457600080fd5b6000613cf38360200151614145565b90508083600001511015613d4e576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613d7457826020036101000a820491505b50949350505050565b8051600090601514613d8e57600080fd5b6116b782613cc6565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416613ddb57506018613dff565b6fffffffffffffffffffffffffffffffff198416613dfb57506010613dff565b5060005b6020811015613e3557818181518110613e1457fe5b01602001516001600160f81b03191615613e2d57613e35565b600101613dff565b60008160200390506060816040519080825280601f01601f191660200182016040528015613e6a576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613eaf5750607f60f81b82600081518110613e9d57fe5b01602001516001600160f81b03191611155b15613ebb575080610e53565b6116b7613ecd8351608060ff16613f4c565b835b6060806040519050835180825260208201818101602087015b81831015613f00578051835260209283019201613ee8565b50855184518101855292509050808201602086015b81831015613f2d578051835260209283019201613f15565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310613f9c576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411613ff65782840160f81b81600081518110613fd857fe5b60200101906001600160f81b031916908160001a90535090506116b7565b606061400185613d97565b90508381510160370160f81b8260008151811061401a57fe5b60200101906001600160f81b031916908160001a90535061403b8282613ecf565b95945050505050565b606061404f82614115565b61405857600080fd5b6000614063836142db565b90506060816040519080825280602002602001820160405280156140a157816020015b61408e614436565b8152602001906001900390816140865790505b50905060006140b38560200151614145565b60208601510190506000805b8481101561410a576140d0836141a8565b91506040518060400160405280838152602001848152508482815181106140f357fe5b6020908102919091010152918101916001016140bf565b509195945050505050565b805160009061412657506000610e53565b6020820151805160001a9060c0821015612a6e57600092505050610e53565b8051600090811a608081101561415f576000915050610e53565b60b881108061417a575060c0811080159061417a575060f881105b15614189576001915050610e53565b60c081101561419d5760b519019050610e53565b60f519019050610e53565b80516000908190811a60808110156141c357600191506142d4565b60b88110156141d857607e19810191506142d4565b60c081101561425257600060b78203600186019550806020036101000a86510491506001810182019350508083101561424c576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142d4565b60f88110156142675760be19810191506142d4565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142d2576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80516000906142ec57506000610e53565b600080905060006143008460200151614145565b602085015185519181019250015b8082101561432e5761431f826141a8565b6001909301929091019061430e565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b6040518060400160405280614429614436565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e2031756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e7474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e736665724f757420424e4220616d6f756e7420616e64206d696e696d756d2072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e20746865206d696e696d756d2072656c6179466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea26469706673582212201169ac2b78bfd69795e87b2436fc0cb78e0f7b31be95579916f0c5ad4cae84f364736f6c63430006040033" + "code": "0x60806040526004361061031e5760003560e01c80639a99b4f0116101ab578063bd466461116100f7578063f014847211610095578063fc1a598f1161006f578063fc1a598f14610cb3578063fc3e590814610996578063fd6a687914610ce6578063ff9c00271461068657610366565b8063f014847214610c74578063f9a2bbc714610c89578063fa9e915914610c9e57610366565b8063d9e6dae9116100d1578063d9e6dae914610608578063dc927faf14610c35578063e1c7392a14610c4a578063ebf71d5314610c5f57610366565b8063bd46646114610b68578063c81b166214610b9b578063c8509d8114610bb057610366565b8063aa7415f511610164578063b99328c51161013e578063b99328c514610ad2578063b9fd21e314610b0b578063ba35ead614610b20578063bbface1f14610b3557610366565b8063aa7415f5146109ab578063ab51bb96146109f2578063ac43175114610a0757610366565b80639a99b4f0146109095780639dc0926214610942578063a1a11bf514610957578063a496fba21461096c578063a78abc1614610981578063a7c9f02d1461099657610366565b8063613684751161026a57806375d47a0a116102235780638b87b21f116101fd5780638b87b21f146105875780638eff336c146108a057806396713da9146108df5780639a854bbd146108f457610366565b806375d47a0a146107f15780637942fd0514610806578063831d65d11461081b57610366565b8063613684751461060857806366dea52a146106865780636e0565201461069b5780636e47b482146107c757806370fd5bad1461068657806371d30863146107dc57610366565b806343a368b9116102d757806350432d32116102b157806350432d321461061d57806351e806721461063257806359b92789146106475780635d499b1b1461067157610366565b806343a368b9146105c7578063493279b1146105dc5780634bf6c8821461060857610366565b80630bee7a671461036b5780631182b87514610399578063149d14d9146104935780633d713223146104ba5780633dffc3871461058757806343756e5c146105b257610366565b36610366573415610364576040805133815234602082015281517f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db929181900390910190a15b005b600080fd5b34801561037757600080fd5b50610380610cfb565b6040805163ffffffff9092168252519081900360200190f35b3480156103a557600080fd5b5061041e600480360360408110156103bc57600080fd5b60ff8235169190810190604081016020820135600160201b8111156103e057600080fd5b8201836020820111156103f257600080fd5b803590602001918460018302840111600160201b8311171561041357600080fd5b509092509050610d00565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610458578181015183820152602001610440565b50505050905090810190601f1680156104855780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561049f57600080fd5b506104a8610e2e565b60408051918252519081900360200190f35b3480156104c657600080fd5b5061056b600480360360208110156104dd57600080fd5b810190602081018135600160201b8111156104f757600080fd5b82018360208201111561050957600080fd5b803590602001918460018302840111600160201b8311171561052a57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610e34945050505050565b604080516001600160a01b039092168252519081900360200190f35b34801561059357600080fd5b5061059c610e58565b6040805160ff9092168252519081900360200190f35b3480156105be57600080fd5b5061056b610e5d565b3480156105d357600080fd5b506104a8610e63565b3480156105e857600080fd5b506105f1610e6f565b6040805161ffff9092168252519081900360200190f35b34801561061457600080fd5b5061059c610e74565b34801561062957600080fd5b506104a8610e79565b34801561063e57600080fd5b5061056b610e84565b34801561065357600080fd5b5061056b6004803603602081101561066a57600080fd5b5035610e8a565b34801561067d57600080fd5b506104a8610ea5565b34801561069257600080fd5b5061059c610eae565b6107b3600480360360808110156106b157600080fd5b810190602081018135600160201b8111156106cb57600080fd5b8201836020820111156106dd57600080fd5b803590602001918460208302840111600160201b831117156106fe57600080fd5b919390929091602081019035600160201b81111561071b57600080fd5b82018360208201111561072d57600080fd5b803590602001918460208302840111600160201b8311171561074e57600080fd5b919390929091602081019035600160201b81111561076b57600080fd5b82018360208201111561077d57600080fd5b803590602001918460208302840111600160201b8311171561079e57600080fd5b91935091503567ffffffffffffffff16610eb3565b604080519115158252519081900360200190f35b3480156107d357600080fd5b5061056b611388565b3480156107e857600080fd5b506104a861138e565b3480156107fd57600080fd5b5061056b611394565b34801561081257600080fd5b5061059c61139a565b34801561082757600080fd5b506103646004803603604081101561083e57600080fd5b60ff8235169190810190604081016020820135600160201b81111561086257600080fd5b82018360208201111561087457600080fd5b803590602001918460018302840111600160201b8311171561089557600080fd5b50909250905061139f565b3480156108ac57600080fd5b50610364600480360360608110156108c357600080fd5b508035906001600160a01b0360208201351690604001356114e8565b3480156108eb57600080fd5b5061059c61156e565b34801561090057600080fd5b506104a8611573565b34801561091557600080fd5b506104a86004803603604081101561092c57600080fd5b506001600160a01b03813516906020013561157f565b34801561094e57600080fd5b5061056b6116bd565b34801561096357600080fd5b5061056b6116c3565b34801561097857600080fd5b5061059c6116c9565b34801561098d57600080fd5b506107b36116ce565b3480156109a257600080fd5b5061059c6116d7565b6107b3600480360360808110156109c157600080fd5b5080356001600160a01b03908116916020810135909116906040810135906060013567ffffffffffffffff166116dc565b3480156109fe57600080fd5b506103806116c9565b348015610a1357600080fd5b5061036460048036036040811015610a2a57600080fd5b810190602081018135600160201b811115610a4457600080fd5b820183602082011115610a5657600080fd5b803590602001918460018302840111600160201b83111715610a7757600080fd5b919390929091602081019035600160201b811115610a9457600080fd5b820183602082011115610aa657600080fd5b803590602001918460018302840111600160201b83111715610ac757600080fd5b509092509050611d9d565b348015610ade57600080fd5b5061036460048036036040811015610af557600080fd5b50803590602001356001600160a01b031661200c565b348015610b1757600080fd5b506104a8612082565b348015610b2c57600080fd5b506104a861208c565b348015610b4157600080fd5b506104a860048036036020811015610b5857600080fd5b50356001600160a01b0316612092565b348015610b7457600080fd5b506104a860048036036020811015610b8b57600080fd5b50356001600160a01b03166120a4565b348015610ba757600080fd5b5061056b6120bf565b348015610bbc57600080fd5b5061036460048036036040811015610bd357600080fd5b60ff8235169190810190604081016020820135600160201b811115610bf757600080fd5b820183602082011115610c0957600080fd5b803590602001918460018302840111600160201b83111715610c2a57600080fd5b5090925090506120c5565b348015610c4157600080fd5b5061056b612195565b348015610c5657600080fd5b5061036461219b565b348015610c6b57600080fd5b5061059c61223b565b348015610c8057600080fd5b5061059c612240565b348015610c9557600080fd5b5061056b612245565b348015610caa57600080fd5b506104a861224b565b348015610cbf57600080fd5b5061041e60048036036020811015610cd657600080fd5b50356001600160a01b0316612251565b348015610cf257600080fd5b5061056b612378565b606481565b60005460609060ff16610d48576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b3361200014610d885760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff841660021415610dda57610dd383838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237e92505050565b9050610e27565b6040805162461bcd60e51b815260206004820152601860248201527f756e7265636f676e697a65642073796e207061636b6167650000000000000000604482015290519081900360640190fd5b9392505050565b60015490565b6020818101516000908152600490915260409020546001600160a01b03165b919050565b600181565b61100181565b670de0b6b3a764000081565b603881565b600881565b66071afd498d000081565b61200081565b6000908152600460205260409020546001600160a01b031690565b6402540be40081565b600281565b6000805460ff16610ef9576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b868514610f375760405162461bcd60e51b815260040180806020018281038252603b81526020018061471b603b913960400191505060405180910390fd5b868314610f755760405162461bcd60e51b815260040180806020018281038252603f8152602001806145ee603f913960400191505060405180910390fd5b426078018267ffffffffffffffff161015610fc15760405162461bcd60e51b81526004018080602001828103825260248152602001806144de6024913960400191505060405180910390fd5b6402540be4003406156110055760405162461bcd60e51b815260040180806020018281038252604081526020018061481e6040913960400191505060405180910390fd5b60408051868152602080880282010190915285906000908190606090848015611038578160200160208202803683370190505b50905060005b84811015611113576402540be4008b8b8381811061105857fe5b905060200201358161106657fe5b06156110a35760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b6110c88b8b838181106110b257fe5b90506020020135856124a290919063ffffffff16565b93506110f46402540be4008c8c848181106110df57fe5b905060200201356124fc90919063ffffffff16565b82828151811061110057fe5b602090810291909101015260010161103e565b506001546111389061112b908663ffffffff61253e16565b849063ffffffff6124a216565b3410156111765760405162461bcd60e51b81526004018080602001828103825260568152602001806147c86056913960600191505060405180910390fd5b611186348463ffffffff61259716565b9150611190614337565b6040518060c001604052806221272160e91b60001b815260200160006001600160a01b031681526020018381526020018e8e808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050908252506040805160208c810282810182019093528c82529283019290918d918d91829185019084908082843760009201919091525050509082525067ffffffffffffffff8916602090910152905061200063f7a251d76003611254846125d9565b611269876402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156112c75781810151838201526020016112af565b50505050905090810190601f1680156112f45780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561131557600080fd5b505af1158015611329573d6000803e3d6000fd5b505060408051600081523360208201528082018890526060810187905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a15060019c9b505050505050505050505050565b61100581565b60015481565b61100881565b600b81565b60005460ff166113e4576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b33612000146114245760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061289492505050565b6114e3565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b33611008146115285760405162461bcd60e51b81526004018080602001828103825260238152602001806147856023913960400191505060405180910390fd5b600083815260046020908152604080832080546001600160a01b039096166001600160a01b03199096168617905593825260038152838220949094556002909352912055565b600981565b677ce66c50e284000081565b6000805460ff166115c5576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b33611005146116055760405162461bcd60e51b815260040180806020018281038252602f815260200180614451602f913960400191505060405180910390fd5b60004783106116145747611616565b825b9050670de0b6b3a76400008111156116325760009150506116b7565b80156116b4576040516001600160a01b0385169082156108fc029083906000818181858888f1935050505015801561166e573d6000803e3d6000fd5b50604080516001600160a01b03861681526020810183905281517ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0929181900390910190a15b90505b92915050565b61100781565b61100681565b600081565b60005460ff1681565b600381565b6000805460ff16611722576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b426078018267ffffffffffffffff16101561176e5760405162461bcd60e51b81526004018080602001828103825260248152602001806144de6024913960400191505060405180910390fd5b6402540be4003406156117b25760405162461bcd60e51b815260040180806020018281038252604081526020018061481e6040913960400191505060405180910390fd5b600080806001600160a01b038816611891576001546117d890879063ffffffff6124a216565b3410156118165760405162461bcd60e51b81526004018080602001828103825260618152602001806145686061913960800191505060405180910390fd5b6402540be40086061561185a5760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b61186a348763ffffffff61259716565b9050611881866402540be40063ffffffff6124fc16565b6221272160e91b93509150611b34565b6001600160a01b0388166000908152600360205260409020549250826118e85760405162461bcd60e51b81526004018080602001828103825260318152602001806145376031913960400191505060405180910390fd5b6001543410156119295760405162461bcd60e51b815260040180806020018281038252603f81526020018061468a603f913960400191505060405180910390fd5b506001600160a01b038716600090815260026020526040902054349060088111158061197457506008811180156119745750611972876007198301600a0a63ffffffff6128f016565b155b6119af5760405162461bcd60e51b815260040180806020018281038252603c81526020018061462d603c913960400191505060405180910390fd5b6119b98782612932565b92506119c484612972565b15611a0c576305f5e100831015611a0c5760405162461bcd60e51b815260040180806020018281038252603a815260200180614480603a913960400191505060405180910390fd5b600881101580611a265750600881108015611a2657508683115b611a615760405162461bcd60e51b81526004018080602001828103825260258152602001806145c96025913960400191505060405180910390fd5b677ce66c50e2840000831115611aa85760405162461bcd60e51b81526004018080602001828103825260358152602001806145026035913960400191505060405180910390fd5b604080516323b872dd60e01b81523360048201523060248201526044810189905290516001600160a01b038b16916323b872dd9160648083019260209291908290030181600087803b158015611afd57600080fd5b505af1158015611b11573d6000803e3d6000fd5b505050506040513d6020811015611b2757600080fd5b5051611b3257600080fd5b505b611b3c614337565b6040805160c0810182528581526001600160a01b038b166020820152815160018082528184018452919283019181602001602082028036833750505081526040805160018082528183019092526020928301929091908083019080368337505050815260408051600180825281830190925260209283019290919080830190803683370190505081526020018767ffffffffffffffff168152509050828160400151600081518110611bea57fe5b602002602001018181525050878160600151600081518110611c0857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050338160800151600081518110611c3a57fe5b6001600160a01b039092166020928302919091019091015261200063f7a251d76003611c65846125d9565b611c7a866402540be40063ffffffff6124fc16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611cd8578181015183820152602001611cc0565b50505050905090810190601f168015611d055780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611d2657600080fd5b505af1158015611d3a573d6000803e3d6000fd5b5050604080516001600160a01b038d1681523360208201528082018b90526060810186905290517f74eab09b0e53aefc23f2e1b16da593f95c2dd49c6f5a23720463d10d9c330b2a9350908190036080019150a150600198975050505050505050565b3361100714611ddd5760405162461bcd60e51b815260040180806020018281038252602e8152602001806146c9602e913960400191505060405180910390fd5b60208114611e32576040805162461bcd60e51b815260206004820152601b60248201527f65787065637465642076616c7565206c656e6774682069732033320000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8801819004810282018101909252868152939450606093925086915085908190840183828082843760009201919091525050505060208301519091506772656c617946656560c01b811415611f3a576020820151670de0b6b3a76400008111801590611ee157506402540be4008106155b611f32576040805162461bcd60e51b815260206004820152601960248201527f7468652072656c6179466565206f7574206f662072616e676500000000000000604482015290519081900360640190fd5b600155611f77565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b336110081461204c5760405162461bcd60e51b81526004018080602001828103825260238152602001806147856023913960400191505060405180910390fd5b600091825260046020908152604080842080546001600160a01b03191690556001600160a01b0392909216835260039052812055565b6221272160e91b81565b61c35081565b60026020526000908152604090205481565b6001600160a01b031660009081526003602052604090205490565b61100281565b60005460ff1661210a576040805162461bcd60e51b815260206004820152601960248201526000805160206147a8833981519152604482015290519081900360640190fd5b336120001461214a5760405162461bcd60e51b815260040180806020018281038252602f815260200180614756602f913960400191505060405180910390fd5b60ff8316600314156114745761146f82828080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a7892505050565b61100381565b60005460ff16156121f3576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b66071afd498d000060019081556000808052600260205260127fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b55805460ff19169091179055565b600481565b600581565b61100081565b61271081565b6001600160a01b03811660009081526003602090815260409182902054825182815280840190935260609290918391906020820181803683375050506020810183905290506000805b60208160ff1610156122e157828160ff16815181106122b557fe5b01602001516001600160f81b031916156122d4576001909101906122d9565b6122e1565b60010161229a565b5060608160ff166040519080825280601f01601f191660200182016040528015612312576020820181803683370190505b50905060005b8260ff168160ff16101561236e57838160ff168151811061233557fe5b602001015160f81c60f81b828260ff168151811061234f57fe5b60200101906001600160f81b031916908160001a905350600101612318565b5095945050505050565b61100481565b6060612388614383565b600061239384612b76565b91509150806123e9576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b60006123f483612cb5565b905063ffffffff811615612488576040808401516020808601516001600160a01b0316600090815260029091529182205461242f9190612932565b90506124396143b8565b60405180608001604052808660000151815260200183815260200186608001516001600160a01b031681526020018463ffffffff16815250905061247c81613002565b95505050505050610e53565b50506040805160008152602081019091529150610e539050565b6000828201838110156116b4576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006116b483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506130de565b60008261254d575060006116b7565b8282028284828161255a57fe5b04146116b45760405162461bcd60e51b81526004018080602001828103825260218152602001806146696021913960400191505060405180910390fd5b60006116b483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613180565b60408051600680825260e08201909252606091829190816020015b60608152602001906001900390816125f45750508351909150612616906131da565b8160008151811061262357fe5b602002602001018190525061264483602001516001600160a01b03166131ed565b8160018151811061265157fe5b60200260200101819052506000836040015151905060608160405190808252806020026020018201604052801561269c57816020015b60608152602001906001900390816126875790505b50905060005b828110156126e9576126ca866040015182815181106126bd57fe5b60200260200101516131da565b8282815181106126d657fe5b60209081029190910101526001016126a2565b506126f381613210565b8360028151811061270057fe5b602002602001018190525060608260405190808252806020026020018201604052801561274157816020015b606081526020019060019003908161272c5790505b50905060005b83811015612797576127788760600151828151811061276257fe5b60200260200101516001600160a01b03166131ed565b82828151811061278457fe5b6020908102919091010152600101612747565b506127a181613210565b846003815181106127ae57fe5b60200260200101819052506060836040519080825280602002602001820160405280156127ef57816020015b60608152602001906001900390816127da5790505b50905060005b8481101561282f576128108860800151828151811061276257fe5b82828151811061281c57fe5b60209081029190910101526001016127f5565b5061283981613210565b8560048151811061284657fe5b60200260200101819052506128688760a0015167ffffffffffffffff166131da565b8560058151811061287557fe5b602002602001018190525061288985613210565b979650505050505050565b61289c6143df565b60006128a78361329a565b91509150806128e75760405162461bcd60e51b81526004018080602001828103825260248152602001806146f76024913960400191505060405180910390fd5b6114e382613465565b60006116b483836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f00000000000000008152506138e9565b6000600882111561295b57612954836007198401600a0a63ffffffff6124fc16565b90506116b7565b6116b4836008849003600a0a63ffffffff61253e16565b604080516020808252818301909252600091606091906020820181803683375050506020810184905290506000805b60208160ff1610156129e857828160ff16815181106129bc57fe5b01602001516001600160f81b031916156129db576001909101906129e0565b6129e8565b6001016129a1565b50600760ff82161015612a0057600092505050610e53565b816005820360ff1681518110612a1257fe5b6020910101516001600160f81b031916602d60f81b14612a3757600092505050610e53565b816001820360ff1681518110612a4957fe5b6020910101516001600160f81b031916604d60f81b14612a6e57600092505050610e53565b5060019392505050565b612a80614337565b6000612a8b8361394b565b9150915080612acb5760405162461bcd60e51b81526004018080602001828103825260248152602001806144ba6024913960400191505060405180910390fd5b612ad36143df565b602080840180516001600160a01b0390811684526040808701518585015291511660009081526002909252812054905b846040015151811015612b5457612b3185604001518281518110612b2357fe5b602002602001015183613baf565b85604001518281518110612b4157fe5b6020908102919091010152600101612b03565b506080840151604083015260056060830152612b6f82613465565b5050505050565b612b7e614383565b6000612b88614383565b612b90614416565b612ba1612b9c86613be8565b613c0d565b90506000805b612bb083613c57565b15612ca85780612bd257612bcb612bc684613c78565b613cc6565b8452612ca0565b8060011415612bff57612bec612be784613c78565b613d7d565b6001600160a01b03166020850152612ca0565b8060021415612c1e57612c14612bc684613c78565b6040850152612ca0565b8060031415612c4657612c33612be784613c78565b6001600160a01b03166060850152612ca0565b8060041415612c6e57612c5b612be784613c78565b6001600160a01b03166080850152612ca0565b8060051415612c9b57612c83612bc684613c78565b67ffffffffffffffff1660a085015260019150612ca0565b612ca8565b600101612ba7565b5091935090915050915091565b60208101516000906001600160a01b0316612dec578160a0015167ffffffffffffffff16421115612ce857506001610e53565b8160400151471015612cfc57506003610e53565b606082015160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d8060008114612d53576040519150601f19603f3d011682016040523d82523d6000602084013e612d58565b606091505b5050905080612d6b575060049050610e53565b7f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5983602001518460600151856040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009050610e53565b8160a0015167ffffffffffffffff16421115612e0a57506001610e53565b81516020808401516001600160a01b031660009081526003909152604090205414612e3757506002610e53565b602080830151604080516370a0823160e01b815230600482015290516000936001600160a01b03909316926370a082319261c3509260248083019392829003018187803b158015612e8757600080fd5b5086fa158015612e9b573d6000803e3d6000fd5b50505050506040513d6020811015612eb257600080fd5b50516040840151909150811015612ecd575060039050610e53565b600083602001516001600160a01b031663a9059cbb61c350866060015187604001516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b158015612f3e57600080fd5b5087f1158015612f52573d6000803e3d6000fd5b50505050506040513d6020811015612f6957600080fd5b505190508015612ff6577f471eb9cc1ffe55ffadf15b32595415eb9d80f22e761d24bd6dffc607e1284d5984602001518560600151866040015160405180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060405180910390a15060009150610e539050565b5060059150610e539050565b60408051600480825260a08201909252606091829190816020015b606081526020019060019003908161301d575050835190915061303f906131da565b8160008151811061304c57fe5b602002602001018190525061306483602001516131da565b8160018151811061307157fe5b602002602001018190525061309283604001516001600160a01b03166131ed565b8160028151811061309f57fe5b60200260200101819052506130bd836060015163ffffffff166131da565b816003815181106130ca57fe5b6020026020010181905250610e2781613210565b6000818361316a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561312f578181015183820152602001613117565b50505050905090810190601f16801561315c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161317657fe5b0495945050505050565b600081848411156131d25760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b505050900390565b60606116b76131e883613d97565b613e7d565b60408051600560a21b8318601482015260348101909152606090610e2781613e7d565b60608151600014156132315750604080516000815260208101909152610e53565b60608260008151811061324057fe5b602002602001015190506000600190505b8351811015613281576132778285838151811061326a57fe5b6020026020010151613ecf565b9150600101613251565b50610e27613294825160c060ff16613f4c565b82613ecf565b6132a26143df565b60006132ac6143df565b6132b4614416565b6132c0612b9c86613be8565b90506000805b6132cf83613c57565b15612ca857806132f5576132e5612be784613c78565b6001600160a01b0316845261345d565b806001141561339657606061331161330c85613c78565b614044565b9050805160405190808252806020026020018201604052801561333e578160200160208202803683370190505b50602086015260005b815181101561338f5761336c82828151811061335f57fe5b6020026020010151613cc6565b8660200151828151811061337c57fe5b6020908102919091010152600101613347565b505061345d565b80600214156134385760606133ad61330c85613c78565b905080516040519080825280602002602001820160405280156133da578160200160208202803683370190505b50604086015260005b815181101561338f576134088282815181106133fb57fe5b6020026020010151613d7d565b8660400151828151811061341857fe5b6001600160a01b03909216602092830291909101909101526001016133e3565b8060031415612c9b5761344d612bc684613c78565b63ffffffff166060850152600191505b6001016132c6565b80516001600160a01b031661368f5760005b8160200151518110156136895760008260400151828151811061349657fe5b60200260200101516001600160a01b0316612710846020015184815181106134ba57fe5b60209081029190910101516040516000818181858888f193505050503d8060008114613502576040519150601f19603f3d011682016040523d82523d6000602084013e613507565b606091505b50509050806135ca577f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061354657fe5b60200260200101518560200151858151811061355e57fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a1613680565b7fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a83600001518460400151848151811061360057fe5b60200260200101518560200151858151811061361857fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613477565b506138e6565b60005b8160200151518110156138e457600082600001516001600160a01b031663a9059cbb61c350856040015185815181106136c757fe5b6020026020010151866020015186815181106136df57fe5b60200260200101516040518463ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600088803b15801561373657600080fd5b5087f115801561374a573d6000803e3d6000fd5b50505050506040513d602081101561376157600080fd5b505190508015613825577fd468d4fa5e8fb4adc119b29a983fd0785e04af5cb8b7a3a69a47270c54b6901a8360000151846040015184815181106137a157fe5b6020026020010151856020015185815181106137b957fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a16138db565b7f203f9f67a785f4f81be4d48b109aa0c498d1bc8097ecc2627063f480cc5fe73e83600001518460400151848151811061385b57fe5b60200260200101518560200151858151811061387357fe5b6020026020010151866060015160405180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b031681526020018381526020018263ffffffff1663ffffffff16815260200194505050505060405180910390a15b50600101613692565b505b50565b600081836139385760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561312f578181015183820152602001613117565b5082848161394257fe5b06949350505050565b613953614337565b600061395d614337565b613965614416565b613971612b9c86613be8565b90506000805b61398083613c57565b15612ca8578061399d57613996612bc684613c78565b8452613ba7565b80600114156139c5576139b2612be784613c78565b6001600160a01b03166020850152613ba7565b8060021415613a545760606139dc61330c85613c78565b90508051604051908082528060200260200182016040528015613a09578160200160208202803683370190505b50604086015260005b8151811015613a4d57613a2a82828151811061335f57fe5b86604001518281518110613a3a57fe5b6020908102919091010152600101613a12565b5050613ba7565b8060031415613ae9576060613a6b61330c85613c78565b90508051604051908082528060200260200182016040528015613a98578160200160208202803683370190505b50606086015260005b8151811015613a4d57613ab98282815181106133fb57fe5b86606001518281518110613ac957fe5b6001600160a01b0390921660209283029190910190910152600101613aa1565b8060041415613b7e576060613b0061330c85613c78565b90508051604051908082528060200260200182016040528015613b2d578160200160208202803683370190505b50608086015260005b8151811015613a4d57613b4e8282815181106133fb57fe5b86608001518281518110613b5e57fe5b6001600160a01b0390921660209283029190910190910152600101613b36565b8060051415612c9b57613b93612bc684613c78565b67ffffffffffffffff1660a0850152600191505b600101613977565b60006008821115613bd157612954836007198401600a0a63ffffffff61253e16565b6116b4836008849003600a0a63ffffffff6124fc16565b613bf0614436565b506040805180820190915281518152602082810190820152919050565b613c15614416565b613c1e82614115565b613c2757600080fd5b6000613c368360200151614145565b60208085015160408051808201909152868152920190820152915050919050565b6000613c61614436565b505080518051602091820151919092015191011190565b613c80614436565b613c8982613c57565b613c9257600080fd5b60208201516000613ca2826141a8565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590613cdb57508151602110155b613ce457600080fd5b6000613cf38360200151614145565b90508083600001511015613d4e576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613d7457826020036101000a820491505b50949350505050565b8051600090601514613d8e57600080fd5b6116b782613cc6565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416613ddb57506018613dff565b6fffffffffffffffffffffffffffffffff198416613dfb57506010613dff565b5060005b6020811015613e3557818181518110613e1457fe5b01602001516001600160f81b03191615613e2d57613e35565b600101613dff565b60008160200390506060816040519080825280601f01601f191660200182016040528015613e6a576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015613eaf5750607f60f81b82600081518110613e9d57fe5b01602001516001600160f81b03191611155b15613ebb575080610e53565b6116b7613ecd8351608060ff16613f4c565b835b6060806040519050835180825260208201818101602087015b81831015613f00578051835260209283019201613ee8565b50855184518101855292509050808201602086015b81831015613f2d578051835260209283019201613f15565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310613f9c576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b60408051600180825281830190925260609160208201818036833701905050905060378411613ff65782840160f81b81600081518110613fd857fe5b60200101906001600160f81b031916908160001a90535090506116b7565b606061400185613d97565b90508381510160370160f81b8260008151811061401a57fe5b60200101906001600160f81b031916908160001a90535061403b8282613ecf565b95945050505050565b606061404f82614115565b61405857600080fd5b6000614063836142db565b90506060816040519080825280602002602001820160405280156140a157816020015b61408e614436565b8152602001906001900390816140865790505b50905060006140b38560200151614145565b60208601510190506000805b8481101561410a576140d0836141a8565b91506040518060400160405280838152602001848152508482815181106140f357fe5b6020908102919091010152918101916001016140bf565b509195945050505050565b805160009061412657506000610e53565b6020820151805160001a9060c0821015612a6e57600092505050610e53565b8051600090811a608081101561415f576000915050610e53565b60b881108061417a575060c0811080159061417a575060f881105b15614189576001915050610e53565b60c081101561419d5760b519019050610e53565b60f519019050610e53565b80516000908190811a60808110156141c357600191506142d4565b60b88110156141d857607e19810191506142d4565b60c081101561425257600060b78203600186019550806020036101000a86510491506001810182019350508083101561424c576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b506142d4565b60f88110156142675760be19810191506142d4565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156142d2576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80516000906142ec57506000610e53565b600080905060006143008460200151614145565b602085015185519181019250015b8082101561432e5761431f826141a8565b6001909301929091019061430e565b50909392505050565b6040518060c001604052806000801916815260200160006001600160a01b03168152602001606081526020016060815260200160608152602001600067ffffffffffffffff1681525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806080016040528060006001600160a01b031681526020016060815260200160608152602001600063ffffffff1681525090565b6040518060400160405280614429614436565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d75737420626520696e63656e746976697a6520636f6e7472616374466f72206d696e69546f6b656e2c20746865207472616e7366657220616d6f756e74206d757374206e6f74206265206c657373207468616e2031756e7265636f676e697a6564207472616e736665724f75742073796e207061636b61676565787069726554696d65206d7573742062652074776f206d696e75746573206c61746572616d6f756e7420697320746f6f206c617267652c20657863656564206d6178696d756d206265703220746f6b656e20616d6f756e7474686520636f6e747261637420686173206e6f74206265656e20626f756e6420746f20616e79206265703220746f6b656e726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e736665724f757420424e4220616d6f756e7420616e64206d696e696d756d2072656c6179466565616d6f756e7420697320746f6f206c617267652c2075696e74323536206f766572666c6f774c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620726566756e644164647273696e76616c6964207472616e7366657220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e20746865206d696e696d756d2072656c6179466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374756e7265636f676e697a6564207472616e736665724f75742061636b207061636b6167654c656e677468206f6620726563697069656e74416464727320646f65736e277420657175616c20746f206c656e677468206f6620616d6f756e7473746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e7472616374746865206d73672073656e646572206d75737420626520746f6b656e4d616e6167657274686520636f6e7472616374206e6f7420696e69742079657400000000000000726563656976656420424e4220616d6f756e742073686f756c64206265206e6f206c657373207468616e207468652073756d206f66207472616e7366657220424e4220616d6f756e7420616e642072656c6179466565696e76616c696420726563656976656420424e4220616d6f756e743a20707265636973696f6e206c6f737320696e20616d6f756e7420636f6e76657273696f6ea2646970667358221220c72f4ad63f8f84b0b15ae9d71fffb0d09b3b3b97a728e64b385305ecb6431b0e64736f6c63430006040033" }, "0x0000000000000000000000000000000000001005": { "balance": "0x0", - "code": "0x6080604052600436106102815760003560e01c8063930e1b091161014f578063bd4cc830116100c1578063e75d72c71161007a578063e75d72c7146107b5578063e89a3020146107e8578063f9a2bbc714610812578063fc3e590814610827578063fd6a68791461083c578063fdd31fcd1461085157610288565b8063bd4cc83014610722578063c81b16621461074c578063d0ab528a14610761578063dc927faf14610776578063dcae76ab1461078b578063e1c7392a146107a057610288565b8063a78abc1611610113578063a78abc16146105d3578063a7c6a59d146105e8578063ab51bb96146105fd578063ac43175114610612578063ace9fcc2146106e3578063af400681146106f857610288565b8063930e1b091461054c57806396713da91461057f5780639dc0926214610594578063a1a11bf5146105a9578063a3c3c0ad146105be57610288565b806343756e5c116101f35780636f93d2e6116101ac5780636f93d2e61461048457806370fd5bad146104e357806374f2272d146104f857806375d47a0a1461050d5780637942fd05146105225780637e146cc51461053757610288565b806343756e5c146103ef578063493279b1146104045780634bf6c8821461043057806351e8067214610445578063541333071461045a5780636e47b4821461046f57610288565b806312950c461161024557806312950c46146103215780631b20087c146103365780631c6433121461034b5780633a9756121461028d5780633dffc3871461039157806340bb43c0146103bc57610288565b8063081e9d131461028d57806308f2ec06146102b4578063093f2fc4146102c95780630bee7a67146102de57806310e06a761461030c57610288565b3661028857005b600080fd5b34801561029957600080fd5b506102a2610884565b60408051918252519081900360200190f35b3480156102c057600080fd5b506102a2610889565b3480156102d557600080fd5b506102a261088e565b3480156102ea57600080fd5b506102f3610893565b6040805163ffffffff9092168252519081900360200190f35b34801561031857600080fd5b506102a2610898565b34801561032d57600080fd5b506102a261089e565b34801561034257600080fd5b506102a26108a4565b34801561035757600080fd5b506103756004803603602081101561036e57600080fd5b50356108aa565b604080516001600160a01b039092168252519081900360200190f35b34801561039d57600080fd5b506103a6610884565b6040805160ff9092168252519081900360200190f35b3480156103c857600080fd5b506102a2600480360360208110156103df57600080fd5b50356001600160a01b03166108d1565b3480156103fb57600080fd5b506103756108e3565b34801561041057600080fd5b506104196108e9565b6040805161ffff9092168252519081900360200190f35b34801561043c57600080fd5b506103a66108ee565b34801561045157600080fd5b506103756108f3565b34801561046657600080fd5b506102a2610893565b34801561047b57600080fd5b506103756108f9565b34801561049057600080fd5b506104cf600480360360808110156104a757600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013515156108ff565b604080519115158252519081900360200190f35b3480156104ef57600080fd5b506103a6610d91565b34801561050457600080fd5b506102a2610d96565b34801561051957600080fd5b50610375610d9c565b34801561052e57600080fd5b506103a6610da2565b34801561054357600080fd5b506102a2610da7565b34801561055857600080fd5b506102a26004803603602081101561056f57600080fd5b50356001600160a01b0316610dac565b34801561058b57600080fd5b506103a6610dbe565b3480156105a057600080fd5b50610375610dc3565b3480156105b557600080fd5b50610375610dc9565b3480156105ca57600080fd5b506102a2610dcf565b3480156105df57600080fd5b506104cf610dd5565b3480156105f457600080fd5b506102a2610dde565b34801561060957600080fd5b506102f3610de4565b34801561061e57600080fd5b506106e16004803603604081101561063557600080fd5b81019060208101813564010000000081111561065057600080fd5b82018360208201111561066257600080fd5b8035906020019184600183028401116401000000008311171561068457600080fd5b9193909290916020810190356401000000008111156106a257600080fd5b8201836020820111156106b457600080fd5b803590602001918460018302840111640100000000831117156106d657600080fd5b509092509050610de9565b005b3480156106ef57600080fd5b506102a2611537565b34801561070457600080fd5b506102a26004803603602081101561071b57600080fd5b503561153d565b34801561072e57600080fd5b506102a26004803603602081101561074557600080fd5b5035611598565b34801561075857600080fd5b506103756115b1565b34801561076d57600080fd5b506102a26115b7565b34801561078257600080fd5b506103756115bd565b34801561079757600080fd5b506102a26115c3565b3480156107ac57600080fd5b506106e16115c9565b3480156107c157600080fd5b506106e1600480360360208110156107d857600080fd5b50356001600160a01b0316611692565b3480156107f457600080fd5b506103756004803603602081101561080b57600080fd5b50356117eb565b34801561081e57600080fd5b506103756117f8565b34801561083357600080fd5b506103a66117fe565b34801561084857600080fd5b50610375611803565b34801561085d57600080fd5b506102a26004803603602081101561087457600080fd5b50356001600160a01b0316611809565b600181565b602881565b605081565b606481565b600b5481565b60015481565b600c5481565b600681815481106108b757fe5b6000918252602090912001546001600160a01b0316905081565b60076020526000908152604090205481565b61100181565b606081565b600881565b61200081565b61100581565b6000805460ff16610957576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b33612000146109975760405162461bcd60e51b815260040180806020018281038252602f815260200180612377602f913960400191505060405180910390fd5b60008215610a4a576110026001600160a01b0316639a99b4f06110056109c8600e548861181b90919063ffffffff16565b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610a1757600080fd5b505af1158015610a2b573d6000803e3d6000fd5b505050506040513d6020811015610a4157600080fd5b50519050610b59565b604080516309a99b4f60e41b8152611005600482015260248101869052905161100491639a99b4f09160448083019260209291908290030181600087803b158015610a9457600080fd5b505af1158015610aa8573d6000803e3d6000fd5b505050506040513d6020811015610abe57600080fd5b5051600e5490915015610b5957600e54604080516309a99b4f60e41b81526110056004820152602481019290925251610b569161100291639a99b4f0916044808201926020929091908290030181600087803b158015610b1d57600080fd5b505af1158015610b31573d6000803e3d6000fd5b505050506040513d6020811015610b4757600080fd5b5051829063ffffffff61181b16565b90505b600c805460010190556000610b6d8261187e565b600954909150610b83908263ffffffff61181b16565b600955600a54610bab908290610b9f908563ffffffff61181b16565b9063ffffffff6118a716565b600a556001600160a01b038716600090815260056020526040902054610c1757600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b0319166001600160a01b0389161790555b6001600160a01b038088166000908152600560209081526040808320805460010190559289168252600790522054610c9557600880546001810182556000919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319166001600160a01b0388161790555b6001600160a01b038616600090815260076020526040902080546001019055600c54606411610d8457600b54600954600a5460408051938452602084019290925282820152517f2649b1b772a1a74bd332a67695e285317dd722941166595741c60a00fa65bb759181900360600190a16000610d0f6118e9565b90506000610d1b611bcd565b6001600160a01b0389166000908152600d6020526040902054909150610d59908290610d4d908563ffffffff61181b16565b9063ffffffff61181b16565b6001600160a01b0389166000908152600d6020526040812091909155600b80546001019055600c5550505b5060019695505050505050565b600281565b60035481565b61100881565b600b81565b600581565b60056020526000908152604090205481565b600981565b61100781565b61100681565b600a5481565b60005460ff1681565b60045481565b600081565b3361100714610e295760405162461bcd60e51b815260040180806020018281038252602e8152602001806122bc602e913960400191505060405180910390fd5b60005460ff16610e6a5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ea6021913960400191505060405180910390fd5b610ede84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601f81527f68656164657252656c61796572526577617264526174654d6f6c6563756c650060208201529150611e4b9050565b15610fab5760208114610f225760405162461bcd60e51b81526004018080602001828103825260328152602001806123a66032913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610f6091858580838501838280828437600092019190915250611f3292505050565b9050600254811115610fa35760405162461bcd60e51b81526004018080602001828103825260608152602001806121956060913960600191505060405180910390fd5b6001556114a5565b61100484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051606081019091526022808252909250905061229a6020830139611e4b565b156110dc57602081146110485760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161108691858580838501838280828437600092019190915250611f3292505050565b9050801580159061109957506001548110155b6110d45760405162461bcd60e51b815260040180806020018281038252606c81526020018061230b606c913960800191505060405180910390fd5b6002556114a5565b61115084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601a81527f63616c6c6572436f6d70656e736174696f6e4d6f6c6563756c6500000000000060208201529150611e4b9050565b1561121d57602081146111945760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f84018190048102820181019092528281526000916111d291858580838501838280828437600092019190915250611f3292505050565b90506004548111156112155760405162461bcd60e51b81526004018080602001828103825260568152602001806121f56056913960600191505060405180910390fd5b6003556114a5565b61129184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601d81527f63616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f7200000060208201529150611e4b9050565b1561136957602081146112d55760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161131391858580838501838280828437600092019190915250611f3292505050565b9050801580159061132657506003548110155b6113615760405162461bcd60e51b81526004018080602001828103825260618152602001806121066061913960800191505060405180910390fd5b6004556114a5565b6113dd84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601b81527f64796e616d69634578747261496e63656e74697665416d6f756e74000000000060208201529150611e4b9050565b1561146857602081146114215760405162461bcd60e51b815260040180806020018281038252602e815260200180612167602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161145f91858580838501838280828437600092019190915250611f3292505050565b600e55506114a5565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60025481565b60006028821161154e575080611593565b81602810801561155f575060508211155b1561156c57506028611593565b60508211801561157d5750606e8211155b1561158d57506078819003611593565b50600481045b919050565b6000602882116115a9575080611593565b506028611593565b61100281565b600e5481565b61100381565b60095481565b60005460ff1615611621576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b60005460ff161561166f576040805162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b60018080556005600255600381905560506004556000805460ff19169091179055565b6001600160a01b0381166000908152600d6020526040902054806116f1576040805162461bcd60e51b81526020600482015260116024820152701b9bc81c995b185e595c881c995dd85c99607a1b604482015290519081900360640190fd5b6001600160a01b0382166000818152600d60205260408082208290555184929184156108fc02918591818181858888f193505050506117a15760405161100290819084156108fc029085906000818181858888f1935050505015801561175b573d6000803e3d6000fd5b506040805161100281526020810185905281517f24502838a334c8f2bb2ee1f8262a4fa7183e4489a717e96cc824e325f8b39e11929181900390910190a15050506117e8565b604080516001600160a01b03851681526020810184905281517f24502838a334c8f2bb2ee1f8262a4fa7183e4489a717e96cc824e325f8b39e11929181900390910190a150505b50565b600881815481106108b757fe5b61100081565b600381565b61100481565b600d6020526000908152604090205481565b600082820183811015611875576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061187860025461189b60015485611f3790919063ffffffff16565b9063ffffffff611f9016565b600061187583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611fd2565b600954600680546040805160208084028201810190925282815260009493859360609383018282801561194557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611927575b5050505050905060608151604051908082528060200260200182016040528015611979578160200160208202803683370190505b50905060005b8251811015611a0657600083828151811061199657fe5b6020026020010151905060006119d060056000846001600160a01b03166001600160a01b0316815260200190815260200160002054611598565b9050808484815181106119df57fe5b60209081029190910101526119fa868263ffffffff61181b16565b9550505060010161197f565b506000611a2460045461189b60035488611f3790919063ffffffff16565b9050611a36858263ffffffff6118a716565b94508460015b8451811015611b0d576000611a718761189b8a888681518110611a5b57fe5b6020026020010151611f3790919063ffffffff16565b9050611abe81600d6000898681518110611a8757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205461181b90919063ffffffff16565b600d6000888581518110611ace57fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055611b02838263ffffffff6118a716565b925050600101611a3c565b50611b2381600d600087600081518110611a8757fe5b600d600086600081518110611b3457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060098190555060008090505b8451811015611bb55760056000868381518110611b8757fe5b6020908102919091018101516001600160a01b03168252810191909152604001600090812055600101611b6e565b50611bc2600660006120ce565b509450505050505b90565b600a546008805460408051602080840282018101909252828152600094938593606093830182828015611c2957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c0b575b5050505050905060608151604051908082528060200260200182016040528015611c5d578160200160208202803683370190505b50905060005b8251811015611cdc576000838281518110611c7a57fe5b602002602001015190506000611cb460076000846001600160a01b03166001600160a01b031681526020019081526020016000205461153d565b905080848481518110611cc357fe5b6020908102919091010152949094019350600101611c63565b506000611cfa60045461189b60035488611f3790919063ffffffff16565b9050611d0c858263ffffffff6118a716565b94508460015b8451811015611d96576000611d318761189b8a888681518110611a5b57fe5b9050611d4781600d6000898681518110611a8757fe5b600d6000888581518110611d5757fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055611d8b838263ffffffff6118a716565b925050600101611d12565b50611dac81600d600087600081518110611a8757fe5b600d600086600081518110611dbd57fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506000600a8190555060008090505b8451811015611e3e5760076000868381518110611e1057fe5b6020908102919091018101516001600160a01b03168252810191909152604001600090812055600101611df7565b50611bc2600860006120ce565b6000816040516020018082805190602001908083835b60208310611e805780518252601f199092019160209182019101611e61565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310611eee5780518252601f199092019160209182019101611ecf565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b600082611f4657506000611878565b82820282848281611f5357fe5b04146118755760405162461bcd60e51b81526004018080602001828103825260218152602001806122796021913960400191505060405180910390fd5b600061187583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612069565b600081848411156120615760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561202657818101518382015260200161200e565b50505050905090810190601f1680156120535780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836120b85760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561202657818101518382015260200161200e565b5060008385816120c457fe5b0495945050505050565b50805460008255906000526020600020908101906117e89190611bca91905b8082111561210157600081556001016120ed565b509056fe746865206e657743616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f72206d757374206e6f74206265207a65726f20616e64206e6f206c657373207468616e2063616c6c6572436f6d70656e736174696f6e4d6f6c6563756c656c656e677468206f662064796e616d69634578747261496e63656e74697665416d6f756e74206d69736d617463686e65772068656164657252656c61796572526577617264526174654d6f6c6563756c652073686f756c646e27742062652067726561746572207468616e2068656164657252656c617965725265776172645261746544656e6f6d696e61746f726e65772063616c6c6572436f6d70656e736174696f6e4d6f6c6563756c652073686f756c646e27742062652067726561746572207468616e2063616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f726c656e677468206f6620726577617264466f7256616c696461746f725365744368616e6765206d69736d61746368536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7768656164657252656c617965725265776172645261746544656e6f6d696e61746f72746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374636f6e747261637420686173206e6f74206265656e20696e697469616c697a6564746865206e65772068656164657252656c617965725265776172645261746544656e6f6d696e61746f72206d757374206e6f74206265207a65726f20616e64206e6f206c657373207468616e2068656164657252656c61796572526577617264526174654d6f6c6563756c65746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163746c656e677468206f662068656164657252656c61796572526577617264526174654d6f6c6563756c65206d69736d61746368a26469706673582212203d0228298d81f0e5fa0f321eec6dd7c32727408a454d8357375dbb3d92b2207c64736f6c63430006040033" + "code": "0x6080604052600436106102815760003560e01c8063930e1b091161014f578063bd4cc830116100c1578063e75d72c71161007a578063e75d72c7146107b5578063e89a3020146107e8578063f9a2bbc714610812578063fc3e590814610827578063fd6a68791461083c578063fdd31fcd1461085157610288565b8063bd4cc83014610722578063c81b16621461074c578063d0ab528a14610761578063dc927faf14610776578063dcae76ab1461078b578063e1c7392a146107a057610288565b8063a78abc1611610113578063a78abc16146105d3578063a7c6a59d146105e8578063ab51bb96146105fd578063ac43175114610612578063ace9fcc2146106e3578063af400681146106f857610288565b8063930e1b091461054c57806396713da91461057f5780639dc0926214610594578063a1a11bf5146105a9578063a3c3c0ad146105be57610288565b806343756e5c116101f35780636f93d2e6116101ac5780636f93d2e61461048457806370fd5bad146104e357806374f2272d146104f857806375d47a0a1461050d5780637942fd05146105225780637e146cc51461053757610288565b806343756e5c146103ef578063493279b1146104045780634bf6c8821461043057806351e8067214610445578063541333071461045a5780636e47b4821461046f57610288565b806312950c461161024557806312950c46146103215780631b20087c146103365780631c6433121461034b5780633a9756121461028d5780633dffc3871461039157806340bb43c0146103bc57610288565b8063081e9d131461028d57806308f2ec06146102b4578063093f2fc4146102c95780630bee7a67146102de57806310e06a761461030c57610288565b3661028857005b600080fd5b34801561029957600080fd5b506102a2610884565b60408051918252519081900360200190f35b3480156102c057600080fd5b506102a2610889565b3480156102d557600080fd5b506102a261088e565b3480156102ea57600080fd5b506102f3610893565b6040805163ffffffff9092168252519081900360200190f35b34801561031857600080fd5b506102a2610898565b34801561032d57600080fd5b506102a261089e565b34801561034257600080fd5b506102a26108a4565b34801561035757600080fd5b506103756004803603602081101561036e57600080fd5b50356108aa565b604080516001600160a01b039092168252519081900360200190f35b34801561039d57600080fd5b506103a6610884565b6040805160ff9092168252519081900360200190f35b3480156103c857600080fd5b506102a2600480360360208110156103df57600080fd5b50356001600160a01b03166108d1565b3480156103fb57600080fd5b506103756108e3565b34801561041057600080fd5b506104196108e9565b6040805161ffff9092168252519081900360200190f35b34801561043c57600080fd5b506103a66108ee565b34801561045157600080fd5b506103756108f3565b34801561046657600080fd5b506102a2610893565b34801561047b57600080fd5b506103756108f9565b34801561049057600080fd5b506104cf600480360360808110156104a757600080fd5b506001600160a01b0381358116916020810135909116906040810135906060013515156108ff565b604080519115158252519081900360200190f35b3480156104ef57600080fd5b506103a6610d91565b34801561050457600080fd5b506102a2610d96565b34801561051957600080fd5b50610375610d9c565b34801561052e57600080fd5b506103a6610da2565b34801561054357600080fd5b506102a2610da7565b34801561055857600080fd5b506102a26004803603602081101561056f57600080fd5b50356001600160a01b0316610dac565b34801561058b57600080fd5b506103a6610dbe565b3480156105a057600080fd5b50610375610dc3565b3480156105b557600080fd5b50610375610dc9565b3480156105ca57600080fd5b506102a2610dcf565b3480156105df57600080fd5b506104cf610dd5565b3480156105f457600080fd5b506102a2610dde565b34801561060957600080fd5b506102f3610de4565b34801561061e57600080fd5b506106e16004803603604081101561063557600080fd5b81019060208101813564010000000081111561065057600080fd5b82018360208201111561066257600080fd5b8035906020019184600183028401116401000000008311171561068457600080fd5b9193909290916020810190356401000000008111156106a257600080fd5b8201836020820111156106b457600080fd5b803590602001918460018302840111640100000000831117156106d657600080fd5b509092509050610de9565b005b3480156106ef57600080fd5b506102a2611537565b34801561070457600080fd5b506102a26004803603602081101561071b57600080fd5b503561153d565b34801561072e57600080fd5b506102a26004803603602081101561074557600080fd5b5035611598565b34801561075857600080fd5b506103756115b1565b34801561076d57600080fd5b506102a26115b7565b34801561078257600080fd5b506103756115bd565b34801561079757600080fd5b506102a26115c3565b3480156107ac57600080fd5b506106e16115c9565b3480156107c157600080fd5b506106e1600480360360208110156107d857600080fd5b50356001600160a01b0316611692565b3480156107f457600080fd5b506103756004803603602081101561080b57600080fd5b50356117eb565b34801561081e57600080fd5b506103756117f8565b34801561083357600080fd5b506103a66117fe565b34801561084857600080fd5b50610375611803565b34801561085d57600080fd5b506102a26004803603602081101561087457600080fd5b50356001600160a01b0316611809565b600181565b602881565b605081565b606481565b600b5481565b60015481565b600c5481565b600681815481106108b757fe5b6000918252602090912001546001600160a01b0316905081565b60076020526000908152604090205481565b61100181565b603881565b600881565b61200081565b61100581565b6000805460ff16610957576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604482015290519081900360640190fd5b33612000146109975760405162461bcd60e51b815260040180806020018281038252602f815260200180612377602f913960400191505060405180910390fd5b60008215610a4a576110026001600160a01b0316639a99b4f06110056109c8600e548861181b90919063ffffffff16565b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610a1757600080fd5b505af1158015610a2b573d6000803e3d6000fd5b505050506040513d6020811015610a4157600080fd5b50519050610b59565b604080516309a99b4f60e41b8152611005600482015260248101869052905161100491639a99b4f09160448083019260209291908290030181600087803b158015610a9457600080fd5b505af1158015610aa8573d6000803e3d6000fd5b505050506040513d6020811015610abe57600080fd5b5051600e5490915015610b5957600e54604080516309a99b4f60e41b81526110056004820152602481019290925251610b569161100291639a99b4f0916044808201926020929091908290030181600087803b158015610b1d57600080fd5b505af1158015610b31573d6000803e3d6000fd5b505050506040513d6020811015610b4757600080fd5b5051829063ffffffff61181b16565b90505b600c805460010190556000610b6d8261187e565b600954909150610b83908263ffffffff61181b16565b600955600a54610bab908290610b9f908563ffffffff61181b16565b9063ffffffff6118a716565b600a556001600160a01b038716600090815260056020526040902054610c1757600680546001810182556000919091527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b0319166001600160a01b0389161790555b6001600160a01b038088166000908152600560209081526040808320805460010190559289168252600790522054610c9557600880546001810182556000919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319166001600160a01b0388161790555b6001600160a01b038616600090815260076020526040902080546001019055600c54606411610d8457600b54600954600a5460408051938452602084019290925282820152517f2649b1b772a1a74bd332a67695e285317dd722941166595741c60a00fa65bb759181900360600190a16000610d0f6118e9565b90506000610d1b611bcd565b6001600160a01b0389166000908152600d6020526040902054909150610d59908290610d4d908563ffffffff61181b16565b9063ffffffff61181b16565b6001600160a01b0389166000908152600d6020526040812091909155600b80546001019055600c5550505b5060019695505050505050565b600281565b60035481565b61100881565b600b81565b600581565b60056020526000908152604090205481565b600981565b61100781565b61100681565b600a5481565b60005460ff1681565b60045481565b600081565b3361100714610e295760405162461bcd60e51b815260040180806020018281038252602e8152602001806122bc602e913960400191505060405180910390fd5b60005460ff16610e6a5760405162461bcd60e51b81526004018080602001828103825260218152602001806122ea6021913960400191505060405180910390fd5b610ede84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601f81527f68656164657252656c61796572526577617264526174654d6f6c6563756c650060208201529150611e4b9050565b15610fab5760208114610f225760405162461bcd60e51b81526004018080602001828103825260328152602001806123a66032913960400191505060405180910390fd5b604080516020601f8401819004810282018101909252828152600091610f6091858580838501838280828437600092019190915250611f3292505050565b9050600254811115610fa35760405162461bcd60e51b81526004018080602001828103825260608152602001806121956060913960600191505060405180910390fd5b6001556114a5565b61100484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051606081019091526022808252909250905061229a6020830139611e4b565b156110dc57602081146110485760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161108691858580838501838280828437600092019190915250611f3292505050565b9050801580159061109957506001548110155b6110d45760405162461bcd60e51b815260040180806020018281038252606c81526020018061230b606c913960800191505060405180910390fd5b6002556114a5565b61115084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601a81527f63616c6c6572436f6d70656e736174696f6e4d6f6c6563756c6500000000000060208201529150611e4b9050565b1561121d57602081146111945760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f84018190048102820181019092528281526000916111d291858580838501838280828437600092019190915250611f3292505050565b90506004548111156112155760405162461bcd60e51b81526004018080602001828103825260568152602001806121f56056913960600191505060405180910390fd5b6003556114a5565b61129184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601d81527f63616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f7200000060208201529150611e4b9050565b1561136957602081146112d55760405162461bcd60e51b815260040180806020018281038252602e81526020018061224b602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161131391858580838501838280828437600092019190915250611f3292505050565b9050801580159061132657506003548110155b6113615760405162461bcd60e51b81526004018080602001828103825260618152602001806121066061913960800191505060405180910390fd5b6004556114a5565b6113dd84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601b81527f64796e616d69634578747261496e63656e74697665416d6f756e74000000000060208201529150611e4b9050565b1561146857602081146114215760405162461bcd60e51b815260040180806020018281038252602e815260200180612167602e913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161145f91858580838501838280828437600092019190915250611f3292505050565b600e55506114a5565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b60025481565b60006028821161154e575080611593565b81602810801561155f575060508211155b1561156c57506028611593565b60508211801561157d5750606e8211155b1561158d57506078819003611593565b50600481045b919050565b6000602882116115a9575080611593565b506028611593565b61100281565b600e5481565b61100381565b60095481565b60005460ff1615611621576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b60005460ff161561166f576040805162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b60018080556005600255600381905560506004556000805460ff19169091179055565b6001600160a01b0381166000908152600d6020526040902054806116f1576040805162461bcd60e51b81526020600482015260116024820152701b9bc81c995b185e595c881c995dd85c99607a1b604482015290519081900360640190fd5b6001600160a01b0382166000818152600d60205260408082208290555184929184156108fc02918591818181858888f193505050506117a15760405161100290819084156108fc029085906000818181858888f1935050505015801561175b573d6000803e3d6000fd5b506040805161100281526020810185905281517f24502838a334c8f2bb2ee1f8262a4fa7183e4489a717e96cc824e325f8b39e11929181900390910190a15050506117e8565b604080516001600160a01b03851681526020810184905281517f24502838a334c8f2bb2ee1f8262a4fa7183e4489a717e96cc824e325f8b39e11929181900390910190a150505b50565b600881815481106108b757fe5b61100081565b600381565b61100481565b600d6020526000908152604090205481565b600082820183811015611875576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b600061187860025461189b60015485611f3790919063ffffffff16565b9063ffffffff611f9016565b600061187583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611fd2565b600954600680546040805160208084028201810190925282815260009493859360609383018282801561194557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611927575b5050505050905060608151604051908082528060200260200182016040528015611979578160200160208202803683370190505b50905060005b8251811015611a0657600083828151811061199657fe5b6020026020010151905060006119d060056000846001600160a01b03166001600160a01b0316815260200190815260200160002054611598565b9050808484815181106119df57fe5b60209081029190910101526119fa868263ffffffff61181b16565b9550505060010161197f565b506000611a2460045461189b60035488611f3790919063ffffffff16565b9050611a36858263ffffffff6118a716565b94508460015b8451811015611b0d576000611a718761189b8a888681518110611a5b57fe5b6020026020010151611f3790919063ffffffff16565b9050611abe81600d6000898681518110611a8757fe5b60200260200101516001600160a01b03166001600160a01b031681526020019081526020016000205461181b90919063ffffffff16565b600d6000888581518110611ace57fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055611b02838263ffffffff6118a716565b925050600101611a3c565b50611b2381600d600087600081518110611a8757fe5b600d600086600081518110611b3457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002081905550600060098190555060008090505b8451811015611bb55760056000868381518110611b8757fe5b6020908102919091018101516001600160a01b03168252810191909152604001600090812055600101611b6e565b50611bc2600660006120ce565b509450505050505b90565b600a546008805460408051602080840282018101909252828152600094938593606093830182828015611c2957602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611c0b575b5050505050905060608151604051908082528060200260200182016040528015611c5d578160200160208202803683370190505b50905060005b8251811015611cdc576000838281518110611c7a57fe5b602002602001015190506000611cb460076000846001600160a01b03166001600160a01b031681526020019081526020016000205461153d565b905080848481518110611cc357fe5b6020908102919091010152949094019350600101611c63565b506000611cfa60045461189b60035488611f3790919063ffffffff16565b9050611d0c858263ffffffff6118a716565b94508460015b8451811015611d96576000611d318761189b8a888681518110611a5b57fe5b9050611d4781600d6000898681518110611a8757fe5b600d6000888581518110611d5757fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055611d8b838263ffffffff6118a716565b925050600101611d12565b50611dac81600d600087600081518110611a8757fe5b600d600086600081518110611dbd57fe5b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055506000600a8190555060008090505b8451811015611e3e5760076000868381518110611e1057fe5b6020908102919091018101516001600160a01b03168252810191909152604001600090812055600101611df7565b50611bc2600860006120ce565b6000816040516020018082805190602001908083835b60208310611e805780518252601f199092019160209182019101611e61565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310611eee5780518252601f199092019160209182019101611ecf565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b600082611f4657506000611878565b82820282848281611f5357fe5b04146118755760405162461bcd60e51b81526004018080602001828103825260218152602001806122796021913960400191505060405180910390fd5b600061187583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612069565b600081848411156120615760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561202657818101518382015260200161200e565b50505050905090810190601f1680156120535780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600081836120b85760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561202657818101518382015260200161200e565b5060008385816120c457fe5b0495945050505050565b50805460008255906000526020600020908101906117e89190611bca91905b8082111561210157600081556001016120ed565b509056fe746865206e657743616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f72206d757374206e6f74206265207a65726f20616e64206e6f206c657373207468616e2063616c6c6572436f6d70656e736174696f6e4d6f6c6563756c656c656e677468206f662064796e616d69634578747261496e63656e74697665416d6f756e74206d69736d617463686e65772068656164657252656c61796572526577617264526174654d6f6c6563756c652073686f756c646e27742062652067726561746572207468616e2068656164657252656c617965725265776172645261746544656e6f6d696e61746f726e65772063616c6c6572436f6d70656e736174696f6e4d6f6c6563756c652073686f756c646e27742062652067726561746572207468616e2063616c6c6572436f6d70656e736174696f6e44656e6f6d696e61746f726c656e677468206f6620726577617264466f7256616c696461746f725365744368616e6765206d69736d61746368536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7768656164657252656c617965725265776172645261746544656e6f6d696e61746f72746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374636f6e747261637420686173206e6f74206265656e20696e697469616c697a6564746865206e65772068656164657252656c617965725265776172645261746544656e6f6d696e61746f72206d757374206e6f74206265207a65726f20616e64206e6f206c657373207468616e2068656164657252656c61796572526577617264526174654d6f6c6563756c65746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163746c656e677468206f662068656164657252656c61796572526577617264526174654d6f6c6563756c65206d69736d61746368a2646970667358221220ed761a0a8bb4eac3f5f94897efb6059f8cb261a19ed73bef336cbc05af2a532064736f6c63430006040033" }, "0x0000000000000000000000000000000000001006": { "balance": "0x0", - "code": "0x6080604052600436106101c25760003560e01c806395468d26116100f7578063c81b166211610095578063f9a2bbc711610064578063f9a2bbc714610529578063fb7cfdd71461053e578063fc3e590814610553578063fd6a687914610568576101c2565b8063c81b1662146104d5578063dc927faf146104ea578063e1c7392a146104ff578063e79a198f14610514576101c2565b8063a1a11bf5116100d1578063a1a11bf5146103c7578063a78abc16146103dc578063ab51bb96146103f1578063ac43175114610406576101c2565b806395468d261461038857806396713da91461039d5780639dc09262146103b2576101c2565b8063541d55481161016457806370fd5bad1161013e57806370fd5bad1461033457806375d47a0a146103495780637942fd051461035e5780637ae2308814610373576101c2565b8063541d5548146102b15780636a87d780146102f85780636e47b4821461031f576101c2565b806343756e5c116101a057806343756e5c1461022a578063493279b11461025b5780634bf6c8821461028757806351e806721461029c576101c2565b80630bee7a67146101c75780631aa3a008146101f55780633dffc387146101ff575b600080fd5b3480156101d357600080fd5b506101dc61057d565b6040805163ffffffff9092168252519081900360200190f35b6101fd610582565b005b34801561020b57600080fd5b5061021461077d565b6040805160ff9092168252519081900360200190f35b34801561023657600080fd5b5061023f610782565b604080516001600160a01b039092168252519081900360200190f35b34801561026757600080fd5b50610270610788565b6040805161ffff9092168252519081900360200190f35b34801561029357600080fd5b5061021461078d565b3480156102a857600080fd5b5061023f610792565b3480156102bd57600080fd5b506102e4600480360360208110156102d457600080fd5b50356001600160a01b0316610798565b604080519115158252519081900360200190f35b34801561030457600080fd5b5061030d6107b6565b60408051918252519081900360200190f35b34801561032b57600080fd5b5061023f6107bc565b34801561034057600080fd5b506102146107c2565b34801561035557600080fd5b5061023f6107c7565b34801561036a57600080fd5b506102146107cd565b34801561037f57600080fd5b5061030d6107d2565b34801561039457600080fd5b5061030d6107df565b3480156103a957600080fd5b506102146107eb565b3480156103be57600080fd5b5061023f6107f0565b3480156103d357600080fd5b5061023f6107f6565b3480156103e857600080fd5b506102e46107fc565b3480156103fd57600080fd5b506101dc610805565b34801561041257600080fd5b506101fd6004803603604081101561042957600080fd5b81019060208101813564010000000081111561044457600080fd5b82018360208201111561045657600080fd5b8035906020019184600183028401116401000000008311171561047857600080fd5b91939092909160208101903564010000000081111561049657600080fd5b8201836020820111156104a857600080fd5b803590602001918460018302840111640100000000831117156104ca57600080fd5b50909250905061080a565b3480156104e157600080fd5b5061023f610c2c565b3480156104f657600080fd5b5061023f610c32565b34801561050b57600080fd5b506101fd610c38565b34801561052057600080fd5b506101fd610cba565b34801561053557600080fd5b5061023f610e73565b34801561054a57600080fd5b5061030d610e79565b34801561055f57600080fd5b50610214610e7f565b34801561057457600080fd5b5061023f610e84565b606481565b3360009081526004602052604090205460ff16156105df576040805162461bcd60e51b81526020600482015260156024820152741c995b185e595c88185b1c9958591e48195e1a5cdd605a1b604482015290519081900360640190fd5b60005460ff16610632576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b61063b33610e8a565b156106775760405162461bcd60e51b815260040180806020018281038252602781526020018061109c6027913960400191505060405180910390fd5b3332146106c1576040805162461bcd60e51b81526020600482015260136024820152721b9bc81c1c9bde1e481a5cc8185b1b1bddd959606a1b604482015290519081900360640190fd5b60015434146107015760405162461bcd60e51b81526004018080602001828103825260258152602001806110776025913960400191505060405180910390fd5b604080518082018252600180548252600254602080840191825233600081815260038352868120955186559251948401949094556004815290849020805460ff1916909217909155825191825291517fdb33a09d38b59a8fa8b7d92a1d82c8015e99f05f67ae9c9ae623157767959496929181900390910190a1565b600181565b61100181565b606081565b600881565b61200081565b6001600160a01b031660009081526004602052604090205460ff1690565b60025481565b61100581565b600281565b61100881565b600b81565b68056bc75e2d6310000081565b67016345785d8a000081565b600981565b61100781565b61100681565b60005460ff1681565b600081565b60005460ff1661085d576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b336110071461089d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806110c3602e913960400191505060405180910390fd5b61090384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e1c995c5d5a5c995911195c1bdcda5d608a1b60208201529150610e909050565b15610a0657602081146109475760405162461bcd60e51b81526004018080602001828103825260228152602001806110f16022913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161098591858580838501838280828437600092019190915250610f7792505050565b90506001811180156109a05750683635c9adc5dea000008111155b80156109ad575060025481115b6109fe576040805162461bcd60e51b815260206004820181905260248201527f7468652072657175697265644465706f736974206f7574206f662072616e6765604482015290519081900360640190fd5b600155610b9a565b610a6184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260048152636475657360e01b60208201529150610e909050565b15610b5d5760208114610abb576040805162461bcd60e51b815260206004820152601760248201527f6c656e677468206f662064756573206d69736d61746368000000000000000000604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091610af991858580838501838280828437600092019190915250610f7792505050565b9050600081118015610b0c575060015481105b610b55576040805162461bcd60e51b81526020600482015260156024820152747468652064756573206f7574206f662072616e676560581b604482015290519081900360640190fd5b600255610b9a565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b60005460ff1615610c90576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b68056bc75e2d63100000600190815567016345785d8a00006002556000805460ff19169091179055565b3360009081526004602052604090205460ff16610d15576040805162461bcd60e51b81526020600482015260146024820152731c995b185e595c88191bc81b9bdd08195e1a5cdd60621b604482015290519081900360640190fd5b60005460ff16610d68576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b610d7061105c565b5033600081815260036020908152604091829020825180840190935280548084526001909101549183018290529192916108fc91610db4919063ffffffff610f7c16565b6040518115909202916000818181858888f19350505050158015610ddc573d6000803e3d6000fd5b50602081015160405161100291829181156108fc0291906000818181858888f19350505050158015610e12573d6000803e3d6000fd5b50336000818152600460209081526040808320805460ff191690556003825280832083815560010192909255815192835290517fd17202129b83db7880d6b9f25df81c58ad46f7e0e2c92236b1aa10663a4876679281900390910190a15050565b61100081565b60015481565b600381565b61100481565b3b151590565b6000816040516020018082805190602001908083835b60208310610ec55780518252601f199092019160209182019101610ea6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610f335780518252601f199092019160209182019101610f14565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b6000610fbe83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610fc5565b9392505050565b600081848411156110545760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611019578181015183820152602001611001565b50505050905090810190601f1680156110465780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60405180604001604052806000815260200160008152509056fe6465706f7369742076616c7565206973206e6f742065786163746c79207468652073616d65636f6e7472616374206973206e6f7420616c6c6f77656420746f20626520612072656c61796572746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662072657175697265644465706f736974206d69736d61746368a264697066735822122011778451ed6d3e3757ce2e74acfc7fa17bf5d16f07168a6ce073d7c91e583c8c64736f6c63430006040033" + "code": "0x6080604052600436106101c25760003560e01c806395468d26116100f7578063c81b166211610095578063f9a2bbc711610064578063f9a2bbc714610529578063fb7cfdd71461053e578063fc3e590814610553578063fd6a687914610568576101c2565b8063c81b1662146104d5578063dc927faf146104ea578063e1c7392a146104ff578063e79a198f14610514576101c2565b8063a1a11bf5116100d1578063a1a11bf5146103c7578063a78abc16146103dc578063ab51bb96146103f1578063ac43175114610406576101c2565b806395468d261461038857806396713da91461039d5780639dc09262146103b2576101c2565b8063541d55481161016457806370fd5bad1161013e57806370fd5bad1461033457806375d47a0a146103495780637942fd051461035e5780637ae2308814610373576101c2565b8063541d5548146102b15780636a87d780146102f85780636e47b4821461031f576101c2565b806343756e5c116101a057806343756e5c1461022a578063493279b11461025b5780634bf6c8821461028757806351e806721461029c576101c2565b80630bee7a67146101c75780631aa3a008146101f55780633dffc387146101ff575b600080fd5b3480156101d357600080fd5b506101dc61057d565b6040805163ffffffff9092168252519081900360200190f35b6101fd610582565b005b34801561020b57600080fd5b5061021461077d565b6040805160ff9092168252519081900360200190f35b34801561023657600080fd5b5061023f610782565b604080516001600160a01b039092168252519081900360200190f35b34801561026757600080fd5b50610270610788565b6040805161ffff9092168252519081900360200190f35b34801561029357600080fd5b5061021461078d565b3480156102a857600080fd5b5061023f610792565b3480156102bd57600080fd5b506102e4600480360360208110156102d457600080fd5b50356001600160a01b0316610798565b604080519115158252519081900360200190f35b34801561030457600080fd5b5061030d6107b6565b60408051918252519081900360200190f35b34801561032b57600080fd5b5061023f6107bc565b34801561034057600080fd5b506102146107c2565b34801561035557600080fd5b5061023f6107c7565b34801561036a57600080fd5b506102146107cd565b34801561037f57600080fd5b5061030d6107d2565b34801561039457600080fd5b5061030d6107df565b3480156103a957600080fd5b506102146107eb565b3480156103be57600080fd5b5061023f6107f0565b3480156103d357600080fd5b5061023f6107f6565b3480156103e857600080fd5b506102e46107fc565b3480156103fd57600080fd5b506101dc610805565b34801561041257600080fd5b506101fd6004803603604081101561042957600080fd5b81019060208101813564010000000081111561044457600080fd5b82018360208201111561045657600080fd5b8035906020019184600183028401116401000000008311171561047857600080fd5b91939092909160208101903564010000000081111561049657600080fd5b8201836020820111156104a857600080fd5b803590602001918460018302840111640100000000831117156104ca57600080fd5b50909250905061080a565b3480156104e157600080fd5b5061023f610c2c565b3480156104f657600080fd5b5061023f610c32565b34801561050b57600080fd5b506101fd610c38565b34801561052057600080fd5b506101fd610cba565b34801561053557600080fd5b5061023f610e73565b34801561054a57600080fd5b5061030d610e79565b34801561055f57600080fd5b50610214610e7f565b34801561057457600080fd5b5061023f610e84565b606481565b3360009081526004602052604090205460ff16156105df576040805162461bcd60e51b81526020600482015260156024820152741c995b185e595c88185b1c9958591e48195e1a5cdd605a1b604482015290519081900360640190fd5b60005460ff16610632576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b61063b33610e8a565b156106775760405162461bcd60e51b815260040180806020018281038252602781526020018061109c6027913960400191505060405180910390fd5b3332146106c1576040805162461bcd60e51b81526020600482015260136024820152721b9bc81c1c9bde1e481a5cc8185b1b1bddd959606a1b604482015290519081900360640190fd5b60015434146107015760405162461bcd60e51b81526004018080602001828103825260258152602001806110776025913960400191505060405180910390fd5b604080518082018252600180548252600254602080840191825233600081815260038352868120955186559251948401949094556004815290849020805460ff1916909217909155825191825291517fdb33a09d38b59a8fa8b7d92a1d82c8015e99f05f67ae9c9ae623157767959496929181900390910190a1565b600181565b61100181565b603881565b600881565b61200081565b6001600160a01b031660009081526004602052604090205460ff1690565b60025481565b61100581565b600281565b61100881565b600b81565b68056bc75e2d6310000081565b67016345785d8a000081565b600981565b61100781565b61100681565b60005460ff1681565b600081565b60005460ff1661085d576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b336110071461089d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806110c3602e913960400191505060405180910390fd5b61090384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e1c995c5d5a5c995911195c1bdcda5d608a1b60208201529150610e909050565b15610a0657602081146109475760405162461bcd60e51b81526004018080602001828103825260228152602001806110f16022913960400191505060405180910390fd5b604080516020601f840181900481028201810190925282815260009161098591858580838501838280828437600092019190915250610f7792505050565b90506001811180156109a05750683635c9adc5dea000008111155b80156109ad575060025481115b6109fe576040805162461bcd60e51b815260206004820181905260248201527f7468652072657175697265644465706f736974206f7574206f662072616e6765604482015290519081900360640190fd5b600155610b9a565b610a6184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260048152636475657360e01b60208201529150610e909050565b15610b5d5760208114610abb576040805162461bcd60e51b815260206004820152601760248201527f6c656e677468206f662064756573206d69736d61746368000000000000000000604482015290519081900360640190fd5b604080516020601f8401819004810282018101909252828152600091610af991858580838501838280828437600092019190915250610f7792505050565b9050600081118015610b0c575060015481105b610b55576040805162461bcd60e51b81526020600482015260156024820152747468652064756573206f7574206f662072616e676560581b604482015290519081900360640190fd5b600255610b9a565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b60005460ff1615610c90576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b68056bc75e2d63100000600190815567016345785d8a00006002556000805460ff19169091179055565b3360009081526004602052604090205460ff16610d15576040805162461bcd60e51b81526020600482015260146024820152731c995b185e595c88191bc81b9bdd08195e1a5cdd60621b604482015290519081900360640190fd5b60005460ff16610d68576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b610d7061105c565b5033600081815260036020908152604091829020825180840190935280548084526001909101549183018290529192916108fc91610db4919063ffffffff610f7c16565b6040518115909202916000818181858888f19350505050158015610ddc573d6000803e3d6000fd5b50602081015160405161100291829181156108fc0291906000818181858888f19350505050158015610e12573d6000803e3d6000fd5b50336000818152600460209081526040808320805460ff191690556003825280832083815560010192909255815192835290517fd17202129b83db7880d6b9f25df81c58ad46f7e0e2c92236b1aa10663a4876679281900390910190a15050565b61100081565b60015481565b600381565b61100481565b3b151590565b6000816040516020018082805190602001908083835b60208310610ec55780518252601f199092019160209182019101610ea6565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610f335780518252601f199092019160209182019101610f14565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b6000610fbe83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610fc5565b9392505050565b600081848411156110545760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611019578181015183820152602001611001565b50505050905090810190601f1680156110465780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60405180604001604052806000815260200160008152509056fe6465706f7369742076616c7565206973206e6f742065786163746c79207468652073616d65636f6e7472616374206973206e6f7420616c6c6f77656420746f20626520612072656c61796572746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662072657175697265644465706f736974206d69736d61746368a2646970667358221220449507f2557413401b33bd1aa888e40f31523a5d010a891cf7383c0090d7f49a64736f6c63430006040033" }, "0x0000000000000000000000000000000000001007": { "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c8063831d65d1116100de578063ab51bb9611610097578063dc927faf11610071578063dc927faf14610486578063f9a2bbc71461048e578063fc3e590814610496578063fd6a68791461049e5761018e565b8063ab51bb96146103fc578063c81b166214610404578063c8509d811461040c5761018e565b8063831d65d11461034457806396713da9146103c05780639ab1a373146103c85780639dc09262146103d0578063a1a11bf5146103d8578063a78abc16146103e05761018e565b8063493279b11161014b5780636e47b482116101255780636e47b4821461032457806370fd5bad1461032c57806375d47a0a146103345780637942fd051461033c5761018e565b8063493279b1146102f55780634bf6c8821461031457806351e806721461031c5761018e565b80630bee7a67146101935780631182b875146101b45780633a21baae146102a35780633dffc387146102ab57806343756e5c146102c95780634900c4ea146102ed575b600080fd5b61019b6104a6565b6040805163ffffffff9092168252519081900360200190f35b61022e600480360360408110156101ca57600080fd5b60ff82351691908101906040810160208201356401000000008111156101ef57600080fd5b82018360208201111561020157600080fd5b8035906020019184600183028401116401000000008311171561022357600080fd5b5090925090506104ab565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610268578181015183820152602001610250565b50505050905090810190601f1680156102955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61019b61059a565b6102b361059f565b6040805160ff9092168252519081900360200190f35b6102d16105a4565b604080516001600160a01b039092168252519081900360200190f35b6102b36105aa565b6102fd6105af565b6040805161ffff9092168252519081900360200190f35b6102b36105b4565b6102d16105b9565b6102d16105bf565b6102b36105c5565b6102d16105ca565b6102b36105d0565b6103be6004803603604081101561035a57600080fd5b60ff823516919081019060408101602082013564010000000081111561037f57600080fd5b82018360208201111561039157600080fd5b803590602001918460018302840111640100000000831117156103b357600080fd5b5090925090506105d5565b005b6102b3610667565b61019b61066c565b6102d1610671565b6102d1610677565b6103e861067d565b604080519115158252519081900360200190f35b61019b6105aa565b6102d1610686565b6103be6004803603604081101561042257600080fd5b60ff823516919081019060408101602082013564010000000081111561044757600080fd5b82018360208201111561045957600080fd5b8035906020019184600183028401116401000000008311171561047b57600080fd5b50909250905061068c565b6102d1610703565b6102d1610709565b6102b361070f565b6102d1610714565b606481565b606033612000146104ed5760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b6104f5611382565b600061053685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061071a92505050565b91509150806105525761054960646107e0565b92505050610593565b600061055d8361084a565b905063ffffffff811661058457505060408051600081526020810190915291506105939050565b61058d816107e0565b93505050505b9392505050565b606681565b600181565b61100181565b600081565b606081565b600881565b61200081565b61100581565b600281565b61100881565b600b81565b33612000146106155760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642061636b207061636b6167650000604482015290519081900360640190fd5b505050565b600981565b606581565b61100781565b61100681565b60005460ff1681565b61100281565b33612000146106cc5760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b60405162461bcd60e51b81526004018080602001828103825260238152602001806114166023913960400191505060405180910390fd5b61100381565b61100081565b600381565b61100481565b610722611382565b600061072c611382565b6107346113ac565b61074561074086610beb565b610c10565b90506000805b61075483610c5a565b156107d357806107765761076f61076a84610c7b565b610cc9565b84526107cb565b80600114156107955761078b61076a84610c7b565b60208501526107cb565b80600214156107c6576107af6107aa84610c7b565b610d42565b6001600160a01b03166040850152600191506107cb565b6107d3565b60010161074b565b5091935090915050915091565b604080516001808252818301909252606091829190816020015b60608152602001906001900390816107fa5790505090506108208363ffffffff16610d62565b8160008151811061082d57fe5b602002602001018190525061084181610d75565b9150505b919050565b60006108598260400151610dff565b6108c557604080516020808252601c908201527f74686520746172676574206973206e6f74206120636f6e7472616374000000008183015290517f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb29181900360600190a1506065610845565b81604001516001600160a01b031663ac431751836000015184602001516040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561093257818101518382015260200161091a565b50505050905090810190601f16801561095f5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561099257818101518382015260200161097a565b50505050905090810190601f1680156109bf5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156109e057600080fd5b505af19250505080156109f1575060015b610be3576040516000815260443d1015610a0d57506000610aaa565b60046000803e60005160e01c6308c379a08114610a2e576000915050610aaa565b60043d036004833e81513d602482011167ffffffffffffffff82111715610a5a57600092505050610aaa565b808301805167ffffffffffffffff811115610a7c576000945050505050610aaa565b8060208301013d8601811115610a9a57600095505050505050610aaa565b601f01601f191660405250925050505b80610ab55750610b58565b7f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015610b14578181015183820152602001610afc565b50505050905090810190601f168015610b415780820380516001836020036101000a031916815260200191505b509250505060405180910390a16066915050610845565b3d808015610b82576040519150601f19603f3d011682016040523d82523d6000602084013e610b87565b606091505b5060408051602080825283518183015283517f1279f84165b4fd69c35e1f338ff107231b036c655cd1688851e011ce617c4e8d938593928392918301919085019080838360008315610b14578181015183820152602001610afc565b506000919050565b610bf36113cc565b506040805180820190915281518152602082810190820152919050565b610c186113ac565b610c2182610e05565b610c2a57600080fd5b6000610c398360200151610e3f565b60208085015160408051808201909152868152920190820152915050919050565b6000610c646113cc565b505080518051602091820151919092015191011190565b610c836113cc565b610c8c82610c5a565b610c9557600080fd5b60208201516000610ca582610ea2565b80830160209586015260408051808201909152908152938401919091525090919050565b8051606090610cd757600080fd5b6000610ce68360200151610e3f565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015610d1d576020820181803683370190505b5090506000816020019050610d39848760200151018285610fd5565b50949350505050565b8051600090601514610d5357600080fd5b610d5c82611020565b92915050565b6060610d5c610d70836110d5565b6111bb565b6060815160001415610d965750604080516000815260208101909152610845565b606082600081518110610da557fe5b602002602001015190506000600190505b8351811015610de657610ddc82858381518110610dcf57fe5b602002602001015161120d565b9150600101610db6565b50610841610df9825160c060ff1661128a565b8261120d565b3b151590565b8051600090610e1657506000610845565b6020820151805160001a9060c0821015610e3557600092505050610845565b5060019392505050565b8051600090811a6080811015610e59576000915050610845565b60b8811080610e74575060c08110801590610e74575060f881105b15610e83576001915050610845565b60c0811015610e975760b519019050610845565b60f519019050610845565b80516000908190811a6080811015610ebd5760019150610fce565b60b8811015610ed257607e1981019150610fce565b60c0811015610f4c57600060b78203600186019550806020036101000a865104915060018101820193505080831015610f46576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50610fce565b60f8811015610f615760be1981019150610fce565b600060f78203600186019550806020036101000a865104915060018101820193505080831015610fcc576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80610fdf57610662565b5b60208110610fff578251825260209283019290910190601f1901610fe0565b915181516020939093036101000a6000190180199091169216919091179052565b80516000901580159061103557508151602110155b61103e57600080fd5b600061104d8360200151610e3f565b905080836000015110156110a8576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015610d3957506020919091036101000a90049392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166111195750601861113d565b6fffffffffffffffffffffffffffffffff1984166111395750601061113d565b5060005b60208110156111735781818151811061115257fe5b01602001516001600160f81b0319161561116b57611173565b60010161113d565b60008160200390506060816040519080825280601f01601f1916602001820160405280156111a8576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156111ed5750607f60f81b826000815181106111db57fe5b01602001516001600160f81b03191611155b156111f9575080610845565b610d5c61120b8351608060ff1661128a565b835b6060806040519050835180825260208201818101602087015b8183101561123e578051835260209283019201611226565b50855184518101855292509050808201602086015b8183101561126b578051835260209283019201611253565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106112da576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116113345782840160f81b8160008151811061131657fe5b60200101906001600160f81b031916908160001a9053509050610d5c565b606061133f856110d5565b90508381510160370160f81b8260008151811061135857fe5b60200101906001600160f81b031916908160001a905350611379828261120d565b95945050505050565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b60405180604001604052806113bf6113cc565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163747265636569766520756e6578706563746564206661696c2061636b207061636b616765a2646970667358221220ea2b2b402a564a222b3f3e7c0f671622652543c9c5f6cb6c7b8db265ae9ebe4564736f6c63430006040033" + "code": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c8063831d65d1116100de578063ab51bb9611610097578063dc927faf11610071578063dc927faf14610486578063f9a2bbc71461048e578063fc3e590814610496578063fd6a68791461049e5761018e565b8063ab51bb96146103fc578063c81b166214610404578063c8509d811461040c5761018e565b8063831d65d11461034457806396713da9146103c05780639ab1a373146103c85780639dc09262146103d0578063a1a11bf5146103d8578063a78abc16146103e05761018e565b8063493279b11161014b5780636e47b482116101255780636e47b4821461032457806370fd5bad1461032c57806375d47a0a146103345780637942fd051461033c5761018e565b8063493279b1146102f55780634bf6c8821461031457806351e806721461031c5761018e565b80630bee7a67146101935780631182b875146101b45780633a21baae146102a35780633dffc387146102ab57806343756e5c146102c95780634900c4ea146102ed575b600080fd5b61019b6104a6565b6040805163ffffffff9092168252519081900360200190f35b61022e600480360360408110156101ca57600080fd5b60ff82351691908101906040810160208201356401000000008111156101ef57600080fd5b82018360208201111561020157600080fd5b8035906020019184600183028401116401000000008311171561022357600080fd5b5090925090506104ab565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610268578181015183820152602001610250565b50505050905090810190601f1680156102955780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61019b61059a565b6102b361059f565b6040805160ff9092168252519081900360200190f35b6102d16105a4565b604080516001600160a01b039092168252519081900360200190f35b6102b36105aa565b6102fd6105af565b6040805161ffff9092168252519081900360200190f35b6102b36105b4565b6102d16105b9565b6102d16105bf565b6102b36105c5565b6102d16105ca565b6102b36105d0565b6103be6004803603604081101561035a57600080fd5b60ff823516919081019060408101602082013564010000000081111561037f57600080fd5b82018360208201111561039157600080fd5b803590602001918460018302840111640100000000831117156103b357600080fd5b5090925090506105d5565b005b6102b3610667565b61019b61066c565b6102d1610671565b6102d1610677565b6103e861067d565b604080519115158252519081900360200190f35b61019b6105aa565b6102d1610686565b6103be6004803603604081101561042257600080fd5b60ff823516919081019060408101602082013564010000000081111561044757600080fd5b82018360208201111561045957600080fd5b8035906020019184600183028401116401000000008311171561047b57600080fd5b50909250905061068c565b6102d1610703565b6102d1610709565b6102b361070f565b6102d1610714565b606481565b606033612000146104ed5760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b6104f5611382565b600061053685858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061071a92505050565b91509150806105525761054960646107e0565b92505050610593565b600061055d8361084a565b905063ffffffff811661058457505060408051600081526020810190915291506105939050565b61058d816107e0565b93505050505b9392505050565b606681565b600181565b61100181565b600081565b603881565b600881565b61200081565b61100581565b600281565b61100881565b600b81565b33612000146106155760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b6040805162461bcd60e51b815260206004820152601e60248201527f7265636569766520756e65787065637465642061636b207061636b6167650000604482015290519081900360640190fd5b505050565b600981565b606581565b61100781565b61100681565b60005460ff1681565b61100281565b33612000146106cc5760405162461bcd60e51b815260040180806020018281038252602f8152602001806113e7602f913960400191505060405180910390fd5b60405162461bcd60e51b81526004018080602001828103825260238152602001806114166023913960400191505060405180910390fd5b61100381565b61100081565b600381565b61100481565b610722611382565b600061072c611382565b6107346113ac565b61074561074086610beb565b610c10565b90506000805b61075483610c5a565b156107d357806107765761076f61076a84610c7b565b610cc9565b84526107cb565b80600114156107955761078b61076a84610c7b565b60208501526107cb565b80600214156107c6576107af6107aa84610c7b565b610d42565b6001600160a01b03166040850152600191506107cb565b6107d3565b60010161074b565b5091935090915050915091565b604080516001808252818301909252606091829190816020015b60608152602001906001900390816107fa5790505090506108208363ffffffff16610d62565b8160008151811061082d57fe5b602002602001018190525061084181610d75565b9150505b919050565b60006108598260400151610dff565b6108c557604080516020808252601c908201527f74686520746172676574206973206e6f74206120636f6e7472616374000000008183015290517f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb29181900360600190a1506065610845565b81604001516001600160a01b031663ac431751836000015184602001516040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561093257818101518382015260200161091a565b50505050905090810190601f16801561095f5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561099257818101518382015260200161097a565b50505050905090810190601f1680156109bf5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156109e057600080fd5b505af19250505080156109f1575060015b610be3576040516000815260443d1015610a0d57506000610aaa565b60046000803e60005160e01c6308c379a08114610a2e576000915050610aaa565b60043d036004833e81513d602482011167ffffffffffffffff82111715610a5a57600092505050610aaa565b808301805167ffffffffffffffff811115610a7c576000945050505050610aaa565b8060208301013d8601811115610a9a57600095505050505050610aaa565b601f01601f191660405250925050505b80610ab55750610b58565b7f70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb2816040518080602001828103825283818151815260200191508051906020019080838360005b83811015610b14578181015183820152602001610afc565b50505050905090810190601f168015610b415780820380516001836020036101000a031916815260200191505b509250505060405180910390a16066915050610845565b3d808015610b82576040519150601f19603f3d011682016040523d82523d6000602084013e610b87565b606091505b5060408051602080825283518183015283517f1279f84165b4fd69c35e1f338ff107231b036c655cd1688851e011ce617c4e8d938593928392918301919085019080838360008315610b14578181015183820152602001610afc565b506000919050565b610bf36113cc565b506040805180820190915281518152602082810190820152919050565b610c186113ac565b610c2182610e05565b610c2a57600080fd5b6000610c398360200151610e3f565b60208085015160408051808201909152868152920190820152915050919050565b6000610c646113cc565b505080518051602091820151919092015191011190565b610c836113cc565b610c8c82610c5a565b610c9557600080fd5b60208201516000610ca582610ea2565b80830160209586015260408051808201909152908152938401919091525090919050565b8051606090610cd757600080fd5b6000610ce68360200151610e3f565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015610d1d576020820181803683370190505b5090506000816020019050610d39848760200151018285610fd5565b50949350505050565b8051600090601514610d5357600080fd5b610d5c82611020565b92915050565b6060610d5c610d70836110d5565b6111bb565b6060815160001415610d965750604080516000815260208101909152610845565b606082600081518110610da557fe5b602002602001015190506000600190505b8351811015610de657610ddc82858381518110610dcf57fe5b602002602001015161120d565b9150600101610db6565b50610841610df9825160c060ff1661128a565b8261120d565b3b151590565b8051600090610e1657506000610845565b6020820151805160001a9060c0821015610e3557600092505050610845565b5060019392505050565b8051600090811a6080811015610e59576000915050610845565b60b8811080610e74575060c08110801590610e74575060f881105b15610e83576001915050610845565b60c0811015610e975760b519019050610845565b60f519019050610845565b80516000908190811a6080811015610ebd5760019150610fce565b60b8811015610ed257607e1981019150610fce565b60c0811015610f4c57600060b78203600186019550806020036101000a865104915060018101820193505080831015610f46576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50610fce565b60f8811015610f615760be1981019150610fce565b600060f78203600186019550806020036101000a865104915060018101820193505080831015610fcc576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b80610fdf57610662565b5b60208110610fff578251825260209283019290910190601f1901610fe0565b915181516020939093036101000a6000190180199091169216919091179052565b80516000901580159061103557508151602110155b61103e57600080fd5b600061104d8360200151610e3f565b905080836000015110156110a8576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015610d3957506020919091036101000a90049392505050565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166111195750601861113d565b6fffffffffffffffffffffffffffffffff1984166111395750601061113d565b5060005b60208110156111735781818151811061115257fe5b01602001516001600160f81b0319161561116b57611173565b60010161113d565b60008160200390506060816040519080825280601f01601f1916602001820160405280156111a8576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156111ed5750607f60f81b826000815181106111db57fe5b01602001516001600160f81b03191611155b156111f9575080610845565b610d5c61120b8351608060ff1661128a565b835b6060806040519050835180825260208201818101602087015b8183101561123e578051835260209283019201611226565b50855184518101855292509050808201602086015b8183101561126b578051835260209283019201611253565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106112da576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b604080516001808252818301909252606091602082018180368337019050509050603784116113345782840160f81b8160008151811061131657fe5b60200101906001600160f81b031916908160001a9053509050610d5c565b606061133f856110d5565b90508381510160370160f81b8260008151811061135857fe5b60200101906001600160f81b031916908160001a905350611379828261120d565b95945050505050565b6040518060600160405280606081526020016060815260200160006001600160a01b031681525090565b60405180604001604052806113bf6113cc565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e74726163747265636569766520756e6578706563746564206661696c2061636b207061636b616765a2646970667358221220a5eefec118f5b467b996b871e3b96c20aa4fe4192a6c4b34c6afc795161d4a9a64736f6c63430006040033" }, "0x0000000000000000000000000000000000001008": { "balance": "0x0", - "code": "0x6080604052600436106103815760003560e01c80637d078e13116101d1578063b795031711610102578063d9e6dae9116100a0578063fa9e91591161006f578063fa9e915914610d38578063fc3e5908146105b2578063fd6a687914610d4d578063fe3a2af514610d6257610381565b8063d9e6dae9146106fc578063dc927faf14610cf9578063e605bca014610d0e578063f9a2bbc714610d2357610381565b8063c8509d81116100dc578063c8509d8114610bdf578063c8e704a4146105b2578063d117a11014610c64578063d7109ce614610ce457610381565b8063b79503171461073b578063bd32d3f9146104d9578063c81b166214610bca57610381565b80639a854bbd1161016f578063a78abc1611610149578063a78abc1614610ad5578063ab51bb9614610aea578063ab67a4851461073b578063ac43175114610aff57610381565b80639a854bbd14610a965780639dc0926214610aab578063a1a11bf514610ac057610381565b8063859180fb116101ab578063859180fb146106e757806394553a4e14610a3757806395b9ad2614610a6c57806396713da914610a8157610381565b80637d078e13146104ee5780637ec816dd1461099b578063831d65d1146109b057610381565b8063493279b1116102b657806366dea52a1161025457806372c4e0861161022357806372c4e0861461081957806375d47a0a146108bd57806377d9dae8146108d25780637942fd051461098657610381565b806366dea52a1461073b5780636b3f1307146107505780636e47b4821461080457806370fd5bad1461073b57610381565b806351e806721161029057806351e80672146107115780635d499b1b146107265780635f558f861461073b57806361368475146106fc57610381565b8063493279b1146106bb5780634bc81c00146106e75780634bf6c882146106fc57610381565b80632e02d77611610323578063401809f9116102fd578063401809f9146105b257806343756e5c146105c7578063445fcefe146105f8578063487c88ac146104ee57610381565b80632e02d7761461054c57806337e6ecda1461057f5780633dffc387146104ee57610381565b80631f91600b1161035f5780631f91600b146104d957806323996b53146104ee57806325c751b7146105035780632d89ac32146104ee57610381565b80630bee7a67146103865780630f212b1b146103b45780631182b875146103df575b600080fd5b34801561039257600080fd5b5061039b610d77565b6040805163ffffffff9092168252519081900360200190f35b3480156103c057600080fd5b506103c9610d7c565b6040805160ff9092168252519081900360200190f35b3480156103eb57600080fd5b506104646004803603604081101561040257600080fd5b60ff8235169190810190604081016020820135600160201b81111561042657600080fd5b82018360208201111561043857600080fd5b803590602001918460018302840111600160201b8311171561045957600080fd5b509092509050610d81565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049e578181015183820152602001610486565b50505050905090810190601f1680156104cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e557600080fd5b506103c9610e9b565b3480156104fa57600080fd5b506103c9610ea0565b6105386004803603604081101561051957600080fd5b5080356001600160a01b031690602001356001600160401b0316610ea5565b604080519115158252519081900360200190f35b34801561055857600080fd5b506105386004803603602081101561056f57600080fd5b50356001600160a01b03166113f1565b34801561058b57600080fd5b50610538600480360360208110156105a257600080fd5b50356001600160a01b0316611406565b3480156105be57600080fd5b506103c961141b565b3480156105d357600080fd5b506105dc611420565b604080516001600160a01b039092168252519081900360200190f35b34801561060457600080fd5b506106a96004803603602081101561061b57600080fd5b810190602081018135600160201b81111561063557600080fd5b82018360208201111561064757600080fd5b803590602001918460018302840111600160201b8311171561066857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611426945050505050565b60408051918252519081900360200190f35b3480156106c757600080fd5b506106d0611584565b6040805161ffff9092168252519081900360200190f35b3480156106f357600080fd5b506103c9611589565b34801561070857600080fd5b506103c961158e565b34801561071d57600080fd5b506105dc611593565b34801561073257600080fd5b506106a9611599565b34801561074757600080fd5b506103c96115a2565b6105386004803603604081101561076657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561079057600080fd5b8201836020820111156107a257600080fd5b803590602001918460018302840111600160201b831117156107c357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506115a7945050505050565b34801561081057600080fd5b506105dc611e7d565b6105386004803603602081101561082f57600080fd5b810190602081018135600160201b81111561084957600080fd5b82018360208201111561085b57600080fd5b803590602001918460018302840111600160201b8311171561087c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e83945050505050565b3480156108c957600080fd5b506105dc6122cf565b610538600480360360408110156108e857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561091257600080fd5b82018360208201111561092457600080fd5b803590602001918460018302840111600160201b8311171561094557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122d5945050505050565b34801561099257600080fd5b506103c96127db565b3480156109a757600080fd5b506106a96127e0565b3480156109bc57600080fd5b50610a35600480360360408110156109d357600080fd5b60ff8235169190810190604081016020820135600160201b8111156109f757600080fd5b820183602082011115610a0957600080fd5b803590602001918460018302840111600160201b83111715610a2a57600080fd5b5090925090506127e6565b005b61053860048036036040811015610a4d57600080fd5b5080356001600160a01b031690602001356001600160401b0316612935565b348015610a7857600080fd5b506103c961332c565b348015610a8d57600080fd5b506103c9613331565b348015610aa257600080fd5b506106a9613336565b348015610ab757600080fd5b506105dc613342565b348015610acc57600080fd5b506105dc613348565b348015610ae157600080fd5b5061053861334e565b348015610af657600080fd5b5061039b613357565b348015610b0b57600080fd5b50610a3560048036036040811015610b2257600080fd5b810190602081018135600160201b811115610b3c57600080fd5b820183602082011115610b4e57600080fd5b803590602001918460018302840111600160201b83111715610b6f57600080fd5b919390929091602081019035600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b50909250905061335c565b348015610bd657600080fd5b506105dc613631565b348015610beb57600080fd5b50610a3560048036036040811015610c0257600080fd5b60ff8235169190810190604081016020820135600160201b811115610c2657600080fd5b820183602082011115610c3857600080fd5b803590602001918460018302840111600160201b83111715610c5957600080fd5b509092509050613637565b348015610c7057600080fd5b50610c8e60048036036020811015610c8757600080fd5b503561370d565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a08301526001600160401b0390921660c082015290519081900360e00190f35b348015610cf057600080fd5b506106a9613764565b348015610d0557600080fd5b506105dc613769565b348015610d1a57600080fd5b506106a961376f565b348015610d2f57600080fd5b506105dc613775565b348015610d4457600080fd5b506106a961377b565b348015610d5957600080fd5b506105dc613781565b348015610d6e57600080fd5b506103c9613357565b606481565b600681565b60603361200014610dc35760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff841660011415610e1557610e0e83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061378792505050565b9050610e94565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605848484604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1506040805160008152602081019091525b9392505050565b600481565b600181565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b158015610ef257600080fd5b505afa158015610f06573d6000803e3d6000fd5b505050506040513d6020811015610f1c57600080fd5b5051905080610f5e576040805162461bcd60e51b81526020600482015260096024820152681b9bdd08189bdd5b9960ba1b604482015290519081900360640190fd5b6001600160a01b03841660009081526003602052604090205460ff16610fc1576040805162461bcd60e51b81526020600482015260136024820152723737ba103137bab73210313c9036b4b93937b960691b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190506402540be4003406158015611053575060055461104f908263ffffffff613a1716565b3410155b61108e5760405162461bcd60e51b8152600401808060200182810382526046815260200180615b156046913960600191505060405180910390fd5b42607801846001600160401b0316101580156110b85750426201518001846001600160401b031611155b6110f35760405162461bcd60e51b8152600401808060200182810382526038815260200180615a126038913960400191505060405180910390fd5b6000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561112e57600080fd5b505afa158015611142573d6000803e3d6000fd5b505050506040513d602081101561115857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0389169163313ce567916004808301926020929190829003018186803b1580156111a057600080fd5b505afa1580156111b4573d6000803e3d6000fd5b505050506040513d60208110156111ca57600080fd5b50519050677ce66c50e28400006111e48360ff8416613a71565b1115611230576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b600554611004906108fc9061124c90349063ffffffff613b0016565b6040518115909202916000818181858888f19350505050158015611274573d6000803e3d6000fd5b5061127d615869565b6040518060c00160405280336001600160a01b03168152602001896001600160a01b031681526020018681526020018481526020016112cc6402540be400600554613b4290919063ffffffff16565b81526001600160401b038916602090910152905061200063f7a251d760056112f384613b84565b61131d6402540be40061131160055434613b0090919063ffffffff16565b9063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561137b578181015183820152602001611363565b50505050905090810190601f1680156113a85780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156113c957600080fd5b505af11580156113dd573d6000803e3d6000fd5b505050506001955050505050505b92915050565b60036020526000908152604090205460ff1681565b60026020526000908152604090205460ff1681565b600381565b61100181565b602081015160009061143661589e565b50600081815260016020818152604092839020835160e081018552815460ff9081168252938201549281019290925260028101546001600160a01b031693820184905260038101546060830152600481015460808301526005015491821660a08201526101009091046001600160401b031660c0820152906114bd5760009250505061157f565b600081604001516001600160a01b03166370a082316110046040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561151b57600080fd5b505afa15801561152f573d6000803e3d6000fd5b505050506040513d602081101561154557600080fd5b5051608083015160608401519192506000916115669163ffffffff613b0016565b9050611578818363ffffffff613b0016565b9450505050505b919050565b606081565b600581565b600881565b61200081565b6402540be40081565b600281565b6001600160a01b03821660009081526002602052604081205460ff16156115ff5760405162461bcd60e51b815260040180806020018281038252602b815260200180615bb8602b913960400191505060405180910390fd5b600061160a83613cb9565b905061161461589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526116d9576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b60006116f682608001518360600151613b0090919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b03161461174c5760405162461bcd60e51b8152600401808060200182810382526045815260200180615a816045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561178f57600080fd5b505afa1580156117a3573d6000803e3d6000fd5b505050506040513d60208110156117b957600080fd5b50516001600160a01b0316146118005760405162461bcd60e51b815260040180806020018281038252602e8152602001806159e4602e913960400191505060405180910390fd5b604080516370a0823160e01b8152611004600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b15801561184c57600080fd5b505afa158015611860573d6000803e3d6000fd5b505050506040513d602081101561187657600080fd5b505160408051636eb1769f60e11b8152336004820152306024820152905191925083916119079184916001600160a01b038c169163dd62ed3e916044808301926020929190829003018186803b1580156118cf57600080fd5b505afa1580156118e3573d6000803e3d6000fd5b505050506040513d60208110156118f957600080fd5b50519063ffffffff613a1716565b101561195a576040805162461bcd60e51b815260206004820152601760248201527f616c6c6f77616e6365206973206e6f7420656e6f756768000000000000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561199c57600080fd5b505afa1580156119b0573d6000803e3d6000fd5b505050506040513d60208110156119c657600080fd5b505190508082108015906119df57506402540be4008206155b611a1a5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b6000611a26868b613cc0565b905063ffffffff8116611c25576001600160a01b038a166323b872dd33611004611a56898963ffffffff613b0016565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015611abe57600080fd5b505af1158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b5050602086015160408088015160a089015182516323bfccdb60e21b815260048101949094526001600160a01b03909116602484015260ff1660448301525161100491638eff336c91606480830192600092919082900301818387803b158015611b5157600080fd5b505af1158015611b65573d6000803e3d6000fd5b50505050896001600160a01b03167f78e7dd9aefcdbf795c4936a66f7dc6d41bb56637b54f561a6bf7829dca3348a88a8860600151886040518080602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b83811015611be4578181015183820152602001611bcc565b50505050905090810190601f168015611c115780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2611cdd565b896001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a1078a8360405180806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611ca1578181015183820152602001611c89565b50505050905090810190601f168015611cce5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25b60008781526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff19169055611d376158da565b5060408051808201825263ffffffff831681526020810189905290516110049085156108fc029086906000818181858888f19350505050158015611d7f573d6000803e3d6000fd5b5061200063f7a251d76001611d938461411a565b611da8886402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611e06578181015183820152602001611dee565b50505050905090810190601f168015611e335780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611e5457600080fd5b505af1158015611e68573d6000803e3d6000fd5b5060019e9d5050505050505050505050505050565b61100581565b600080611e8f83613cb9565b9050611e9961589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c0830152611f5e576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c001516001600160401b031610611fbf576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561200157600080fd5b505afa158015612015573d6000803e3d6000fd5b505050506040513d602081101561202b57600080fd5b5051905080821080159061204457506402540be4008206155b61207f5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556120d96158da565b50604080518082018252600181526020810186905290516110049084156108fc029085906000818181858888f1935050505015801561211c573d6000803e3d6000fd5b5061200063f7a251d760016121308461411a565b612145876402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156121a357818101518382015260200161218b565b50505050905090810190601f1680156121d05780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156121f157600080fd5b505af1158015612205573d6000803e3d6000fd5b5050505083604001516001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600160405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561228757818101518382015260200161226f565b50505050905090810190601f1680156122b45780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25060019695505050505050565b61100881565b6000806122e183613cb9565b90506122eb61589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526123b0576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b0316146124045760405162461bcd60e51b8152600401808060200182810382526045815260200180615a816045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561244757600080fd5b505afa15801561245b573d6000803e3d6000fd5b505050506040513d602081101561247157600080fd5b50516001600160a01b0316146124ce576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703230206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561251057600080fd5b505afa158015612524573d6000803e3d6000fd5b505050506040513d602081101561253a57600080fd5b5051905080821080159061255357506402540be4008206155b61258e5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556125e86158da565b50604080518082018252600781526020810186905290516110049084156108fc029085906000818181858888f1935050505015801561262b573d6000803e3d6000fd5b5061200063f7a251d7600161263f8461411a565b612654876402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156126b257818101518382015260200161269a565b50505050905090810190601f1680156126df5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561270057600080fd5b505af1158015612714573d6000803e3d6000fd5b50505050876001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600760405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561279257818101518382015260200161277a565b50505050905090810190601f1680156127bf5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2506001979650505050505050565b600b81565b60045481565b33612000146128265760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff8316600414156128765761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061419092505050565b612930565b60ff8316600514156128c15761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061443d92505050565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051146129f0576040805162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e48189bdd5b99609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526002602052604090205460ff1615612a4f576040805162461bcd60e51b815260206004820152600e60248201526d6d6972726f722070656e64696e6760901b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8c57600080fd5b505afa158015612aa0573d6000803e3d6000fd5b505050506040513d6020811015612ab657600080fd5b505190506402540be4003406158015612ae15750600454612add908263ffffffff613a1716565b3410155b612b1c5760405162461bcd60e51b815260040180806020018281038252604d815260200180615997604d913960600191505060405180910390fd5b42607801836001600160401b031610158015612b465750426201518001836001600160401b031611155b612b815760405162461bcd60e51b8152600401808060200182810382526038815260200180615a126038913960400191505060405180910390fd5b6000846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bbc57600080fd5b505afa158015612bd0573d6000803e3d6000fd5b505050506040513d6020811015612be657600080fd5b5051604080516318160ddd60e01b815290519192506000916001600160a01b038816916318160ddd916004808301926020929190829003018186803b158015612c2e57600080fd5b505afa158015612c42573d6000803e3d6000fd5b505050506040513d6020811015612c5857600080fd5b50519050677ce66c50e2840000612c728260ff8516613a71565b1115612cbe576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b6060866001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d3657600080fd5b8101908080516040519392919084600160201b821115612d5557600080fd5b908301906020820185811115612d6a57600080fd5b8251600160201b811182820188101715612d8357600080fd5b82525081516020918201929091019080838360005b83811015612db0578181015183820152602001612d98565b50505050905090810190601f168015612ddd5780820380516001836020036101000a031916815260200191505b50604052505050905060608190506001815110158015612dff57506020815111155b612e50576040805162461bcd60e51b815260206004820152601d60248201527f6e616d65206c656e677468206d75737420626520696e205b312c33325d000000604482015290519081900360640190fd5b6060886001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015612e8b57600080fd5b505afa158015612e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612ec857600080fd5b8101908080516040519392919084600160201b821115612ee757600080fd5b908301906020820185811115612efc57600080fd5b8251600160201b811182820188101715612f1557600080fd5b82525081516020918201929091019080838360005b83811015612f42578181015183820152602001612f2a565b50505050905090810190601f168015612f6f5780820380516001836020036101000a031916815260200191505b5060405250508151919250829160021180159150612f8f57508051600810155b612fe0576040805162461bcd60e51b815260206004820152601e60248201527f73796d626f6c206c656e677468206d75737420626520696e205b322c385d0000604482015290519081900360640190fd5b60005b81518160ff16101561313457604160f81b828260ff168151811061300357fe5b01602001516001600160f81b031916108015906130415750602d60f91b828260ff168151811061302f57fe5b01602001516001600160f81b03191611155b806130995750606160f81b828260ff168151811061305b57fe5b01602001516001600160f81b031916108015906130995750603d60f91b828260ff168151811061308757fe5b01602001516001600160f81b03191611155b806130f15750600360fc1b828260ff16815181106130b357fe5b01602001516001600160f81b031916108015906130f15750603960f81b828260ff16815181106130df57fe5b01602001516001600160f81b03191611155b61312c5760405162461bcd60e51b815260040180806020018281038252602e815260200180615ac6602e913960400191505060405180910390fd5b600101612fe3565b50600454611004906108fc9061315190349063ffffffff613b0016565b6040518115909202916000818181858888f19350505050158015613179573d6000803e3d6000fd5b506001600160a01b038a166000908152600260209081526040909120805460ff1916600117905584810151908301516131b06158f1565b604051806101000160405280336001600160a01b031681526020018e6001600160a01b031681526020018481526020018381526020018981526020018a60ff16815260200161320f6402540be400600454613b4290919063ffffffff16565b81526001600160401b038e16602090910152905061200063f7a251d7600461323684614608565b6132546402540be40061131160045434613b0090919063ffffffff16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156132b257818101518382015260200161329a565b50505050905090810190601f1680156132df5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561330057600080fd5b505af1158015613314573d6000803e3d6000fd5b5050505060019a505050505050505050505092915050565b600781565b600981565b677ce66c50e284000081565b61100781565b61100681565b60005460ff1681565b600081565b336110071461339c5760405162461bcd60e51b815260040180806020018281038252602e815260200180615b5b602e913960400191505060405180910390fd5b602081146133f1576040805162461bcd60e51b815260206004820152601860248201527f65787065637465642076616c7565206c656e6774682033320000000000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f880181900481028201810190925286815293945060609392508691508590819084018382808284376000920191909152505050506020830151909150686d6972726f7246656560b81b8114156134e65760208201516402540be4008106156134de576040805162461bcd60e51b815260206004820152601a60248201527f6d6972726f72466565206d757374206265204e202a2031653130000000000000604482015290519081900360640190fd5b60045561359c565b6673796e6346656560c81b81141561355f5760208201516402540be400810615613557576040805162461bcd60e51b815260206004820152601860248201527f73796e63466565206d757374206265204e202a20316531300000000000000000604482015290519081900360640190fd5b60055561359c565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61100281565b33612000146136775760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff8316600414156136c25761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061477a92505050565b60ff8316600514156128c15761287182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506148b992505050565b600160208190526000918252604090912080549181015460028201546003830154600484015460059094015460ff9586169593946001600160a01b039093169391929181169061010090046001600160401b031687565b604d81565b61100381565b60055481565b61100081565b61271081565b61100481565b606061379161589e565b600061379c846149b3565b91509150806137f2576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff166138a5576020828101805160009081526001928390526040908190208551815460ff1990811660ff928316178355935194820194909455908501516002820180546001600160a01b0319166001600160a01b03909216919091179055606085015160038201556080850151600482015560a08501516005909101805460c08701519316919093161768ffffffffffffffff0019166101006001600160401b03909216919091021790556139fc565b815160ff16600114156139af5760006110046001600160a01b03166359b9278984602001516040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156138fe57600080fd5b505afa158015613912573d6000803e3d6000fd5b505050506040513d602081101561392857600080fd5b505190506001600160a01b038116156139a95760208301516040805163b99328c560e01b815260048101929092526001600160a01b0383166024830152516110049163b99328c591604480830192600092919082900301818387803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b506139fc565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b600082820183811015610e94576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006008821115613ae957604d60071983011115613acb576040805162461bcd60e51b8152602060048201526012602482015271746f6f206c6172676520646563696d616c7360701b604482015290519081900360640190fd5b613ae2836007198401600a0a63ffffffff613b4216565b90506113eb565b610e94836008849003600a0a63ffffffff614b0416565b6000610e9483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b5d565b6000610e9483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bf4565b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613b9f5750508351909150613bca906001600160a01b0316614c59565b81600081518110613bd757fe5b6020026020010181905250613bf883602001516001600160a01b0316614c59565b81600181518110613c0557fe5b6020026020010181905250613c20836040015160001c614c7c565b81600281518110613c2d57fe5b6020026020010181905250613c458360600151614c7c565b81600381518110613c5257fe5b6020026020010181905250613c6a8360800151614c7c565b81600481518110613c7757fe5b6020026020010181905250613c988360a001516001600160401b0316614c7c565b81600581518110613ca557fe5b6020026020010181905250610e9481614c8f565b6020015190565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cfc57600080fd5b505afa158015613d10573d6000803e3d6000fd5b505050506040513d6020811015613d2657600080fd5b5051604080516395d89b4160e01b8152905160ff90921692506060916001600160a01b038616916395d89b41916004808301926000929190829003018186803b158015613d7257600080fd5b505afa158015613d86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613daf57600080fd5b8101908080516040519392919084600160201b821115613dce57600080fd5b908301906020820185811115613de357600080fd5b8251600160201b811182820188101715613dfc57600080fd5b82525081516020918201929091019080838360005b83811015613e29578181015183820152602001613e11565b50505050905090810190601f168015613e565780820380516001836020036101000a031916815260200191505b5060408181526370a0823160e01b82526110046004830152519495506000946001600160a01b038a1694506370a08231935060248083019350602092829003018186803b158015613ea657600080fd5b505afa158015613eba573d6000803e3d6000fd5b505050506040513d6020811015613ed057600080fd5b505160808701516060880151919250600091613ef19163ffffffff613b0016565b9050428760c001516001600160401b03161015613f165750600193506113eb92505050565b613f24838860200151614d19565b613f365750600293506113eb92505050565b80821115613f4c5750600393506113eb92505050565b866060015187604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f8e57600080fd5b505afa158015613fa2573d6000803e3d6000fd5b505050506040513d6020811015613fb857600080fd5b505114613fcd5750600493506113eb92505050565b8660a0015160ff168414613fe95750600593506113eb92505050565b602080880151604080516359b9278960e01b8152600481019290925251600092611004926359b927899260248083019392829003018186803b15801561402e57600080fd5b505afa158015614042573d6000803e3d6000fd5b505050506040513d602081101561405857600080fd5b50516001600160a01b03161415806140fa57506000801b6110046001600160a01b031663bd46646189604001516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156140cb57600080fd5b505afa1580156140df573d6000803e3d6000fd5b505050506040513d60208110156140f557600080fd5b505114155b1561410d5750600693506113eb92505050565b5060009695505050505050565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081614133575050835190915061415b9063ffffffff16614c7c565b8160008151811061416857fe5b6020026020010181905250614183836020015160001c614c7c565b81600181518110613ca557fe5b614198615869565b60006141a383614e01565b91509150806141f0576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b03166000908152600290915260409020805460ff1916905560a082015160ff166143515760808201516040516110049180156108fc02916000818181858888f19350505050158015614253573d6000803e3d6000fd5b506110046001600160a01b0316638eff336c8360600151846020015185604001516040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b031681526020018260ff1681526020019350505050600060405180830381600087803b1580156142cd57600080fd5b505af11580156142e1573d6000803e3d6000fd5b50505050602082810180516001600160a01b03908116600090815260038452604090819020805460ff1916600117905591516060860151835190815292519116927f41787d7db08fc5907641ee8343379f28215727eb123d4b462099afab4300b036928290030190a2505061443a565b815160808301516040516000926001600160a01b0316916127109184818181858888f193505050503d80600081146143a5576040519150601f19603f3d011682016040523d82523d6000602084013e6143aa565b606091505b50509050806143e75760808301516040516110029180156108fc02916000818181858888f193505050501580156143e5573d6000803e3d6000fd5b505b82602001516001600160a01b03167fefe400ad0042ebf81a245de9ae669616105e0ca9fc946352c085da0c2bc524e58460a00151604051808260ff1660ff16815260200191505060405180910390a25050505b50565b614445615935565b600061445083614f0e565b915091508061449d576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b606082015160ff1661451d5760408083015190516110049180156108fc02916000818181858888f193505050501580156144db573d6000803e3d6000fd5b5081602001516001600160a01b03167fbb7d3a9a559080d8281b0e4fb39dacbe2fdcafd5ef765e9a6ed871c9167dc60f60405160405180910390a2505061443a565b81602001516001600160a01b03167ff1e25fa536da84053644fd788b1d6a27ea6edd1f3af80c7d36ca253c4c82c9c38360600151604051808260ff1660ff16815260200191505060405180910390a2815160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d80600081146145c0576040519150601f19603f3d011682016040523d82523d6000602084013e6145c5565b606091505b50509050806146025760408084015190516110029180156108fc02916000818181858888f19350505050158015614600573d6000803e3d6000fd5b505b50505050565b6040805160088082526101208201909252606091829190816020015b6060815260200190600190039081614624575050835190915061464f906001600160a01b0316614c59565b8160008151811061465c57fe5b602002602001018190525061467d83602001516001600160a01b0316614c59565b8160018151811061468a57fe5b60200260200101819052506146a5836040015160001c614c7c565b816002815181106146b257fe5b60200260200101819052506146cd836060015160001c614c7c565b816003815181106146da57fe5b60200260200101819052506146f28360800151614c7c565b816004815181106146ff57fe5b602002602001018190525061471a8360a0015160ff16614c7c565b8160058151811061472757fe5b602002602001018190525061473f8360c00151614c7c565b8160068151811061474c57fe5b602002602001018190525061476d8360e001516001600160401b0316614c7c565b81600781518110613ca557fe5b6147826158f1565b600061478d83614fda565b91509150806147da576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b039081166000908152600290925260408220805460ff19169055835160c085015191169061271090614824906402540be40063ffffffff614b0416565b6040516000818181858888f193505050503d8060008114614861576040519150601f19603f3d011682016040523d82523d6000602084013e614866565b606091505b50509050806146025760c0830151611002906108fc90614891906402540be40063ffffffff614b0416565b6040518115909202916000818181858888f19350505050158015614600573d6000803e3d6000fd5b6148c1615869565b60006148cc8361512b565b9150915080614919576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b815160808301516000916001600160a01b03169061271090614946906402540be40063ffffffff614b0416565b6040516000818181858888f193505050503d8060008114614983576040519150601f19603f3d011682016040523d82523d6000602084013e614988565b606091505b5050905080614602576080830151611002906108fc90614891906402540be40063ffffffff614b0416565b6149bb61589e565b60006149c561589e565b6149cd61595c565b6149de6149d98661523b565b615260565b90506000805b6149ed836152aa565b15614af75780614a1257614a08614a03846152cb565b615319565b60ff168452614aef565b8060011415614a3157614a27614a03846152cb565b6020850152614aef565b8060021415614a5e57614a4b614a46846152cb565b6153ce565b6001600160a01b03166040850152614aef565b8060031415614a7d57614a73614a03846152cb565b6060850152614aef565b8060041415614a9c57614a92614a03846152cb565b6080850152614aef565b8060051415614abe57614ab1614a03846152cb565b60ff1660a0850152614aef565b8060061415614aea57614ad3614a03846152cb565b6001600160401b031660c085015260019150614aef565b614af7565b6001016149e4565b5091935090915050915091565b600082614b13575060006113eb565b82820282848281614b2057fe5b0414610e945760405162461bcd60e51b8152600401808060200182810382526021815260200180615af46021913960400191505060405180910390fd5b60008184841115614bec5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614bb1578181015183820152602001614b99565b50505050905090810190601f168015614bde5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183614c435760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614bb1578181015183820152602001614b99565b506000838581614c4f57fe5b0495945050505050565b60408051600560a21b8318601482015260348101909152606090610e94816153e8565b60606113eb614c8a8361543e565b6153e8565b6060815160001415614cb0575060408051600081526020810190915261157f565b606082600081518110614cbf57fe5b602002602001015190506000600190505b8351811015614d0057614cf682858381518110614ce957fe5b6020026020010151615524565b9150600101614cd0565b50610e94614d13825160c060ff166155a1565b82615524565b8151600090839060081080614d2f575080516002115b15614d3e5760009150506113eb565b60408051602080825281830190925260609160208201818036833701905050905083602082015280825181518110614d7257fe5b6020910101516001600160f81b031916602d60f81b14614d97576000925050506113eb565b600160005b8351811015614df757828181518110614db157fe5b602001015160f81c60f81b6001600160f81b031916848281518110614dd257fe5b01602001516001600160f81b03191614614def5760009150614df7565b600101614d9c565b5095945050505050565b614e09615869565b6000614e13615869565b614e1b61595c565b614e276149d98661523b565b90506000805b614e36836152aa565b15614af75780614e5c57614e4c614a46846152cb565b6001600160a01b03168452614f06565b8060011415614e8457614e71614a46846152cb565b6001600160a01b03166020850152614f06565b8060021415614ea657614e99614a03846152cb565b60ff166040850152614f06565b8060031415614ec557614ebb614a03846152cb565b6060850152614f06565b8060041415614ee457614eda614a03846152cb565b6080850152614f06565b8060051415614aea57614ef9614a03846152cb565b60ff1660a0850152600191505b600101614e2d565b614f16615935565b6000614f20615935565b614f2861595c565b614f346149d98661523b565b90506000805b614f43836152aa565b15614af75780614f6957614f59614a46846152cb565b6001600160a01b03168452614fd2565b8060011415614f9157614f7e614a46846152cb565b6001600160a01b03166020850152614fd2565b8060021415614fb057614fa6614a03846152cb565b6040850152614fd2565b8060031415614aea57614fc5614a03846152cb565b60ff166060850152600191505b600101614f3a565b614fe26158f1565b6000614fec6158f1565b614ff461595c565b6150006149d98661523b565b90506000805b61500f836152aa565b15614af7578061503557615025614a46846152cb565b6001600160a01b03168452615123565b806001141561505d5761504a614a46846152cb565b6001600160a01b03166020850152615123565b806002141561507c57615072614a03846152cb565b6040850152615123565b806003141561509b57615091614a03846152cb565b6060850152615123565b80600414156150ba576150b0614a03846152cb565b6080850152615123565b80600514156150dc576150cf614a03846152cb565b60ff1660a0850152615123565b80600614156150fb576150f1614a03846152cb565b60c0850152615123565b8060071415614aea57615110614a03846152cb565b6001600160401b031660e0850152600191505b600101615006565b615133615869565b600061513d615869565b61514561595c565b6151516149d98661523b565b90506000805b615160836152aa565b15614af7578061518657615176614a46846152cb565b6001600160a01b03168452615233565b80600114156151ae5761519b614a46846152cb565b6001600160a01b03166020850152615233565b80600214156151cd576151c3614a03846152cb565b6040850152615233565b80600314156151ec576151e2614a03846152cb565b6060850152615233565b806004141561520b57615201614a03846152cb565b6080850152615233565b8060051415614aea57615220614a03846152cb565b6001600160401b031660a0850152600191505b600101615157565b61524361597c565b506040805180820190915281518152602082810190820152919050565b61526861595c565b61527182615699565b61527a57600080fd5b600061528983602001516156d3565b60208085015160408051808201909152868152920190820152915050919050565b60006152b461597c565b505080518051602091820151919092015191011190565b6152d361597c565b6152dc826152aa565b6152e557600080fd5b602082015160006152f582615736565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061532e57508151602110155b61533757600080fd5b600061534683602001516156d3565b905080836000015110156153a1576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613a0e57506020919091036101000a90049392505050565b80516000906015146153df57600080fd5b6113eb82615319565b60608151600114801561541a5750607f60f81b8260008151811061540857fe5b01602001516001600160f81b03191611155b1561542657508061157f565b6113eb6154388351608060ff166155a1565b83615524565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416615482575060186154a6565b6fffffffffffffffffffffffffffffffff1984166154a2575060106154a6565b5060005b60208110156154dc578181815181106154bb57fe5b01602001516001600160f81b031916156154d4576154dc565b6001016154a6565b60008160200390506060816040519080825280601f01601f191660200182016040528015615511576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b8183101561555557805183526020928301920161553d565b50855184518101855292509050808201602086015b8183101561558257805183526020928301920161556a565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106155f1576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161564b5782840160f81b8160008151811061562d57fe5b60200101906001600160f81b031916908160001a90535090506113eb565b60606156568561543e565b90508381510160370160f81b8260008151811061566f57fe5b60200101906001600160f81b031916908160001a9053506156908282615524565b95945050505050565b80516000906156aa5750600061157f565b6020820151805160001a9060c08210156156c95760009250505061157f565b5060019392505050565b8051600090811a60808110156156ed57600091505061157f565b60b8811080615708575060c08110801590615708575060f881105b1561571757600191505061157f565b60c081101561572b5760b51901905061157f565b60f51901905061157f565b80516000908190811a60808110156157515760019150615862565b60b881101561576657607e1981019150615862565b60c08110156157e057600060b78203600186019550806020036101000a8651049150600181018201935050808310156157da576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50615862565b60f88110156157f55760be1981019150615862565b600060f78203600186019550806020036101000a865104915060018101820193505080831015615860576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806040016040528061596f61597c565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6d73672e76616c7565206d757374206265204e202a203165313020616e642067726561746572207468616e2073756d206f66206d696e6952656c617946656520616e64206d6972726f724665656f6e6c79206265703230206f776e65722063616e20617070726f766520746869732062696e64207265717565737465787069726554696d65206d7573742062652074776f206d696e75746573206c6174657220616e64206f6e6520646179206561726c69657272656c6179466565206d757374206265204e202a203165313020616e642067726561746572207468616e206d696e6952656c6179466565636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e64207265717565737473796d626f6c2073686f756c64206f6e6c7920636f6e7461696e20616c70686162657420616e64206e756d626572536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776d73672e76616c7565206d757374206265204e202a203165313020616e64206e6f206c6573732073756d206f66206d696e6952656c617946656520616e642073796e63466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e747261637474686520626570323020746f6b656e20697320696e206d6972726f722070656e64696e6720737461747573a2646970667358221220e74347a816e56fa846d45b718bd95e0c54bf4a086c7a4c2cc469ee1575a8f9b464736f6c63430006040033" + "code": "0x6080604052600436106103815760003560e01c80637d078e13116101d1578063b795031711610102578063d9e6dae9116100a0578063fa9e91591161006f578063fa9e915914610d38578063fc3e5908146105b2578063fd6a687914610d4d578063fe3a2af514610d6257610381565b8063d9e6dae9146106fc578063dc927faf14610cf9578063e605bca014610d0e578063f9a2bbc714610d2357610381565b8063c8509d81116100dc578063c8509d8114610bdf578063c8e704a4146105b2578063d117a11014610c64578063d7109ce614610ce457610381565b8063b79503171461073b578063bd32d3f9146104d9578063c81b166214610bca57610381565b80639a854bbd1161016f578063a78abc1611610149578063a78abc1614610ad5578063ab51bb9614610aea578063ab67a4851461073b578063ac43175114610aff57610381565b80639a854bbd14610a965780639dc0926214610aab578063a1a11bf514610ac057610381565b8063859180fb116101ab578063859180fb146106e757806394553a4e14610a3757806395b9ad2614610a6c57806396713da914610a8157610381565b80637d078e13146104ee5780637ec816dd1461099b578063831d65d1146109b057610381565b8063493279b1116102b657806366dea52a1161025457806372c4e0861161022357806372c4e0861461081957806375d47a0a146108bd57806377d9dae8146108d25780637942fd051461098657610381565b806366dea52a1461073b5780636b3f1307146107505780636e47b4821461080457806370fd5bad1461073b57610381565b806351e806721161029057806351e80672146107115780635d499b1b146107265780635f558f861461073b57806361368475146106fc57610381565b8063493279b1146106bb5780634bc81c00146106e75780634bf6c882146106fc57610381565b80632e02d77611610323578063401809f9116102fd578063401809f9146105b257806343756e5c146105c7578063445fcefe146105f8578063487c88ac146104ee57610381565b80632e02d7761461054c57806337e6ecda1461057f5780633dffc387146104ee57610381565b80631f91600b1161035f5780631f91600b146104d957806323996b53146104ee57806325c751b7146105035780632d89ac32146104ee57610381565b80630bee7a67146103865780630f212b1b146103b45780631182b875146103df575b600080fd5b34801561039257600080fd5b5061039b610d77565b6040805163ffffffff9092168252519081900360200190f35b3480156103c057600080fd5b506103c9610d7c565b6040805160ff9092168252519081900360200190f35b3480156103eb57600080fd5b506104646004803603604081101561040257600080fd5b60ff8235169190810190604081016020820135600160201b81111561042657600080fd5b82018360208201111561043857600080fd5b803590602001918460018302840111600160201b8311171561045957600080fd5b509092509050610d81565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049e578181015183820152602001610486565b50505050905090810190601f1680156104cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e557600080fd5b506103c9610e9b565b3480156104fa57600080fd5b506103c9610ea0565b6105386004803603604081101561051957600080fd5b5080356001600160a01b031690602001356001600160401b0316610ea5565b604080519115158252519081900360200190f35b34801561055857600080fd5b506105386004803603602081101561056f57600080fd5b50356001600160a01b03166113f1565b34801561058b57600080fd5b50610538600480360360208110156105a257600080fd5b50356001600160a01b0316611406565b3480156105be57600080fd5b506103c961141b565b3480156105d357600080fd5b506105dc611420565b604080516001600160a01b039092168252519081900360200190f35b34801561060457600080fd5b506106a96004803603602081101561061b57600080fd5b810190602081018135600160201b81111561063557600080fd5b82018360208201111561064757600080fd5b803590602001918460018302840111600160201b8311171561066857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611426945050505050565b60408051918252519081900360200190f35b3480156106c757600080fd5b506106d0611584565b6040805161ffff9092168252519081900360200190f35b3480156106f357600080fd5b506103c9611589565b34801561070857600080fd5b506103c961158e565b34801561071d57600080fd5b506105dc611593565b34801561073257600080fd5b506106a9611599565b34801561074757600080fd5b506103c96115a2565b6105386004803603604081101561076657600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561079057600080fd5b8201836020820111156107a257600080fd5b803590602001918460018302840111600160201b831117156107c357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506115a7945050505050565b34801561081057600080fd5b506105dc611e7d565b6105386004803603602081101561082f57600080fd5b810190602081018135600160201b81111561084957600080fd5b82018360208201111561085b57600080fd5b803590602001918460018302840111600160201b8311171561087c57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e83945050505050565b3480156108c957600080fd5b506105dc6122cf565b610538600480360360408110156108e857600080fd5b6001600160a01b038235169190810190604081016020820135600160201b81111561091257600080fd5b82018360208201111561092457600080fd5b803590602001918460018302840111600160201b8311171561094557600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506122d5945050505050565b34801561099257600080fd5b506103c96127db565b3480156109a757600080fd5b506106a96127e0565b3480156109bc57600080fd5b50610a35600480360360408110156109d357600080fd5b60ff8235169190810190604081016020820135600160201b8111156109f757600080fd5b820183602082011115610a0957600080fd5b803590602001918460018302840111600160201b83111715610a2a57600080fd5b5090925090506127e6565b005b61053860048036036040811015610a4d57600080fd5b5080356001600160a01b031690602001356001600160401b0316612935565b348015610a7857600080fd5b506103c961332c565b348015610a8d57600080fd5b506103c9613331565b348015610aa257600080fd5b506106a9613336565b348015610ab757600080fd5b506105dc613342565b348015610acc57600080fd5b506105dc613348565b348015610ae157600080fd5b5061053861334e565b348015610af657600080fd5b5061039b613357565b348015610b0b57600080fd5b50610a3560048036036040811015610b2257600080fd5b810190602081018135600160201b811115610b3c57600080fd5b820183602082011115610b4e57600080fd5b803590602001918460018302840111600160201b83111715610b6f57600080fd5b919390929091602081019035600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b50909250905061335c565b348015610bd657600080fd5b506105dc613631565b348015610beb57600080fd5b50610a3560048036036040811015610c0257600080fd5b60ff8235169190810190604081016020820135600160201b811115610c2657600080fd5b820183602082011115610c3857600080fd5b803590602001918460018302840111600160201b83111715610c5957600080fd5b509092509050613637565b348015610c7057600080fd5b50610c8e60048036036020811015610c8757600080fd5b503561370d565b6040805160ff988916815260208101979097526001600160a01b03909516868601526060860193909352608085019190915290931660a08301526001600160401b0390921660c082015290519081900360e00190f35b348015610cf057600080fd5b506106a9613764565b348015610d0557600080fd5b506105dc613769565b348015610d1a57600080fd5b506106a961376f565b348015610d2f57600080fd5b506105dc613775565b348015610d4457600080fd5b506106a961377b565b348015610d5957600080fd5b506105dc613781565b348015610d6e57600080fd5b506103c9613357565b606481565b600681565b60603361200014610dc35760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff841660011415610e1557610e0e83838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061378792505050565b9050610e94565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605848484604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a1506040805160008152602081019091525b9392505050565b600481565b600181565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b158015610ef257600080fd5b505afa158015610f06573d6000803e3d6000fd5b505050506040513d6020811015610f1c57600080fd5b5051905080610f5e576040805162461bcd60e51b81526020600482015260096024820152681b9bdd08189bdd5b9960ba1b604482015290519081900360640190fd5b6001600160a01b03841660009081526003602052604090205460ff16610fc1576040805162461bcd60e51b81526020600482015260136024820152723737ba103137bab73210313c9036b4b93937b960691b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190506402540be4003406158015611053575060055461104f908263ffffffff613a1716565b3410155b61108e5760405162461bcd60e51b8152600401808060200182810382526046815260200180615b156046913960600191505060405180910390fd5b42607801846001600160401b0316101580156110b85750426201518001846001600160401b031611155b6110f35760405162461bcd60e51b8152600401808060200182810382526038815260200180615a126038913960400191505060405180910390fd5b6000856001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561112e57600080fd5b505afa158015611142573d6000803e3d6000fd5b505050506040513d602081101561115857600080fd5b50516040805163313ce56760e01b815290519192506000916001600160a01b0389169163313ce567916004808301926020929190829003018186803b1580156111a057600080fd5b505afa1580156111b4573d6000803e3d6000fd5b505050506040513d60208110156111ca57600080fd5b50519050677ce66c50e28400006111e48360ff8416613a71565b1115611230576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b600554611004906108fc9061124c90349063ffffffff613b0016565b6040518115909202916000818181858888f19350505050158015611274573d6000803e3d6000fd5b5061127d615869565b6040518060c00160405280336001600160a01b03168152602001896001600160a01b031681526020018681526020018481526020016112cc6402540be400600554613b4290919063ffffffff16565b81526001600160401b038916602090910152905061200063f7a251d760056112f384613b84565b61131d6402540be40061131160055434613b0090919063ffffffff16565b9063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b8381101561137b578181015183820152602001611363565b50505050905090810190601f1680156113a85780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156113c957600080fd5b505af11580156113dd573d6000803e3d6000fd5b505050506001955050505050505b92915050565b60036020526000908152604090205460ff1681565b60026020526000908152604090205460ff1681565b600381565b61100181565b602081015160009061143661589e565b50600081815260016020818152604092839020835160e081018552815460ff9081168252938201549281019290925260028101546001600160a01b031693820184905260038101546060830152600481015460808301526005015491821660a08201526101009091046001600160401b031660c0820152906114bd5760009250505061157f565b600081604001516001600160a01b03166370a082316110046040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561151b57600080fd5b505afa15801561152f573d6000803e3d6000fd5b505050506040513d602081101561154557600080fd5b5051608083015160608401519192506000916115669163ffffffff613b0016565b9050611578818363ffffffff613b0016565b9450505050505b919050565b603881565b600581565b600881565b61200081565b6402540be40081565b600281565b6001600160a01b03821660009081526002602052604081205460ff16156115ff5760405162461bcd60e51b815260040180806020018281038252602b815260200180615bb8602b913960400191505060405180910390fd5b600061160a83613cb9565b905061161461589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526116d9576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b60006116f682608001518360600151613b0090919063ffffffff16565b905081604001516001600160a01b0316866001600160a01b03161461174c5760405162461bcd60e51b8152600401808060200182810382526045815260200180615a816045913960600191505060405180910390fd5b336001600160a01b0316866001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561178f57600080fd5b505afa1580156117a3573d6000803e3d6000fd5b505050506040513d60208110156117b957600080fd5b50516001600160a01b0316146118005760405162461bcd60e51b815260040180806020018281038252602e8152602001806159e4602e913960400191505060405180910390fd5b604080516370a0823160e01b8152611004600482015290516000916001600160a01b038916916370a0823191602480820192602092909190829003018186803b15801561184c57600080fd5b505afa158015611860573d6000803e3d6000fd5b505050506040513d602081101561187657600080fd5b505160408051636eb1769f60e11b8152336004820152306024820152905191925083916119079184916001600160a01b038c169163dd62ed3e916044808301926020929190829003018186803b1580156118cf57600080fd5b505afa1580156118e3573d6000803e3d6000fd5b505050506040513d60208110156118f957600080fd5b50519063ffffffff613a1716565b101561195a576040805162461bcd60e51b815260206004820152601760248201527f616c6c6f77616e6365206973206e6f7420656e6f756768000000000000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561199c57600080fd5b505afa1580156119b0573d6000803e3d6000fd5b505050506040513d60208110156119c657600080fd5b505190508082108015906119df57506402540be4008206155b611a1a5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b6000611a26868b613cc0565b905063ffffffff8116611c25576001600160a01b038a166323b872dd33611004611a56898963ffffffff613b0016565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015611abe57600080fd5b505af1158015611ad2573d6000803e3d6000fd5b505050506040513d6020811015611ae857600080fd5b5050602086015160408088015160a089015182516323bfccdb60e21b815260048101949094526001600160a01b03909116602484015260ff1660448301525161100491638eff336c91606480830192600092919082900301818387803b158015611b5157600080fd5b505af1158015611b65573d6000803e3d6000fd5b50505050896001600160a01b03167f78e7dd9aefcdbf795c4936a66f7dc6d41bb56637b54f561a6bf7829dca3348a88a8860600151886040518080602001848152602001838152602001828103825285818151815260200191508051906020019080838360005b83811015611be4578181015183820152602001611bcc565b50505050905090810190601f168015611c115780820380516001836020036101000a031916815260200191505b5094505050505060405180910390a2611cdd565b896001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a1078a8360405180806020018363ffffffff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b83811015611ca1578181015183820152602001611c89565b50505050905090810190601f168015611cce5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25b60008781526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff19169055611d376158da565b5060408051808201825263ffffffff831681526020810189905290516110049085156108fc029086906000818181858888f19350505050158015611d7f573d6000803e3d6000fd5b5061200063f7a251d76001611d938461411a565b611da8886402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b83811015611e06578181015183820152602001611dee565b50505050905090810190601f168015611e335780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b158015611e5457600080fd5b505af1158015611e68573d6000803e3d6000fd5b5060019e9d5050505050505050505050505050565b61100581565b600080611e8f83613cb9565b9050611e9961589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c0830152611f5e576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b428160c001516001600160401b031610611fbf576040805162461bcd60e51b815260206004820152601b60248201527f62696e642072657175657374206973206e6f7420657870697265640000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561200157600080fd5b505afa158015612015573d6000803e3d6000fd5b505050506040513d602081101561202b57600080fd5b5051905080821080159061204457506402540be4008206155b61207f5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556120d96158da565b50604080518082018252600181526020810186905290516110049084156108fc029085906000818181858888f1935050505015801561211c573d6000803e3d6000fd5b5061200063f7a251d760016121308461411a565b612145876402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156121a357818101518382015260200161218b565b50505050905090810190601f1680156121d05780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156121f157600080fd5b505af1158015612205573d6000803e3d6000fd5b5050505083604001516001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600160405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561228757818101518382015260200161226f565b50505050905090810190601f1680156122b45780820380516001836020036101000a031916815260200191505b50935050505060405180910390a25060019695505050505050565b61100881565b6000806122e183613cb9565b90506122eb61589e565b50600081815260016020818152604092839020835160e081018552815460ff90811682529382015492810183905260028201546001600160a01b03169481019490945260038101546060850152600481015460808501526005015491821660a08401526101009091046001600160401b031660c08301526123b0576040805162461bcd60e51b815260206004820152601a602482015279189a5b99081c995c5d595cdd08191bd95cdb89dd08195e1a5cdd60321b604482015290519081900360640190fd5b80604001516001600160a01b0316856001600160a01b0316146124045760405162461bcd60e51b8152600401808060200182810382526045815260200180615a816045913960600191505060405180910390fd5b336001600160a01b0316856001600160a01b031663893d20e86040518163ffffffff1660e01b815260040160206040518083038186803b15801561244757600080fd5b505afa15801561245b573d6000803e3d6000fd5b505050506040513d602081101561247157600080fd5b50516001600160a01b0316146124ce576040805162461bcd60e51b815260206004820152601b60248201527f6f6e6c79206265703230206f776e65722063616e2072656a6563740000000000604482015290519081900360640190fd5b600034905060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561251057600080fd5b505afa158015612524573d6000803e3d6000fd5b505050506040513d602081101561253a57600080fd5b5051905080821080159061255357506402540be4008206155b61258e5760405162461bcd60e51b8152600401808060200182810382526037815260200180615a4a6037913960400191505060405180910390fd5b60008481526001602081905260408220805460ff191681559081018290556002810180546001600160a01b0319169055600381018290556004810191909155600501805468ffffffffffffffffff191690556125e86158da565b50604080518082018252600781526020810186905290516110049084156108fc029085906000818181858888f1935050505015801561262b573d6000803e3d6000fd5b5061200063f7a251d7600161263f8461411a565b612654876402540be40063ffffffff613b4216565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156126b257818101518382015260200161269a565b50505050905090810190601f1680156126df5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561270057600080fd5b505af1158015612714573d6000803e3d6000fd5b50505050876001600160a01b03167f831c0ef4d93bda3bce08b69ae3f29ef1a6e052b833200988554158494405a10788600760405180806020018360ff1663ffffffff168152602001828103825284818151815260200191508051906020019080838360005b8381101561279257818101518382015260200161277a565b50505050905090810190601f1680156127bf5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2506001979650505050505050565b600b81565b60045481565b33612000146128265760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff8316600414156128765761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061419092505050565b612930565b60ff8316600514156128c15761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061443d92505050565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051808460ff1660ff168152602001806020018281038252848482818152602001925080828437600083820152604051601f909101601f1916909201829003965090945050505050a15b505050565b6040805163bd46646160e01b81526001600160a01b0384166004820152905160009182916110049163bd466461916024808301926020929190829003018186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051146129f0576040805162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e48189bdd5b99609a1b604482015290519081900360640190fd5b6001600160a01b03831660009081526002602052604090205460ff1615612a4f576040805162461bcd60e51b815260206004820152600e60248201526d6d6972726f722070656e64696e6760901b604482015290519081900360640190fd5b60006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8c57600080fd5b505afa158015612aa0573d6000803e3d6000fd5b505050506040513d6020811015612ab657600080fd5b505190506402540be4003406158015612ae15750600454612add908263ffffffff613a1716565b3410155b612b1c5760405162461bcd60e51b815260040180806020018281038252604d815260200180615997604d913960600191505060405180910390fd5b42607801836001600160401b031610158015612b465750426201518001836001600160401b031611155b612b815760405162461bcd60e51b8152600401808060200182810382526038815260200180615a126038913960400191505060405180910390fd5b6000846001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612bbc57600080fd5b505afa158015612bd0573d6000803e3d6000fd5b505050506040513d6020811015612be657600080fd5b5051604080516318160ddd60e01b815290519192506000916001600160a01b038816916318160ddd916004808301926020929190829003018186803b158015612c2e57600080fd5b505afa158015612c42573d6000803e3d6000fd5b505050506040513d6020811015612c5857600080fd5b50519050677ce66c50e2840000612c728260ff8516613a71565b1115612cbe576040805162461bcd60e51b8152602060048201526016602482015275746f6f206c6172676520746f74616c20737570706c7960501b604482015290519081900360640190fd5b6060866001600160a01b03166306fdde036040518163ffffffff1660e01b815260040160006040518083038186803b158015612cf957600080fd5b505afa158015612d0d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612d3657600080fd5b8101908080516040519392919084600160201b821115612d5557600080fd5b908301906020820185811115612d6a57600080fd5b8251600160201b811182820188101715612d8357600080fd5b82525081516020918201929091019080838360005b83811015612db0578181015183820152602001612d98565b50505050905090810190601f168015612ddd5780820380516001836020036101000a031916815260200191505b50604052505050905060608190506001815110158015612dff57506020815111155b612e50576040805162461bcd60e51b815260206004820152601d60248201527f6e616d65206c656e677468206d75737420626520696e205b312c33325d000000604482015290519081900360640190fd5b6060886001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b158015612e8b57600080fd5b505afa158015612e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015612ec857600080fd5b8101908080516040519392919084600160201b821115612ee757600080fd5b908301906020820185811115612efc57600080fd5b8251600160201b811182820188101715612f1557600080fd5b82525081516020918201929091019080838360005b83811015612f42578181015183820152602001612f2a565b50505050905090810190601f168015612f6f5780820380516001836020036101000a031916815260200191505b5060405250508151919250829160021180159150612f8f57508051600810155b612fe0576040805162461bcd60e51b815260206004820152601e60248201527f73796d626f6c206c656e677468206d75737420626520696e205b322c385d0000604482015290519081900360640190fd5b60005b81518160ff16101561313457604160f81b828260ff168151811061300357fe5b01602001516001600160f81b031916108015906130415750602d60f91b828260ff168151811061302f57fe5b01602001516001600160f81b03191611155b806130995750606160f81b828260ff168151811061305b57fe5b01602001516001600160f81b031916108015906130995750603d60f91b828260ff168151811061308757fe5b01602001516001600160f81b03191611155b806130f15750600360fc1b828260ff16815181106130b357fe5b01602001516001600160f81b031916108015906130f15750603960f81b828260ff16815181106130df57fe5b01602001516001600160f81b03191611155b61312c5760405162461bcd60e51b815260040180806020018281038252602e815260200180615ac6602e913960400191505060405180910390fd5b600101612fe3565b50600454611004906108fc9061315190349063ffffffff613b0016565b6040518115909202916000818181858888f19350505050158015613179573d6000803e3d6000fd5b506001600160a01b038a166000908152600260209081526040909120805460ff1916600117905584810151908301516131b06158f1565b604051806101000160405280336001600160a01b031681526020018e6001600160a01b031681526020018481526020018381526020018981526020018a60ff16815260200161320f6402540be400600454613b4290919063ffffffff16565b81526001600160401b038e16602090910152905061200063f7a251d7600461323684614608565b6132546402540be40061131160045434613b0090919063ffffffff16565b6040518463ffffffff1660e01b8152600401808460ff1660ff16815260200180602001838152602001828103825284818151815260200191508051906020019080838360005b838110156132b257818101518382015260200161329a565b50505050905090810190601f1680156132df5780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561330057600080fd5b505af1158015613314573d6000803e3d6000fd5b5050505060019a505050505050505050505092915050565b600781565b600981565b677ce66c50e284000081565b61100781565b61100681565b60005460ff1681565b600081565b336110071461339c5760405162461bcd60e51b815260040180806020018281038252602e815260200180615b5b602e913960400191505060405180910390fd5b602081146133f1576040805162461bcd60e51b815260206004820152601860248201527f65787065637465642076616c7565206c656e6774682033320000000000000000604482015290519081900360640190fd5b606084848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f880181900481028201810190925286815293945060609392508691508590819084018382808284376000920191909152505050506020830151909150686d6972726f7246656560b81b8114156134e65760208201516402540be4008106156134de576040805162461bcd60e51b815260206004820152601a60248201527f6d6972726f72466565206d757374206265204e202a2031653130000000000000604482015290519081900360640190fd5b60045561359c565b6673796e6346656560c81b81141561355f5760208201516402540be400810615613557576040805162461bcd60e51b815260206004820152601860248201527f73796e63466565206d757374206265204e202a20316531300000000000000000604482015290519081900360640190fd5b60055561359c565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a878787876040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050505050565b61100281565b33612000146136775760405162461bcd60e51b815260040180806020018281038252602f815260200180615b89602f913960400191505060405180910390fd5b60ff8316600414156136c25761287182828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061477a92505050565b60ff8316600514156128c15761287182828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506148b992505050565b600160208190526000918252604090912080549181015460028201546003830154600484015460059094015460ff9586169593946001600160a01b039093169391929181169061010090046001600160401b031687565b604d81565b61100381565b60055481565b61100081565b61271081565b61100481565b606061379161589e565b600061379c846149b3565b91509150806137f2576040805162461bcd60e51b815260206004820152601f60248201527f756e7265636f676e697a6564207472616e73666572496e207061636b61676500604482015290519081900360640190fd5b815160ff166138a5576020828101805160009081526001928390526040908190208551815460ff1990811660ff928316178355935194820194909455908501516002820180546001600160a01b0319166001600160a01b03909216919091179055606085015160038201556080850151600482015560a08501516005909101805460c08701519316919093161768ffffffffffffffff0019166101006001600160401b03909216919091021790556139fc565b815160ff16600114156139af5760006110046001600160a01b03166359b9278984602001516040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b1580156138fe57600080fd5b505afa158015613912573d6000803e3d6000fd5b505050506040513d602081101561392857600080fd5b505190506001600160a01b038116156139a95760208301516040805163b99328c560e01b815260048101929092526001600160a01b0383166024830152516110049163b99328c591604480830192600092919082900301818387803b15801561399057600080fd5b505af11580156139a4573d6000803e3d6000fd5b505050505b506139fc565b6040805162461bcd60e51b815260206004820152601960248201527f756e7265636f676e697a65642062696e64207061636b61676500000000000000604482015290519081900360640190fd5b60408051600080825260208201909252905b50949350505050565b600082820183811015610e94576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60006008821115613ae957604d60071983011115613acb576040805162461bcd60e51b8152602060048201526012602482015271746f6f206c6172676520646563696d616c7360701b604482015290519081900360640190fd5b613ae2836007198401600a0a63ffffffff613b4216565b90506113eb565b610e94836008849003600a0a63ffffffff614b0416565b6000610e9483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b5d565b6000610e9483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614bf4565b60408051600680825260e08201909252606091829190816020015b6060815260200190600190039081613b9f5750508351909150613bca906001600160a01b0316614c59565b81600081518110613bd757fe5b6020026020010181905250613bf883602001516001600160a01b0316614c59565b81600181518110613c0557fe5b6020026020010181905250613c20836040015160001c614c7c565b81600281518110613c2d57fe5b6020026020010181905250613c458360600151614c7c565b81600381518110613c5257fe5b6020026020010181905250613c6a8360800151614c7c565b81600481518110613c7757fe5b6020026020010181905250613c988360a001516001600160401b0316614c7c565b81600581518110613ca557fe5b6020026020010181905250610e9481614c8f565b6020015190565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015613cfc57600080fd5b505afa158015613d10573d6000803e3d6000fd5b505050506040513d6020811015613d2657600080fd5b5051604080516395d89b4160e01b8152905160ff90921692506060916001600160a01b038616916395d89b41916004808301926000929190829003018186803b158015613d7257600080fd5b505afa158015613d86573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015613daf57600080fd5b8101908080516040519392919084600160201b821115613dce57600080fd5b908301906020820185811115613de357600080fd5b8251600160201b811182820188101715613dfc57600080fd5b82525081516020918201929091019080838360005b83811015613e29578181015183820152602001613e11565b50505050905090810190601f168015613e565780820380516001836020036101000a031916815260200191505b5060408181526370a0823160e01b82526110046004830152519495506000946001600160a01b038a1694506370a08231935060248083019350602092829003018186803b158015613ea657600080fd5b505afa158015613eba573d6000803e3d6000fd5b505050506040513d6020811015613ed057600080fd5b505160808701516060880151919250600091613ef19163ffffffff613b0016565b9050428760c001516001600160401b03161015613f165750600193506113eb92505050565b613f24838860200151614d19565b613f365750600293506113eb92505050565b80821115613f4c5750600393506113eb92505050565b866060015187604001516001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613f8e57600080fd5b505afa158015613fa2573d6000803e3d6000fd5b505050506040513d6020811015613fb857600080fd5b505114613fcd5750600493506113eb92505050565b8660a0015160ff168414613fe95750600593506113eb92505050565b602080880151604080516359b9278960e01b8152600481019290925251600092611004926359b927899260248083019392829003018186803b15801561402e57600080fd5b505afa158015614042573d6000803e3d6000fd5b505050506040513d602081101561405857600080fd5b50516001600160a01b03161415806140fa57506000801b6110046001600160a01b031663bd46646189604001516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156140cb57600080fd5b505afa1580156140df573d6000803e3d6000fd5b505050506040513d60208110156140f557600080fd5b505114155b1561410d5750600693506113eb92505050565b5060009695505050505050565b6040805160028082526060828101909352829190816020015b6060815260200190600190039081614133575050835190915061415b9063ffffffff16614c7c565b8160008151811061416857fe5b6020026020010181905250614183836020015160001c614c7c565b81600181518110613ca557fe5b614198615869565b60006141a383614e01565b91509150806141f0576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b03166000908152600290915260409020805460ff1916905560a082015160ff166143515760808201516040516110049180156108fc02916000818181858888f19350505050158015614253573d6000803e3d6000fd5b506110046001600160a01b0316638eff336c8360600151846020015185604001516040518463ffffffff1660e01b815260040180848152602001836001600160a01b03166001600160a01b031681526020018260ff1681526020019350505050600060405180830381600087803b1580156142cd57600080fd5b505af11580156142e1573d6000803e3d6000fd5b50505050602082810180516001600160a01b03908116600090815260038452604090819020805460ff1916600117905591516060860151835190815292519116927f41787d7db08fc5907641ee8343379f28215727eb123d4b462099afab4300b036928290030190a2505061443a565b815160808301516040516000926001600160a01b0316916127109184818181858888f193505050503d80600081146143a5576040519150601f19603f3d011682016040523d82523d6000602084013e6143aa565b606091505b50509050806143e75760808301516040516110029180156108fc02916000818181858888f193505050501580156143e5573d6000803e3d6000fd5b505b82602001516001600160a01b03167fefe400ad0042ebf81a245de9ae669616105e0ca9fc946352c085da0c2bc524e58460a00151604051808260ff1660ff16815260200191505060405180910390a25050505b50565b614445615935565b600061445083614f0e565b915091508061449d576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b606082015160ff1661451d5760408083015190516110049180156108fc02916000818181858888f193505050501580156144db573d6000803e3d6000fd5b5081602001516001600160a01b03167fbb7d3a9a559080d8281b0e4fb39dacbe2fdcafd5ef765e9a6ed871c9167dc60f60405160405180910390a2505061443a565b81602001516001600160a01b03167ff1e25fa536da84053644fd788b1d6a27ea6edd1f3af80c7d36ca253c4c82c9c38360600151604051808260ff1660ff16815260200191505060405180910390a2815160408084015190516000926001600160a01b0316916127109184818181858888f193505050503d80600081146145c0576040519150601f19603f3d011682016040523d82523d6000602084013e6145c5565b606091505b50509050806146025760408084015190516110029180156108fc02916000818181858888f19350505050158015614600573d6000803e3d6000fd5b505b50505050565b6040805160088082526101208201909252606091829190816020015b6060815260200190600190039081614624575050835190915061464f906001600160a01b0316614c59565b8160008151811061465c57fe5b602002602001018190525061467d83602001516001600160a01b0316614c59565b8160018151811061468a57fe5b60200260200101819052506146a5836040015160001c614c7c565b816002815181106146b257fe5b60200260200101819052506146cd836060015160001c614c7c565b816003815181106146da57fe5b60200260200101819052506146f28360800151614c7c565b816004815181106146ff57fe5b602002602001018190525061471a8360a0015160ff16614c7c565b8160058151811061472757fe5b602002602001018190525061473f8360c00151614c7c565b8160068151811061474c57fe5b602002602001018190525061476d8360e001516001600160401b0316614c7c565b81600781518110613ca557fe5b6147826158f1565b600061478d83614fda565b91509150806147da576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b6020808301516001600160a01b039081166000908152600290925260408220805460ff19169055835160c085015191169061271090614824906402540be40063ffffffff614b0416565b6040516000818181858888f193505050503d8060008114614861576040519150601f19603f3d011682016040523d82523d6000602084013e614866565b606091505b50509050806146025760c0830151611002906108fc90614891906402540be40063ffffffff614b0416565b6040518115909202916000818181858888f19350505050158015614600573d6000803e3d6000fd5b6148c1615869565b60006148cc8361512b565b9150915080614919576040805162461bcd60e51b8152602060048201526014602482015273756e7265636f676e697a6564207061636b61676560601b604482015290519081900360640190fd5b815160808301516000916001600160a01b03169061271090614946906402540be40063ffffffff614b0416565b6040516000818181858888f193505050503d8060008114614983576040519150601f19603f3d011682016040523d82523d6000602084013e614988565b606091505b5050905080614602576080830151611002906108fc90614891906402540be40063ffffffff614b0416565b6149bb61589e565b60006149c561589e565b6149cd61595c565b6149de6149d98661523b565b615260565b90506000805b6149ed836152aa565b15614af75780614a1257614a08614a03846152cb565b615319565b60ff168452614aef565b8060011415614a3157614a27614a03846152cb565b6020850152614aef565b8060021415614a5e57614a4b614a46846152cb565b6153ce565b6001600160a01b03166040850152614aef565b8060031415614a7d57614a73614a03846152cb565b6060850152614aef565b8060041415614a9c57614a92614a03846152cb565b6080850152614aef565b8060051415614abe57614ab1614a03846152cb565b60ff1660a0850152614aef565b8060061415614aea57614ad3614a03846152cb565b6001600160401b031660c085015260019150614aef565b614af7565b6001016149e4565b5091935090915050915091565b600082614b13575060006113eb565b82820282848281614b2057fe5b0414610e945760405162461bcd60e51b8152600401808060200182810382526021815260200180615af46021913960400191505060405180910390fd5b60008184841115614bec5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614bb1578181015183820152602001614b99565b50505050905090810190601f168015614bde5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183614c435760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614bb1578181015183820152602001614b99565b506000838581614c4f57fe5b0495945050505050565b60408051600560a21b8318601482015260348101909152606090610e94816153e8565b60606113eb614c8a8361543e565b6153e8565b6060815160001415614cb0575060408051600081526020810190915261157f565b606082600081518110614cbf57fe5b602002602001015190506000600190505b8351811015614d0057614cf682858381518110614ce957fe5b6020026020010151615524565b9150600101614cd0565b50610e94614d13825160c060ff166155a1565b82615524565b8151600090839060081080614d2f575080516002115b15614d3e5760009150506113eb565b60408051602080825281830190925260609160208201818036833701905050905083602082015280825181518110614d7257fe5b6020910101516001600160f81b031916602d60f81b14614d97576000925050506113eb565b600160005b8351811015614df757828181518110614db157fe5b602001015160f81c60f81b6001600160f81b031916848281518110614dd257fe5b01602001516001600160f81b03191614614def5760009150614df7565b600101614d9c565b5095945050505050565b614e09615869565b6000614e13615869565b614e1b61595c565b614e276149d98661523b565b90506000805b614e36836152aa565b15614af75780614e5c57614e4c614a46846152cb565b6001600160a01b03168452614f06565b8060011415614e8457614e71614a46846152cb565b6001600160a01b03166020850152614f06565b8060021415614ea657614e99614a03846152cb565b60ff166040850152614f06565b8060031415614ec557614ebb614a03846152cb565b6060850152614f06565b8060041415614ee457614eda614a03846152cb565b6080850152614f06565b8060051415614aea57614ef9614a03846152cb565b60ff1660a0850152600191505b600101614e2d565b614f16615935565b6000614f20615935565b614f2861595c565b614f346149d98661523b565b90506000805b614f43836152aa565b15614af75780614f6957614f59614a46846152cb565b6001600160a01b03168452614fd2565b8060011415614f9157614f7e614a46846152cb565b6001600160a01b03166020850152614fd2565b8060021415614fb057614fa6614a03846152cb565b6040850152614fd2565b8060031415614aea57614fc5614a03846152cb565b60ff166060850152600191505b600101614f3a565b614fe26158f1565b6000614fec6158f1565b614ff461595c565b6150006149d98661523b565b90506000805b61500f836152aa565b15614af7578061503557615025614a46846152cb565b6001600160a01b03168452615123565b806001141561505d5761504a614a46846152cb565b6001600160a01b03166020850152615123565b806002141561507c57615072614a03846152cb565b6040850152615123565b806003141561509b57615091614a03846152cb565b6060850152615123565b80600414156150ba576150b0614a03846152cb565b6080850152615123565b80600514156150dc576150cf614a03846152cb565b60ff1660a0850152615123565b80600614156150fb576150f1614a03846152cb565b60c0850152615123565b8060071415614aea57615110614a03846152cb565b6001600160401b031660e0850152600191505b600101615006565b615133615869565b600061513d615869565b61514561595c565b6151516149d98661523b565b90506000805b615160836152aa565b15614af7578061518657615176614a46846152cb565b6001600160a01b03168452615233565b80600114156151ae5761519b614a46846152cb565b6001600160a01b03166020850152615233565b80600214156151cd576151c3614a03846152cb565b6040850152615233565b80600314156151ec576151e2614a03846152cb565b6060850152615233565b806004141561520b57615201614a03846152cb565b6080850152615233565b8060051415614aea57615220614a03846152cb565b6001600160401b031660a0850152600191505b600101615157565b61524361597c565b506040805180820190915281518152602082810190820152919050565b61526861595c565b61527182615699565b61527a57600080fd5b600061528983602001516156d3565b60208085015160408051808201909152868152920190820152915050919050565b60006152b461597c565b505080518051602091820151919092015191011190565b6152d361597c565b6152dc826152aa565b6152e557600080fd5b602082015160006152f582615736565b80830160209586015260408051808201909152908152938401919091525090919050565b80516000901580159061532e57508151602110155b61533757600080fd5b600061534683602001516156d3565b905080836000015110156153a1576040805162461bcd60e51b815260206004820152601a60248201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604482015290519081900360640190fd5b825160208085015183018051928490039291831015613a0e57506020919091036101000a90049392505050565b80516000906015146153df57600080fd5b6113eb82615319565b60608151600114801561541a5750607f60f81b8260008151811061540857fe5b01602001516001600160f81b03191611155b1561542657508061157f565b6113eb6154388351608060ff166155a1565b83615524565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff198416615482575060186154a6565b6fffffffffffffffffffffffffffffffff1984166154a2575060106154a6565b5060005b60208110156154dc578181815181106154bb57fe5b01602001516001600160f81b031916156154d4576154dc565b6001016154a6565b60008160200390506060816040519080825280601f01601f191660200182016040528015615511576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b8183101561555557805183526020928301920161553d565b50855184518101855292509050808201602086015b8183101561558257805183526020928301920161556a565b508651929092011591909101601f01601f191660405250905092915050565b60606801000000000000000083106155f1576040805162461bcd60e51b815260206004820152600e60248201526d696e70757420746f6f206c6f6e6760901b604482015290519081900360640190fd5b6040805160018082528183019092526060916020820181803683370190505090506037841161564b5782840160f81b8160008151811061562d57fe5b60200101906001600160f81b031916908160001a90535090506113eb565b60606156568561543e565b90508381510160370160f81b8260008151811061566f57fe5b60200101906001600160f81b031916908160001a9053506156908282615524565b95945050505050565b80516000906156aa5750600061157f565b6020820151805160001a9060c08210156156c95760009250505061157f565b5060019392505050565b8051600090811a60808110156156ed57600091505061157f565b60b8811080615708575060c08110801590615708575060f881105b1561571757600191505061157f565b60c081101561572b5760b51901905061157f565b60f51901905061157f565b80516000908190811a60808110156157515760019150615862565b60b881101561576657607e1981019150615862565b60c08110156157e057600060b78203600186019550806020036101000a8651049150600181018201935050808310156157da576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b50615862565b60f88110156157f55760be1981019150615862565b600060f78203600186019550806020036101000a865104915060018101820193505080831015615860576040805162461bcd60e51b81526020600482015260116024820152706164646974696f6e206f766572666c6f7760781b604482015290519081900360640190fd5b505b5092915050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b604080518082019091526000808252602082015290565b6040805161010081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081019190915290565b60408051608081018252600080825260208201819052918101829052606081019190915290565b604051806040016040528061596f61597c565b8152602001600081525090565b60405180604001604052806000815260200160008152509056fe6d73672e76616c7565206d757374206265204e202a203165313020616e642067726561746572207468616e2073756d206f66206d696e6952656c617946656520616e64206d6972726f724665656f6e6c79206265703230206f776e65722063616e20617070726f766520746869732062696e64207265717565737465787069726554696d65206d7573742062652074776f206d696e75746573206c6174657220616e64206f6e6520646179206561726c69657272656c6179466565206d757374206265204e202a203165313020616e642067726561746572207468616e206d696e6952656c6179466565636f6e74616374206164647265737320646f65736e277420657175616c20746f2074686520636f6e7472616374206164647265737320696e2062696e64207265717565737473796d626f6c2073686f756c64206f6e6c7920636f6e7461696e20616c70686162657420616e64206e756d626572536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f776d73672e76616c7565206d757374206265204e202a203165313020616e64206e6f206c6573732073756d206f66206d696e6952656c617946656520616e642073796e63466565746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e7472616374746865206d6573736167652073656e646572206d7573742062652063726f737320636861696e20636f6e747261637474686520626570323020746f6b656e20697320696e206d6972726f722070656e64696e6720737461747573a2646970667358221220ab8dfdd9914857b55fc1c6e49c911de2d861380dc81004c5ff0a4e67915545b764736f6c63430006040033" }, "0x0000000000000000000000000000000000002000": { "balance": "0x0", - "code": "0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063863fe4ab1161013b578063c81b1662116100b8578063e3b048051161007c578063e3b048051461072c578063f7a251d71461074c578063f9a2bbc7146107c4578063fc3e5908146107cc578063fd6a6879146107d457610248565b8063c81b1662146106dd578063d31f968d146106e5578063d76a867514610714578063dc927faf1461071c578063e1c7392a1461072457610248565b8063a78abc16116100ff578063a78abc16146105d3578063ab51bb96146105db578063ac431751146105e3578063b0355f5b146103ff578063c27cdcfb146106a157610248565b8063863fe4ab146105b35780638cc8f561146104b657806396713da9146105bb5780639dc09262146105c3578063a1a11bf5146105cb57610248565b8063493279b1116101c957806370fd5bad1161018d57806370fd5bad146104b657806374f079b8146104be57806375d47a0a146104c65780637942fd05146104ce57806384013b6a146104d657610248565b8063493279b11461045f5780634bf6c8821461047e57806351e80672146104865780636e47a51a1461048e5780636e47b482146104ae57610248565b8063308325f411610210578063308325f4146102cf5780633bdc47a6146102d75780633dffc387146103ff578063422f90501461040757806343756e5c1461043b57610248565b806305e682581461024d5780630bee7a671461026b57806314b3023b1461028c57806322556cdc146102a65780632ff32aea146102ae575b600080fd5b6102556107dc565b6040805160ff9092168252519081900360200190f35b6102736107e1565b6040805163ffffffff9092168252519081900360200190f35b6102946107e6565b60408051918252519081900360200190f35b6102946107ec565b6102b66107f1565b60408051600792830b90920b8252519081900360200190f35b6102946107fa565b61038a600480360360608110156102ed57600080fd5b60ff82351691602081013591810190606081016040820135600160201b81111561031657600080fd5b82018360208201111561032857600080fd5b803590602001918460018302840111600160201b8311171561034957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610800945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103c45781810151838201526020016103ac565b50505050905090810190601f1680156103f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610255610876565b6104276004803603602081101561041d57600080fd5b503560ff1661087b565b604080519115158252519081900360200190f35b610443610890565b604080516001600160a01b039092168252519081900360200190f35b610467610896565b6040805161ffff9092168252519081900360200190f35b61025561089b565b6104436108a0565b610443600480360360208110156104a457600080fd5b503560ff166108a6565b6104436108c1565b6102556108c7565b6102946108cc565b6104436108d2565b6102556108d8565b6105b1600480360360a08110156104ec57600080fd5b810190602081018135600160201b81111561050657600080fd5b82018360208201111561051857600080fd5b803590602001918460018302840111600160201b8311171561053957600080fd5b919390929091602081019035600160201b81111561055657600080fd5b82018360208201111561056857600080fd5b803590602001918460018302840111600160201b8311171561058957600080fd5b919350915080356001600160401b03908116916020810135909116906040013560ff166108dd565b005b610294611a8d565b610255611a95565b610443611a9a565b610443611aa0565b610427611aa6565b6102736107dc565b6105b1600480360360408110156105f957600080fd5b810190602081018135600160201b81111561061357600080fd5b82018360208201111561062557600080fd5b803590602001918460018302840111600160201b8311171561064657600080fd5b919390929091602081019035600160201b81111561066357600080fd5b82018360208201111561067557600080fd5b803590602001918460018302840111600160201b8311171561069657600080fd5b509092509050611aaf565b6106c1600480360360208110156106b757600080fd5b503560ff16612051565b604080516001600160401b039092168252519081900360200190f35b61044361206c565b610427600480360360408110156106fb57600080fd5b5080356001600160a01b0316906020013560ff16612072565b61038a612092565b6104436120b1565b6105b16120b7565b6106c16004803603602081101561074257600080fd5b503560ff1661246e565b6105b16004803603606081101561076257600080fd5b60ff8235169190810190604081016020820135600160201b81111561078657600080fd5b82018360208201111561079857600080fd5b803590602001918460018302840111600160201b831117156107b957600080fd5b919350915035612489565b6104436125da565b6102556125e0565b6104436125e5565b600081565b606481565b60015481565b603281565b60045460070b81565b60025481565b60606000825160210190506060816040519080825280601f01601f191660200182016040528015610838576020820181803683370190505b506021810186905260018101879052828152905060418101600061085b866125eb565b50905061086a818388516125f5565b50909695505050505050565b600181565b60096020526000908152604090205460ff1681565b61100181565b606081565b600881565b61200081565b6005602052600090815260409020546001600160a01b031681565b61100581565b600281565b60035481565b61100881565b600b81565b60005460ff16610930576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b60408051630a83aaa960e31b815233600482015290516110069163541d5548916024808301926020929190829003018186803b15801561096f57600080fd5b505afa158015610983573d6000803e3d6000fd5b505050506040513d602081101561099957600080fd5b50516109ec576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b60ff8116600090815260086020526040902054829082906001600160401b039081169083168114610a5c576040805162461bcd60e51b815260206004820152601560248201527439b2b8bab2b731b2903737ba1034b71037b93232b960591b604482015290519081900360640190fd5b60ff8216600090815260086020908152604091829020805467ffffffffffffffff1916600185016001600160401b039081169190911790915582516337d7f9c160e21b81529089166004820152915188926110039263df5fe70492602480840193829003018186803b158015610ad157600080fd5b505afa158015610ae5573d6000803e3d6000fd5b505050506040513d6020811015610afb57600080fd5b5051610b385760405162461bcd60e51b8152600401808060200182810382526023815260200180612bcc6023913960400191505060405180910390fd5b60ff851660009081526005602052604090205485906001600160a01b0316610ba7576040805162461bcd60e51b815260206004820152601860248201527f6368616e6e656c206973206e6f7420737570706f727465640000000000000000604482015290519081900360640190fd5b60608c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805163cba510a960e01b81526001600160401b038f1660048201529051939450610cce93611003935063cba510a992506024808301926020929190829003018186803b158015610c7757600080fd5b505afa158015610c8b573d6000803e3d6000fd5b505050506040513d6020811015610ca157600080fd5b505160408051808201909152600381526269626360e81b6020820152610cc78c8c612636565b858561267d565b610d16576040805162461bcd60e51b815260206004820152601460248201527334b73b30b634b21036b2b935b63290383937b7b360611b604482015290519081900360640190fd5b60408051631bb5062960e31b81526001600160401b038c16600482015290516000916110039163dda8314891602480820192602092909190829003018186803b158015610d6257600080fd5b505afa158015610d76573d6000803e3d6000fd5b505050506040513d6020811015610d8c57600080fd5b5051905088600080806060610da08861277a565b935093509350935083610e61578460ff168f6001600160401b03167ff7b2e42d694eb1100184aae86d4245d9e46966100b1dc7e723275b98326854ac8a6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610e1a578181015183820152602001610e02565b50505050905090810190601f168015610e475780820380516001836020036101000a031916815260200191505b509250505060405180910390a35050505050505050611a7f565b8460ff168f6001600160401b03167f36afdaf439a8f43fe72135135d804ae620b37a474f0943b5b85f6788312cad4085604051808260ff1660ff16815260200191505060405180910390a360ff83166113ea5760ff85166000818152600560209081526040808320548151631182b87560e01b815260048101958652602481019283528651604482015286516001600160a01b03909216958695631182b875958d958a9593949093606490910192918601918190849084905b83811015610f32578181015183820152602001610f1a565b50505050905090810190601f168015610f5f5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015610f7f57600080fd5b505af192505050801561106357506040513d6000823e601f3d908101601f191682016040526020811015610fb257600080fd5b8101908080516040519392919084600160201b821115610fd157600080fd5b908301906020820185811115610fe657600080fd5b8251600160201b811182820188101715610fff57600080fd5b82525081516020918201929091019080838360005b8381101561102c578181015183820152602001611014565b50505050905090810190601f1680156110595780820380516001836020036101000a031916815260200191505b5060405250505060015b611375576040516000815260443d101561107f5750600061111a565b60046000803e60005160e01c6308c379a081146110a057600091505061111a565b60043d036004833e81513d60248201116001600160401b03821117156110cb5760009250505061111a565b80830180516001600160401b038111156110ec57600094505050505061111a565b8060208301013d860181111561110a5760009550505050505061111a565b601f01601f191660405250925050505b806111255750611237565b60ff871660009081526007602052604081205461115c916001600160401b039091169089906111579060029088610800565b61282a565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf948794849390840192918601918190849084905b838110156111f75781810151838201526020016111df565b50505050905090810190601f1680156112245780820380516001836020036101000a031916815260200191505b509250505060405180910390a250611370565b3d808015611261576040519150601f19603f3d011682016040523d82523d6000602084013e611266565b606091505b5060ff8716600090815260076020526040812054611299916001600160401b039091169089906111579060029088610800565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351948794849390840192918601918190849084905b8381101561133457818101518382015260200161131c565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6113e4565b8051156113e25760ff87166000908152600760205260408120546113ae916001600160401b039091169089906111579060019086610800565b60ff8716600090815260076020526040902080546001600160401b038082166001011667ffffffffffffffff199091161790555b505b506119b8565b60ff83166001141561168e5760ff8516600081815260056020908152604080832054815163831d65d160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563831d65d1958d958a9593949093606490910192918601918190849084905b8381101561147457818101518382015260200161145c565b50505050905090810190601f1680156114a15780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156114c157600080fd5b505af19250505080156114d2575060015b6113e4576040516000815260443d10156114ee57506000611589565b60046000803e60005160e01c6308c379a0811461150f576000915050611589565b60043d036004833e81513d60248201116001600160401b038211171561153a57600092505050611589565b80830180516001600160401b0381111561155b576000945050505050611589565b8060208301013d860181111561157957600095505050505050611589565b601f01601f191660405250925050505b8061159457506115f9565b60408051602080825283518183015283516001600160a01b038616937ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf93869390928392830191850190808383600083156111f75781810151838201526020016111df565b3d808015611623576040519150601f19603f3d011682016040523d82523d6000602084013e611628565b606091505b5060408051602080825283518183015283516001600160a01b038616937f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351938693909283928301918501908083836000831561133457818101518382015260200161131c565b60ff8316600214156119b85760ff8516600081815260056020908152604080832054815163c8509d8160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563c8509d81958d958a9593949093606490910192918601918190849084905b83811015611718578181015183820152602001611700565b50505050905090810190601f1680156117455780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561176557600080fd5b505af1925050508015611776575060015b6119b6576040516000815260443d10156117925750600061182d565b60046000803e60005160e01c6308c379a081146117b357600091505061182d565b60043d036004833e81513d60248201116001600160401b03821117156117de5760009250505061182d565b80830180516001600160401b038111156117ff57600094505050505061182d565b8060208301013d860181111561181d5760009550505050505061182d565b601f01601f191660405250925050505b8061183857506118e1565b816001600160a01b03167ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf826040518080602001828103825283818151815260200191508051906020019080838360005b838110156118a1578181015183820152602001611889565b50505050905090810190601f1680156118ce5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2506119b6565b3d80801561190b576040519150601f19603f3d011682016040523d82523d6000602084013e611910565b606091505b50816001600160a01b03167f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351826040518080602001828103825283818151815260200191508051906020019080838360005b8381101561197a578181015183820152602001611962565b50505050905090810190601f1680156119a75780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b505b60ff80861660009081526009602052604090205461100591636f93d2e69189913391879116806119ea575060ff881615155b604080516001600160e01b031960e088901b1681526001600160a01b039586166004820152939094166024840152604483019190915215156064820152905160848083019260209291908290030181600087803b158015611a4a57600080fd5b505af1158015611a5e573d6000803e3d6000fd5b505050506040513d6020811015611a7457600080fd5b505050505050505050505b505050505050505050505050565b630100600081565b600981565b61100781565b61100681565b60005460ff1681565b3361100714611aef5760405162461bcd60e51b815260040180806020018281038252602e815260200180612b22602e913960400191505060405180910390fd5b611b5884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526012815271626174636853697a65466f724f7261636c6560701b602082015291506129809050565b15611bf357604080516020601f8401819004810282018101909252828152600091611b9b91858580838501838280828437600092019190915250612a6792505050565b90506127108111158015611bb05750600a8110155b611beb5760405162461bcd60e51b8152600401808060200182810382526032815260200180612b9a6032913960400191505060405180910390fd5b600155611fbf565b611c5c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601281527118591913dc955c19185d1950da185b9b995b60721b602082015291506129809050565b15611de457606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060169091149050611cdf5760405162461bcd60e51b815260040180806020018281038252605a815260200180612ac8605a913960600191505060405180910390fd5b60018101516002820151601683015160ff82161590611cfd81612a6c565b611d4e576040805162461bcd60e51b815260206004820152601960248201527f61646472657373206973206e6f74206120636f6e747261637400000000000000604482015290519081900360640190fd5b60ff8416600081815260056020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452600683528184208585528352818420805460ff199081166001179091556009909352818420805490931687151517909255519092917f7e3b6af43092577ee20e60eaa1d9b114a7031305c895ee7dd3ffe17196d2e1e091a35050505050611fbf565b611e5184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526016815275195b98589b1953dc911a5cd8589b1950da185b9b995b60521b602082015291506129809050565b15611f8257606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060029091149050611ed45760405162461bcd60e51b815260040180806020018281038252604a815260200180612b50604a913960600191505060405180910390fd5b600181810151600283015160ff80831660009081526005602052604090205492939192908316909114906001600160a01b03168015611f78576001600160a01b038116600090815260066020908152604080832060ff881680855290835292819020805460ff1916861515908117909155815190815290517fa3132e3f9819fbddc7f0ed6d38d7feef59aa95112090b7c592f5cb5bc4aa4adc929181900390910190a25b5050505050611fbf565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b6008602052600090815260409020546001600160401b031681565b61100281565b600660209081526000928352604080842090915290825290205460ff1681565b6040518060400160405280600381526020016269626360e81b81525081565b61100381565b60005460ff161561210f576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b7f1471eb6eb2c5e789fc3de43f8ce62938c7d1836ec861730447e2ada8fd81017b80546001600160a01b0319908116611008179091557f92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36805460ff199081169091557fd8af288fc1c8680b4f4706064cf021e264efb6828fcaf7eb5ca36818eb365bcc8054821660019081179091557f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a805484166110049081179091557f6cde3cea4b3a3fb2488b2808bae7556f4a405e50f65e1794383bc026131b13c38054841690557f72e4efa1513b071517c6c74dba31b5934a81aa83cddd400e7081df5529c9943680548416831790557fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc08054851690911790557fc575c31fea594a6eb97c8e9d3f9caee4c16218c6ef37e923234c0fe9014a61e78054831690557f4e523af77f034e9810f1c94057f5e931fb3d16a51511a4c3add793617d18610580548316821790557ffb33122aa9f93cc639ebe80a7bc4784c11e6053dde89c6f4f7e268c6a623da1e805484166110001790557fc7694af312c4f286114180fd0ba6a52461fcee8a381636770b19a343af92538a80548316821790557f01112dd68e482ba8d68a7e828cff8b3abcea08eab88941953c180a7e650e9cd480548316821790557fc0a4a8be475dfebc377ebef2d7c4ff47656f572a08dd92b81017efcdba0febe1805484166110071790557f87e8a52529e8ece4ef759037313542a6429ff494a9fab9027fb79db90124eba680548316821790557f4c7666bbcb22d46469f7cc282f70764a7012dca2cce630ff8d83db9a9cdd48f080548316821790557f40f28f99a40bc9f6beea1013afdbc3cdcc689eb76b82c4de06c0acf1e1932ed58054909316611001179092557f0d9cf2cd531699eed8dd34e40ff2884a14a698c4898184fba85194e6f6772d248054821683179055600b60009081527f23f68c9bd22b8a93d06adabe17481c87c016bcbd20adc8bfd707a4d813a572176020527fdf0d5d05428057f5455c2dc8e810dd86d1e9350faa72f16bda8a45443c5b39328054831684179055603283556004805467ffffffffffffffff19166001600160401b031790556002819055600381905580549091169091179055565b6007602052600090815260409020546001600160401b031681565b60005460ff166124dc576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b33600090815260066020908152604080832060ff80891685529252909120548591166125395760405162461bcd60e51b8152600401808060200182810382526031815260200180612a976031913960400191505060405180910390fd5b60ff85166000908152600760209081526040808320548151601f88018490048402810184019092528682526001600160401b03169261259e9284928a9261115792909189918c908c908190840183828082843760009201919091525061080092505050565b60ff959095166000908152600760205260409020805467ffffffffffffffff191660019096016001600160401b03169590951790945550505050565b61100081565b600381565b61100481565b8051602090910191565b5b60208110612615578251825260209283019290910190601f19016125f6565b915181516020939093036101000a6000190180199091169216919091179052565b60408051600e808252818301909252606091630100600060ff851617918391602082018180368337505050600e818101969096526006810192909252509283525090919050565b60008561268c57506000612771565b606082518451865160800101016040519080825280601f01601f1916602001820160405280156126c3576020820181803683370190505b50905060006126d182612a72565b6020808901518252019050866000806126e9896125eb565b80865260209095019490925090506127028285836125f5565b9283019261270f886125eb565b80865260209095019490925090506127288285836125f5565b9283018a81526020019261273b876125eb565b909250905061274b8285836125f5565b508351602001612759612a78565b60208183886065600019fa5051600114955050505050505b95945050505050565b600080600060606021855110156127aa575050604080516000808252602082019092529092508291508190612823565b600185015160218601518651604080516020198301808252601f19600119909401939093168101602001909152604189019392916060919080156127f5576020820181803683370190505b5090506000612803826125eb565b509050612815858260218d51036125f5565b506001975091955093509150505b9193509193565b600254431115612869576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b1617909155600355436002556128aa565b600380546001908101918290555410156128aa576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b16179091556003555b8160ff16836001600160401b0316600460009054906101000a900460070b6001600160401b03167f3a6e0fc61675aa2a100bcba0568368bb92bcec91c97673391074f11138f0cffe606085604051808361ffff1661ffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612940578181015183820152602001612928565b50505050905090810190601f16801561296d5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a4505050565b6000816040516020018082805190602001908083835b602083106129b55780518252601f199092019160209182019101612996565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310612a235780518252601f199092019160209182019101612a04565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b3b151590565b60200190565b6040518060200160405280600190602082028036833750919291505056fe74686520636f6e747261637420616e64206368616e6e656c2068617665206e6f74206265656e20726567697374657265646c656e677468206f662076616c756520666f72206164644f725570646174654368616e6e656c2073686f756c642062652032322c206368616e6e656c49643a697346726f6d53797374656d3a68616e646c657241646472657373746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f7220656e61626c654f7244697361626c654368616e6e656c2073686f756c6420626520322c206368616e6e656c49643a6973456e61626c65746865206e6577426174636853697a65466f724f7261636c652073686f756c6420626520696e205b31302c2031303030305d6c6967687420636c69656e74206e6f742073796e632074686520626c6f636b20796574a264697066735822122033c2492ac02e70488d9ed3adb95888d7f5998dff786cf03d72be0cde759a14d064736f6c63430006040033" + "code": "0x608060405234801561001057600080fd5b50600436106102485760003560e01c8063863fe4ab1161013b578063c81b1662116100b8578063e3b048051161007c578063e3b048051461072c578063f7a251d71461074c578063f9a2bbc7146107c4578063fc3e5908146107cc578063fd6a6879146107d457610248565b8063c81b1662146106dd578063d31f968d146106e5578063d76a867514610714578063dc927faf1461071c578063e1c7392a1461072457610248565b8063a78abc16116100ff578063a78abc16146105d3578063ab51bb96146105db578063ac431751146105e3578063b0355f5b146103ff578063c27cdcfb146106a157610248565b8063863fe4ab146105b35780638cc8f561146104b657806396713da9146105bb5780639dc09262146105c3578063a1a11bf5146105cb57610248565b8063493279b1116101c957806370fd5bad1161018d57806370fd5bad146104b657806374f079b8146104be57806375d47a0a146104c65780637942fd05146104ce57806384013b6a146104d657610248565b8063493279b11461045f5780634bf6c8821461047e57806351e80672146104865780636e47a51a1461048e5780636e47b482146104ae57610248565b8063308325f411610210578063308325f4146102cf5780633bdc47a6146102d75780633dffc387146103ff578063422f90501461040757806343756e5c1461043b57610248565b806305e682581461024d5780630bee7a671461026b57806314b3023b1461028c57806322556cdc146102a65780632ff32aea146102ae575b600080fd5b6102556107dc565b6040805160ff9092168252519081900360200190f35b6102736107e1565b6040805163ffffffff9092168252519081900360200190f35b6102946107e6565b60408051918252519081900360200190f35b6102946107ec565b6102b66107f1565b60408051600792830b90920b8252519081900360200190f35b6102946107fa565b61038a600480360360608110156102ed57600080fd5b60ff82351691602081013591810190606081016040820135600160201b81111561031657600080fd5b82018360208201111561032857600080fd5b803590602001918460018302840111600160201b8311171561034957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610800945050505050565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103c45781810151838201526020016103ac565b50505050905090810190601f1680156103f15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610255610876565b6104276004803603602081101561041d57600080fd5b503560ff1661087b565b604080519115158252519081900360200190f35b610443610890565b604080516001600160a01b039092168252519081900360200190f35b610467610896565b6040805161ffff9092168252519081900360200190f35b61025561089b565b6104436108a0565b610443600480360360208110156104a457600080fd5b503560ff166108a6565b6104436108c1565b6102556108c7565b6102946108cc565b6104436108d2565b6102556108d8565b6105b1600480360360a08110156104ec57600080fd5b810190602081018135600160201b81111561050657600080fd5b82018360208201111561051857600080fd5b803590602001918460018302840111600160201b8311171561053957600080fd5b919390929091602081019035600160201b81111561055657600080fd5b82018360208201111561056857600080fd5b803590602001918460018302840111600160201b8311171561058957600080fd5b919350915080356001600160401b03908116916020810135909116906040013560ff166108dd565b005b610294611a8d565b610255611a95565b610443611a9a565b610443611aa0565b610427611aa6565b6102736107dc565b6105b1600480360360408110156105f957600080fd5b810190602081018135600160201b81111561061357600080fd5b82018360208201111561062557600080fd5b803590602001918460018302840111600160201b8311171561064657600080fd5b919390929091602081019035600160201b81111561066357600080fd5b82018360208201111561067557600080fd5b803590602001918460018302840111600160201b8311171561069657600080fd5b509092509050611aaf565b6106c1600480360360208110156106b757600080fd5b503560ff16612051565b604080516001600160401b039092168252519081900360200190f35b61044361206c565b610427600480360360408110156106fb57600080fd5b5080356001600160a01b0316906020013560ff16612072565b61038a612092565b6104436120b1565b6105b16120b7565b6106c16004803603602081101561074257600080fd5b503560ff1661246e565b6105b16004803603606081101561076257600080fd5b60ff8235169190810190604081016020820135600160201b81111561078657600080fd5b82018360208201111561079857600080fd5b803590602001918460018302840111600160201b831117156107b957600080fd5b919350915035612489565b6104436125da565b6102556125e0565b6104436125e5565b600081565b606481565b60015481565b603281565b60045460070b81565b60025481565b60606000825160210190506060816040519080825280601f01601f191660200182016040528015610838576020820181803683370190505b506021810186905260018101879052828152905060418101600061085b866125eb565b50905061086a818388516125f5565b50909695505050505050565b600181565b60096020526000908152604090205460ff1681565b61100181565b603881565b600881565b61200081565b6005602052600090815260409020546001600160a01b031681565b61100581565b600281565b60035481565b61100881565b600b81565b60005460ff16610930576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b60408051630a83aaa960e31b815233600482015290516110069163541d5548916024808301926020929190829003018186803b15801561096f57600080fd5b505afa158015610983573d6000803e3d6000fd5b505050506040513d602081101561099957600080fd5b50516109ec576040805162461bcd60e51b815260206004820152601f60248201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604482015290519081900360640190fd5b60ff8116600090815260086020526040902054829082906001600160401b039081169083168114610a5c576040805162461bcd60e51b815260206004820152601560248201527439b2b8bab2b731b2903737ba1034b71037b93232b960591b604482015290519081900360640190fd5b60ff8216600090815260086020908152604091829020805467ffffffffffffffff1916600185016001600160401b039081169190911790915582516337d7f9c160e21b81529089166004820152915188926110039263df5fe70492602480840193829003018186803b158015610ad157600080fd5b505afa158015610ae5573d6000803e3d6000fd5b505050506040513d6020811015610afb57600080fd5b5051610b385760405162461bcd60e51b8152600401808060200182810382526023815260200180612bcc6023913960400191505060405180910390fd5b60ff851660009081526005602052604090205485906001600160a01b0316610ba7576040805162461bcd60e51b815260206004820152601860248201527f6368616e6e656c206973206e6f7420737570706f727465640000000000000000604482015290519081900360640190fd5b60608c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050905060608b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805163cba510a960e01b81526001600160401b038f1660048201529051939450610cce93611003935063cba510a992506024808301926020929190829003018186803b158015610c7757600080fd5b505afa158015610c8b573d6000803e3d6000fd5b505050506040513d6020811015610ca157600080fd5b505160408051808201909152600381526269626360e81b6020820152610cc78c8c612636565b858561267d565b610d16576040805162461bcd60e51b815260206004820152601460248201527334b73b30b634b21036b2b935b63290383937b7b360611b604482015290519081900360640190fd5b60408051631bb5062960e31b81526001600160401b038c16600482015290516000916110039163dda8314891602480820192602092909190829003018186803b158015610d6257600080fd5b505afa158015610d76573d6000803e3d6000fd5b505050506040513d6020811015610d8c57600080fd5b5051905088600080806060610da08861277a565b935093509350935083610e61578460ff168f6001600160401b03167ff7b2e42d694eb1100184aae86d4245d9e46966100b1dc7e723275b98326854ac8a6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610e1a578181015183820152602001610e02565b50505050905090810190601f168015610e475780820380516001836020036101000a031916815260200191505b509250505060405180910390a35050505050505050611a7f565b8460ff168f6001600160401b03167f36afdaf439a8f43fe72135135d804ae620b37a474f0943b5b85f6788312cad4085604051808260ff1660ff16815260200191505060405180910390a360ff83166113ea5760ff85166000818152600560209081526040808320548151631182b87560e01b815260048101958652602481019283528651604482015286516001600160a01b03909216958695631182b875958d958a9593949093606490910192918601918190849084905b83811015610f32578181015183820152602001610f1a565b50505050905090810190601f168015610f5f5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b158015610f7f57600080fd5b505af192505050801561106357506040513d6000823e601f3d908101601f191682016040526020811015610fb257600080fd5b8101908080516040519392919084600160201b821115610fd157600080fd5b908301906020820185811115610fe657600080fd5b8251600160201b811182820188101715610fff57600080fd5b82525081516020918201929091019080838360005b8381101561102c578181015183820152602001611014565b50505050905090810190601f1680156110595780820380516001836020036101000a031916815260200191505b5060405250505060015b611375576040516000815260443d101561107f5750600061111a565b60046000803e60005160e01c6308c379a081146110a057600091505061111a565b60043d036004833e81513d60248201116001600160401b03821117156110cb5760009250505061111a565b80830180516001600160401b038111156110ec57600094505050505061111a565b8060208301013d860181111561110a5760009550505050505061111a565b601f01601f191660405250925050505b806111255750611237565b60ff871660009081526007602052604081205461115c916001600160401b039091169089906111579060029088610800565b61282a565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf948794849390840192918601918190849084905b838110156111f75781810151838201526020016111df565b50505050905090810190601f1680156112245780820380516001836020036101000a031916815260200191505b509250505060405180910390a250611370565b3d808015611261576040519150601f19603f3d011682016040523d82523d6000602084013e611266565b606091505b5060ff8716600090815260076020526040812054611299916001600160401b039091169089906111579060029088610800565b60ff8716600090815260076020908152604080832080546001600160401b038082166001011667ffffffffffffffff19909116179055805182815284518184015284516001600160a01b038716947f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351948794849390840192918601918190849084905b8381101561133457818101518382015260200161131c565b50505050905090810190601f1680156113615780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b6113e4565b8051156113e25760ff87166000908152600760205260408120546113ae916001600160401b039091169089906111579060019086610800565b60ff8716600090815260076020526040902080546001600160401b038082166001011667ffffffffffffffff199091161790555b505b506119b8565b60ff83166001141561168e5760ff8516600081815260056020908152604080832054815163831d65d160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563831d65d1958d958a9593949093606490910192918601918190849084905b8381101561147457818101518382015260200161145c565b50505050905090810190601f1680156114a15780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156114c157600080fd5b505af19250505080156114d2575060015b6113e4576040516000815260443d10156114ee57506000611589565b60046000803e60005160e01c6308c379a0811461150f576000915050611589565b60043d036004833e81513d60248201116001600160401b038211171561153a57600092505050611589565b80830180516001600160401b0381111561155b576000945050505050611589565b8060208301013d860181111561157957600095505050505050611589565b601f01601f191660405250925050505b8061159457506115f9565b60408051602080825283518183015283516001600160a01b038616937ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf93869390928392830191850190808383600083156111f75781810151838201526020016111df565b3d808015611623576040519150601f19603f3d011682016040523d82523d6000602084013e611628565b606091505b5060408051602080825283518183015283516001600160a01b038616937f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351938693909283928301918501908083836000831561133457818101518382015260200161131c565b60ff8316600214156119b85760ff8516600081815260056020908152604080832054815163c8509d8160e01b815260048101958652602481019283528651604482015286516001600160a01b0390921695869563c8509d81958d958a9593949093606490910192918601918190849084905b83811015611718578181015183820152602001611700565b50505050905090810190601f1680156117455780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b15801561176557600080fd5b505af1925050508015611776575060015b6119b6576040516000815260443d10156117925750600061182d565b60046000803e60005160e01c6308c379a081146117b357600091505061182d565b60043d036004833e81513d60248201116001600160401b03821117156117de5760009250505061182d565b80830180516001600160401b038111156117ff57600094505050505061182d565b8060208301013d860181111561181d5760009550505050505061182d565b601f01601f191660405250925050505b8061183857506118e1565b816001600160a01b03167ff91a8f63e5b3e0e89e5f93e1915a7805f3c52d9a73b3c09769785c2c7bf87acf826040518080602001828103825283818151815260200191508051906020019080838360005b838110156118a1578181015183820152602001611889565b50505050905090810190601f1680156118ce5780820380516001836020036101000a031916815260200191505b509250505060405180910390a2506119b6565b3d80801561190b576040519150601f19603f3d011682016040523d82523d6000602084013e611910565b606091505b50816001600160a01b03167f63ac299d6332d1cc4e61b81e59bc00c0ac7c798addadf33840f1307cd2977351826040518080602001828103825283818151815260200191508051906020019080838360005b8381101561197a578181015183820152602001611962565b50505050905090810190601f1680156119a75780820380516001836020036101000a031916815260200191505b509250505060405180910390a2505b505b60ff80861660009081526009602052604090205461100591636f93d2e69189913391879116806119ea575060ff881615155b604080516001600160e01b031960e088901b1681526001600160a01b039586166004820152939094166024840152604483019190915215156064820152905160848083019260209291908290030181600087803b158015611a4a57600080fd5b505af1158015611a5e573d6000803e3d6000fd5b505050506040513d6020811015611a7457600080fd5b505050505050505050505b505050505050505050505050565b630100380081565b600981565b61100781565b61100681565b60005460ff1681565b3361100714611aef5760405162461bcd60e51b815260040180806020018281038252602e815260200180612b22602e913960400191505060405180910390fd5b611b5884848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526012815271626174636853697a65466f724f7261636c6560701b602082015291506129809050565b15611bf357604080516020601f8401819004810282018101909252828152600091611b9b91858580838501838280828437600092019190915250612a6792505050565b90506127108111158015611bb05750600a8110155b611beb5760405162461bcd60e51b8152600401808060200182810382526032815260200180612b9a6032913960400191505060405180910390fd5b600155611fbf565b611c5c84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601281527118591913dc955c19185d1950da185b9b995b60721b602082015291506129809050565b15611de457606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060169091149050611cdf5760405162461bcd60e51b815260040180806020018281038252605a815260200180612ac8605a913960600191505060405180910390fd5b60018101516002820151601683015160ff82161590611cfd81612a6c565b611d4e576040805162461bcd60e51b815260206004820152601960248201527f61646472657373206973206e6f74206120636f6e747261637400000000000000604482015290519081900360640190fd5b60ff8416600081815260056020908152604080832080546001600160a01b0319166001600160a01b038716908117909155808452600683528184208585528352818420805460ff199081166001179091556009909352818420805490931687151517909255519092917f7e3b6af43092577ee20e60eaa1d9b114a7031305c895ee7dd3ffe17196d2e1e091a35050505050611fbf565b611e5184848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526016815275195b98589b1953dc911a5cd8589b1950da185b9b995b60521b602082015291506129809050565b15611f8257606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060029091149050611ed45760405162461bcd60e51b815260040180806020018281038252604a815260200180612b50604a913960600191505060405180910390fd5b600181810151600283015160ff80831660009081526005602052604090205492939192908316909114906001600160a01b03168015611f78576001600160a01b038116600090815260066020908152604080832060ff881680855290835292819020805460ff1916861515908117909155815190815290517fa3132e3f9819fbddc7f0ed6d38d7feef59aa95112090b7c592f5cb5bc4aa4adc929181900390910190a25b5050505050611fbf565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b6008602052600090815260409020546001600160401b031681565b61100281565b600660209081526000928352604080842090915290825290205460ff1681565b6040518060400160405280600381526020016269626360e81b81525081565b61100381565b60005460ff161561210f576040805162461bcd60e51b815260206004820152601960248201527f74686520636f6e747261637420616c726561647920696e697400000000000000604482015290519081900360640190fd5b7f1471eb6eb2c5e789fc3de43f8ce62938c7d1836ec861730447e2ada8fd81017b80546001600160a01b0319908116611008179091557f92e85d02570a8092d09a6e3a57665bc3815a2699a4074001bf1ccabf660f5a36805460ff199081169091557fd8af288fc1c8680b4f4706064cf021e264efb6828fcaf7eb5ca36818eb365bcc8054821660019081179091557f89832631fb3c3307a103ba2c84ab569c64d6182a18893dcd163f0f1c2090733a805484166110049081179091557f6cde3cea4b3a3fb2488b2808bae7556f4a405e50f65e1794383bc026131b13c38054841690557f72e4efa1513b071517c6c74dba31b5934a81aa83cddd400e7081df5529c9943680548416831790557fa9bc9a3a348c357ba16b37005d7e6b3236198c0e939f4af8c5f19b8deeb8ebc08054851690911790557fc575c31fea594a6eb97c8e9d3f9caee4c16218c6ef37e923234c0fe9014a61e78054831690557f4e523af77f034e9810f1c94057f5e931fb3d16a51511a4c3add793617d18610580548316821790557ffb33122aa9f93cc639ebe80a7bc4784c11e6053dde89c6f4f7e268c6a623da1e805484166110001790557fc7694af312c4f286114180fd0ba6a52461fcee8a381636770b19a343af92538a80548316821790557f01112dd68e482ba8d68a7e828cff8b3abcea08eab88941953c180a7e650e9cd480548316821790557fc0a4a8be475dfebc377ebef2d7c4ff47656f572a08dd92b81017efcdba0febe1805484166110071790557f87e8a52529e8ece4ef759037313542a6429ff494a9fab9027fb79db90124eba680548316821790557f4c7666bbcb22d46469f7cc282f70764a7012dca2cce630ff8d83db9a9cdd48f080548316821790557f40f28f99a40bc9f6beea1013afdbc3cdcc689eb76b82c4de06c0acf1e1932ed58054909316611001179092557f0d9cf2cd531699eed8dd34e40ff2884a14a698c4898184fba85194e6f6772d248054821683179055600b60009081527f23f68c9bd22b8a93d06adabe17481c87c016bcbd20adc8bfd707a4d813a572176020527fdf0d5d05428057f5455c2dc8e810dd86d1e9350faa72f16bda8a45443c5b39328054831684179055603283556004805467ffffffffffffffff19166001600160401b031790556002819055600381905580549091169091179055565b6007602052600090815260409020546001600160401b031681565b60005460ff166124dc576040805162461bcd60e51b81526020600482015260196024820152781d1a194818dbdb9d1c9858dd081b9bdd081a5b9a5d081e595d603a1b604482015290519081900360640190fd5b33600090815260066020908152604080832060ff80891685529252909120548591166125395760405162461bcd60e51b8152600401808060200182810382526031815260200180612a976031913960400191505060405180910390fd5b60ff85166000908152600760209081526040808320548151601f88018490048402810184019092528682526001600160401b03169261259e9284928a9261115792909189918c908c908190840183828082843760009201919091525061080092505050565b60ff959095166000908152600760205260409020805467ffffffffffffffff191660019096016001600160401b03169590951790945550505050565b61100081565b600381565b61100481565b8051602090910191565b5b60208110612615578251825260209283019290910190601f19016125f6565b915181516020939093036101000a6000190180199091169216919091179052565b60408051600e808252818301909252606091630100380060ff851617918391602082018180368337505050600e818101969096526006810192909252509283525090919050565b60008561268c57506000612771565b606082518451865160800101016040519080825280601f01601f1916602001820160405280156126c3576020820181803683370190505b50905060006126d182612a72565b6020808901518252019050866000806126e9896125eb565b80865260209095019490925090506127028285836125f5565b9283019261270f886125eb565b80865260209095019490925090506127288285836125f5565b9283018a81526020019261273b876125eb565b909250905061274b8285836125f5565b508351602001612759612a78565b60208183886065600019fa5051600114955050505050505b95945050505050565b600080600060606021855110156127aa575050604080516000808252602082019092529092508291508190612823565b600185015160218601518651604080516020198301808252601f19600119909401939093168101602001909152604189019392916060919080156127f5576020820181803683370190505b5090506000612803826125eb565b509050612815858260218d51036125f5565b506001975091955093509150505b9193509193565b600254431115612869576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b1617909155600355436002556128aa565b600380546001908101918290555410156128aa576004805467ffffffffffffffff1981166001600160401b036001600793840b810190930b16179091556003555b8160ff16836001600160401b0316600460009054906101000a900460070b6001600160401b03167f3a6e0fc61675aa2a100bcba0568368bb92bcec91c97673391074f11138f0cffe603885604051808361ffff1661ffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015612940578181015183820152602001612928565b50505050905090810190601f16801561296d5780820380516001836020036101000a031916815260200191505b50935050505060405180910390a4505050565b6000816040516020018082805190602001908083835b602083106129b55780518252601f199092019160209182019101612996565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310612a235780518252601f199092019160209182019101612a04565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012014905092915050565b015190565b3b151590565b60200190565b6040518060200160405280600190602082028036833750919291505056fe74686520636f6e747261637420616e64206368616e6e656c2068617665206e6f74206265656e20726567697374657265646c656e677468206f662076616c756520666f72206164644f725570646174654368616e6e656c2073686f756c642062652032322c206368616e6e656c49643a697346726f6d53797374656d3a68616e646c657241646472657373746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f7220656e61626c654f7244697361626c654368616e6e656c2073686f756c6420626520322c206368616e6e656c49643a6973456e61626c65746865206e6577426174636853697a65466f724f7261636c652073686f756c6420626520696e205b31302c2031303030305d6c6967687420636c69656e74206e6f742073796e632074686520626c6f636b20796574a264697066735822122083f6194f9a326fa5963aa39ffe11dcd28d1421a9f74fbe97a97f4853026e29ff64736f6c63430006040033" }, "9fB29AAc15b9A4B7F17c3385939b007540f4d791": { "balance": "0x21e19e0c9bab2400000" diff --git a/hardhat.config.ts b/hardhat.config.ts new file mode 100644 index 00000000..8133d6ce --- /dev/null +++ b/hardhat.config.ts @@ -0,0 +1,66 @@ +import '@typechain/hardhat'; +import 'hardhat-watcher' +import 'hardhat-gas-reporter'; +import '@nomiclabs/hardhat-ethers'; +import '@nomiclabs/hardhat-waffle'; + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +export default { + solidity: { + compilers: [ + { + version: "0.6.4", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + }, + ] + }, + networks: { + hardhat: { + accounts: { + mnemonic: "clock radar mass judge dismiss just intact mind resemble fringe diary casino", + count: 100 + }, + allowUnlimitedContractSize: true, + }, + development: { + url: "http://127.0.0.1:8545", // Localhost (default: none) + accounts: { + mnemonic: "clock radar mass judge dismiss just intact mind resemble fringe diary casino", + count: 100 + } + }, + 'bsc': { + url: "https://bsc-dataseed1.ninicoin.io", + accounts: { + mnemonic: "clock radar mass judge dismiss just intact mind resemble fringe diary casino", + } + } + }, + watcher: { + compilation: { + tasks: ["compile"], + files: ["./contracts"], + verbose: true, + } + }, + mocha: { + timeout: 2000000 + }, + paths: { + sources: "./contracts", + tests: "./test/test-maintenance", + cache: "./cache", + artifacts: "./artifacts" + }, + gasReporter: { + enabled: (process.env.REPORT_GAS) ? true : false + } +}; + diff --git a/package.json b/package.json index e632cc37..774e099e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,9 @@ "lint:js": "eslint test/**/*.js", "lint:sol:fix": "solium -d contracts/ --fix", "lint:sol": "solium -d contracts/", + "prettier:write": "prettier --write 'test/test-maintenance/**.ts'", "flatten": "truffle-flattener contracts/BSCValidatorSet.sol > contracts/flattened/BSCValidatorSet.sol && truffle-flattener contracts/GovHub.sol > contracts/flattened/GovHub.sol && truffle-flattener contracts/RelayerHub.sol > contracts/flattened/RelayerHub.sol && truffle-flattener contracts/RelayerIncentivize.sol > contracts/flattened/RelayerIncentivize.sol && truffle-flattener contracts/SlashIndicator.sol > contracts/flattened/SlashIndicator.sol && truffle-flattener contracts/SystemReward.sol > contracts/flattened/SystemReward.sol && truffle-flattener contracts/TendermintLightClient.sol > contracts/flattened/TendermintLightClient.sol && truffle-flattener contracts/TokenHub.sol > contracts/flattened/TokenHub.sol && truffle-flattener contracts/CrossChain.sol > contracts/flattened/CrossChain.sol && truffle-flattener contracts/TokenManager.sol > contracts/flattened/TokenManager.sol", + "generate-QA": "node generate-genesis.js --chainid 714 --bscChainId 02ca --initBurnRatio 1000 --initConsensusStateBytes 42696e616e63652d436861696e2d47616e67657300000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000aea1ac326886b992a991d21a6eb155f41b77867cbf659e78f31d89d8205122a84d1be64f0e9a466c2e66a53433928192783e29f8fa21beb2133499b5ef770f60000000e8d4a5100099308aa365c40554bc89982af505d85da95251445d5dd4a9bb37dd2584fd92d3000000e8d4a5100001776920ff0b0f38d78cf95c033c21adf7045785114e392a7544179652e0a612000000e8d4a51000 --initValidatorSetBytes f901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a78410000000", "generate-test": "node generate-system.js --mock true && node generate-systemReward.js --mock true && node generate-validatorset.js --mock true && node generate-system.js --mock true && node generate-crosschain.js --mock true && node generate-tokenhub.js --mock true && node generate-tendermintlightclient.js --mock true && node generate-relayerincentivizecontract.js --roundSize 30 --maximumWeight 3 --mock true && node generate-slash.js --mock true", "generate-mainnet": "node generate-genesis.js --chainid 56 --bscChainId 0038 --initBurnRatio 1000 --initConsensusStateBytes 42696e616e63652d436861696e2d5469677269730000000000000000000000000000000006915167cedaf7bbf7df47d932fdda630527ee648562cf3e52c5e5f46156a3a971a4ceb443c53a50d8653ef8cf1e5716da68120fb51b636dc6d111ec3277b098ecd42d49d3769d8a1f78b4c17a965f7a30d4181fabbd1f969f46d3c8e83b5ad4845421d8000000e8d4a510002ba4e81542f437b7ae1f8a35ddb233c789a8dc22734377d9b6d63af1ca403b61000000e8d4a51000df8da8c5abfdb38595391308bb71e5a1e0aabdc1d0cf38315d50d6be939b2606000000e8d4a51000b6619edca4143484800281d698b70c935e9152ad57b31d85c05f2f79f64b39f3000000e8d4a510009446d14ad86c8d2d74780b0847110001a1c2e252eedfea4753ebbbfce3a22f52000000e8d4a510000353c639f80cc8015944436dab1032245d44f912edc31ef668ff9f4a45cd0599000000e8d4a51000e81d3797e0544c3a718e1f05f0fb782212e248e784c1a851be87e77ae0db230e000000e8d4a510005e3fcda30bd19d45c4b73688da35e7da1fce7c6859b2c1f20ed5202d24144e3e000000e8d4a51000b06a59a2d75bf5d014fce7c999b5e71e7a960870f725847d4ba3235baeaa08ef000000e8d4a510000c910e2fe650e4e01406b3310b489fb60a84bc3ff5c5bee3a56d5898b6a8af32000000e8d4a5100071f2d7b8ec1c8b99a653429b0118cd201f794f409d0fea4d65b1b662f2b00063000000e8d4a51000 --initValidatorSetBytes f905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a2000", "generate-testnet": "node generate-genesis.js --chainid 97 --bscChainId 0061 --initBurnRatio 1000 --initConsensusStateBytes 42696e616e63652d436861696e2d47616e67657300000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000aea1ac326886b992a991d21a6eb155f41b77867cbf659e78f31d89d8205122a84d1be64f0e9a466c2e66a53433928192783e29f8fa21beb2133499b5ef770f60000000e8d4a5100099308aa365c40554bc89982af505d85da95251445d5dd4a9bb37dd2584fd92d3000000e8d4a5100001776920ff0b0f38d78cf95c033c21adf7045785114e392a7544179652e0a612000000e8d4a51000 --initValidatorSetBytes f901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a78410000000" @@ -22,20 +24,46 @@ "author": "", "license": "MIT", "dependencies": { + "@openzeppelin/contracts": "^4.3.1", + "@openzeppelin/contracts-upgradeable": "^4.3.1", + "await-sleep": "0.0.1", "commander": "^3.0.1", + "elliptic": ">=6.5.3", + "ethereum-input-data-decoder": "0.3.0", + "lodash": ">=4.17.19", + "mem": ">=4.0.0", + "minimist": ">=1.2.3", "nunjucks": "^3.2.0", "openzeppelin-solidity": "v3.0.0-rc.0", + "rlp": "^2.2.7", "solidity-bytes-utils": "0.0.8", "solium": "^1.2.5", "truffle-assertions": "0.9.2", "truffle-flattener": "1.4.4", - "web3": "1.3.1", - "await-sleep": "0.0.1", - "ethereum-input-data-decoder": "0.3.0", - "rlp": "2.2.5", - "elliptic": ">=6.5.3", - "minimist": ">=1.2.3", - "mem": ">=4.0.0", - "lodash": ">=4.17.19" + "web3": "^1.7.0" + }, + "devDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.4", + "@nomiclabs/hardhat-etherscan": "^3.0.0", + "@nomiclabs/hardhat-waffle": "^2.0.2", + "@typechain/ethers-v5": "^9.0.0", + "@typechain/hardhat": "^4.0.0", + "@types/chai": "^4.3.0", + "@types/mocha": "^9.1.0", + "chai": "^4.3.4", + "decimal.js": "^10.3.1", + "ethereum-waffle": "^3.4.0", + "ethers": "^5.5.3", + "hardhat": "^2.8.3", + "hardhat-gas-reporter": "^1.0.7", + "hardhat-watcher": "^2.1.1", + "mocha": "^9.1.4", + "mocha-chai-jest-snapshot": "^1.1.3", + "prettier": "^2.5.1", + "truffle": "5.1.14", + "ts-generator": "^0.1.1", + "ts-node": "^10.4.0", + "typechain": "^7.0.0", + "typescript": "^4.5.5" } } diff --git a/test/BSCValidatorSet.js b/test/BSCValidatorSet.js index aed19f04..8769ecdf 100644 --- a/test/BSCValidatorSet.js +++ b/test/BSCValidatorSet.js @@ -600,6 +600,136 @@ contract('BSCValidatorSet', (accounts) => { }); }); +contract('BSCValidatorSet', (accounts) => { + it('test set maxNumOfWorkingCandidates greater than maxNumOfCandidates', async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + const relayer = accounts[2]; + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({from: relayer, value: 1e20}); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + + // should fail + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; + govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(0)), true, "wrong maxNumOfWorkingCandidates"); + }); +}); + +contract('BSCValidatorSet', (accounts) => { + it('test set maxNumOfCandidates less than maxNumOfWorkingCandidates', async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + const relayer = accounts[2]; + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({from: relayer, value: 1e20}); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + + // set maxNumOfCandidates to 20 + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; + govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + except = await validatorSetInstance.maxNumOfCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); + + // set maxNumOfWorkingCandidates to 10 + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x000000000000000000000000000000000000000000000000000000000000000A";// 10; + govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(10)), true, "wrong maxNumOfWorkingCandidates"); + + // set maxNumOfCandidates to 5 + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000005";// 5; + govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + except = await validatorSetInstance.maxNumOfCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(5)), true, "wrong maxNumOfCandidates"); + except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(5)), true, "wrong maxNumOfWorkingCandidates"); + }); +}); + +contract('BSCValidatorSet', (accounts) => { + it('test getMiningValidators with 41 validators', async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + const relayer = accounts[2]; + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({from: relayer, value: 1e20}); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + + let relayerAccount = accounts[8]; + let newValidators = []; + for (let i = 0; i < 41; i++) { + newValidators.push(web3.eth.accounts.create().address) + } + let packageBytes = validatorUpdateRlpEncode(newValidators, + newValidators, newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); + + // set numOfCabinets to 21 + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000015";// 21; + let govPackageBytes = serializeGovPack("numOfCabinets", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + let except = await validatorSetInstance.numOfCabinets.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(21)), true, "wrong numOfCabinets"); + + // without candidate validators + let maxNumOfWorkingCandidates = 2; + let numOfCabinets = 21; + let validators = await validatorSetInstance.getValidators.call(); + let miningValidators = await validatorSetInstance.getMiningValidators.call(); + assert.deepEqual(validators.slice(0,numOfCabinets), miningValidators, "wrong validators"); + + // set maxNumOfCandidates to 20 + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; + govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + except = await validatorSetInstance.maxNumOfCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); + + // set maxNumOfWorkingCandidates to 2 + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; + govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(2)), true, "wrong maxNumOfWorkingCandidates"); + + if ((validators.length - numOfCabinets) < maxNumOfWorkingCandidates){ + maxNumOfWorkingCandidates = validators.length - numOfCabinets; + } + + miningValidators = await validatorSetInstance.getMiningValidators.call(); + let exceptValues = validators.slice(0,numOfCabinets); + let outValidator = miningValidators.filter((addr)=>{ + return !exceptValues.includes(addr); + }); + // TODO, this is not always true, but as the epoch number is fixed during UT, the result is fixed. + assert(outValidator.length > 0, "no validator choose from candidates"); + assert(outValidator.length <= maxNumOfWorkingCandidates, "too many working candidates" ) + + }); +}); + function jailRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) { let pkg = []; pkg.push(0x01); diff --git a/test/Slash.js b/test/Slash.js index 340009fe..a1a6342b 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -11,67 +11,77 @@ const STAKE_CHANNEL_ID = 0x08; contract('SlashIndicator', (accounts) => { it('slash success', async () => { const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); + const accountOne = accounts[0]; - - let validatorAccount = web3.eth.accounts.create(); + + let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccount = validatorAccounts[0]; + for (let i =1; i<10; i++){ - await slashInstance.slash(validatorAccount.address, { from: accountOne }); - let res= (await slashInstance.getSlashIndicator.call(validatorAccount.address)); + await slashInstance.slash(validatorAccount, { from: accountOne }); + let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); let count =res[1].toNumber(); assert.equal(count, i, "slash num is not correct"); } }); - + it('slash from no system account', async () => { const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); const nonSystemAccount = accounts[1]; - let validatorAccount = web3.eth.accounts.create(); - + let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccount = validatorAccounts[0]; // first slash try{ - await slashInstance.slash(validatorAccount.address, { from: nonSystemAccount }); + await slashInstance.slash(validatorAccount, { from: nonSystemAccount }); assert.fail(); }catch (error) { assert.ok(error.toString().includes("the message sender must be the block producer"), "slash from no system account should not be ok"); } }); +}); - it('catch emit event', async () => { - const slashInstance = await SlashIndicator.deployed(); - - const accountOne = accounts[0]; - let validatorAccount = web3.eth.accounts.create(); - for (let i =1; i<50; i++){ - let tx = await slashInstance.slash(validatorAccount.address, { from: accountOne }); - truffleAssert.eventEmitted(tx, "validatorSlashed",(ev) => { - return ev.validator === validatorAccount.address; - }); - } - }); - - +contract('SlashIndicator: isOperator works', (accounts) => { it('isOperator works', async () => { const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); const accountOne = accounts[0]; - let validatorAccount1 = web3.eth.accounts.create(); - let validatorAccount2 = web3.eth.accounts.create(); + let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccount = validatorAccounts[0]; // slash afterward for (let i =1; i<10; i++){ - await slashInstance.slash(validatorAccount1.address, { from: accountOne }); - let res= (await slashInstance.getSlashIndicator.call(validatorAccount1.address)); + await slashInstance.slash(validatorAccount, { from: accountOne }); + let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); let count =res[1].toNumber(); - assert.equal(count, i, "slash num is not correct for validator 1"); - - await slashInstance.slash(validatorAccount2.address, { from: accountOne }); - res= (await slashInstance.getSlashIndicator.call(validatorAccount2.address)); - count =res[1].toNumber(); - assert.equal(count, i, "slash num is not correct for validator 2"); + assert.equal(count, i, "slash num is not correct for validator"); } }); +}); + +contract('SlashIndicator: catch emit event', (accounts) => { + it('catch emit event', async () => { + const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); + + const accountOne = accounts[0]; + let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccount = validatorAccounts[0]; + for (let i =1; i<50; i++){ + let tx = await slashInstance.slash(validatorAccount, { from: accountOne }); + truffleAssert.eventEmitted(tx, "validatorSlashed",(ev) => { + return ev.validator === validatorAccount; + }); + } + }); +}); + + +contract('SlashIndicator', (accounts) => { it('trigger misdemeanor', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); @@ -113,7 +123,6 @@ contract('SlashIndicator', (accounts) => { assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) amount = await validatorSetInstance.getIncoming.call(thirdValidator); assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) - await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 1e18 }); @@ -144,7 +153,6 @@ contract('SlashIndicator', (accounts) => { assert.equal(amount.toNumber(),0); }); - }); contract('felony SlashIndicator', (accounts) => { @@ -163,23 +171,23 @@ contract('felony SlashIndicator', (accounts) => { await validatorSetInstance.deposit(validator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case1: incoming of account1 is wrong") for (let i =1; i<=150; i++){ await slashInstance.slash(validator, { from: systemAccount }); } let res= (await slashInstance.getSlashIndicator.call(validator)); - assert.equal(res[1].toNumber(),0); + assert.equal(res[1].toNumber(),0, "case1: slash indicator of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(),0, "case1: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); - let consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length,2); - assert.equal(consensusAddres[0],thirdValidator); - assert.equal(consensusAddres[1],secondValidator); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account3 is wrong"); + let consensusAddress = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddress.length,2, "case1: length of validators should be 2"); + assert.equal(consensusAddress[0],secondValidator, "case1: index 0 of validators should be account2"); + assert.equal(consensusAddress[1],thirdValidator, "case1: index 1 of validators should be account3"); packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); @@ -187,23 +195,23 @@ contract('felony SlashIndicator', (accounts) => { await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case2: incoming of account2 is wrong") for (let i =1; i<=150; i++){ await slashInstance.slash(secondValidator, { from: systemAccount }); } res= (await slashInstance.getSlashIndicator.call(secondValidator)); - assert.equal(res[1].toNumber(),0); + assert.equal(res[1].toNumber(),0, "case2: slash indicator of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(),0, "case2: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); - consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length,2); - assert.equal(consensusAddres[0],validator); - assert.equal(consensusAddres[1],thirdValidator); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account3 is wrong"); + consensusAddress = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddress.length,2, "case2: length of validators should be 2"); + assert.equal(consensusAddress[0],validator, "case2: index 0 of validators should be account1"); + assert.equal(consensusAddress[1],thirdValidator, "case2: index 1 of validators should be account3"); packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); @@ -211,23 +219,23 @@ contract('felony SlashIndicator', (accounts) => { await validatorSetInstance.deposit(thirdValidator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case3: incoming of account3 is wrong") for (let i =1; i<=150; i++){ await slashInstance.slash(thirdValidator, { from: systemAccount }); } res= (await slashInstance.getSlashIndicator.call(thirdValidator)); - assert.equal(res[1].toNumber(),0); + assert.equal(res[1].toNumber(),0, "case3: slash indicator of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(),0, "case3: incoming of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()); - consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length,2); - assert.equal(consensusAddres[0],validator); - assert.equal(consensusAddres[1],secondValidator); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account2 is wrong"); + consensusAddress = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddress.length,2, "case3: length of validators should be 2"); + assert.equal(consensusAddress[0],validator, "case3: index 0 of validators should be account1"); + assert.equal(consensusAddress[1],secondValidator, "case3: index 0 of validators should be account2"); }); }); @@ -245,12 +253,16 @@ contract('Clean SlashIndicator', (accounts) => { for(let i =0;i <20; i++){ validators.push(web3.eth.accounts.create().address); } + // Do init + let packageBytes = validatorUpdateRlpEncode(validators, + validators,validators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + for(let i =0;i <20;i++){ await slashInstance.slash(validators[i], { from: accountOne }); } + // doclean - let packageBytes = validatorUpdateRlpEncode([newValidator.address], - [newValidator.address],[newValidator.address]); await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); let res= (await slashInstance.getSlashValidators.call()); @@ -271,8 +283,6 @@ contract('Clean SlashIndicator', (accounts) => { } } // doclean - packageBytes = validatorUpdateRlpEncode([newValidator.address], - [newValidator.address],[newValidator.address]); await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 20); @@ -290,8 +300,6 @@ contract('Clean SlashIndicator', (accounts) => { await slashInstance.slash(validators[2*i+1], { from: accountOne }); } // doclean - packageBytes = validatorUpdateRlpEncode([newValidator.address], - [newValidator.address],[newValidator.address]); await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 10); @@ -313,8 +321,6 @@ contract('Clean SlashIndicator', (accounts) => { await slashInstance.slash(validators[2*i], { from: accountOne }); } // doclean - packageBytes = validatorUpdateRlpEncode([newValidator.address], - [newValidator.address],[newValidator.address]); await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 10); diff --git a/test/test-maintenance/BSCValidatorSet.spec.ts b/test/test-maintenance/BSCValidatorSet.spec.ts new file mode 100644 index 00000000..0c9fc134 --- /dev/null +++ b/test/test-maintenance/BSCValidatorSet.spec.ts @@ -0,0 +1,784 @@ +import { BigNumber, Contract } from 'ethers'; +import { ethers } from 'hardhat'; +import { expect } from 'chai'; +import { + deployContract, + waitTx, + setSlashIndicator, + validatorUpdateRlpEncode, + buildSyncPackagePrefix, + serializeGovPack, + mineBlocks, +} from './helper'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import web3 from 'web3'; +import { + BSCValidatorSet, + SlashIndicator, + CrossChain, + GovHub, + RelayerHub, + RelayerIncentivize, + SystemReward, + TendermintLightClient, +} from '../../typechain-types'; + +const log = console.log; +const STAKE_CHANNEL_ID = 0x08; +const GOV_CHANNEL_ID = 0x09; +const proof = Buffer.from(web3.utils.hexToBytes('0x00')); +const merkleHeight = 100; + +const deployContractAndInit = async ( + deployer: SignerWithAddress, + factoryPath: string, + needInit?: boolean +): Promise => { + const instance = await deployContract(deployer, factoryPath); + if (needInit) { + await (await instance.init()).wait(1); + } + return instance; +}; + +describe('BSCValidatorSet', () => { + const unit = ethers.constants.WeiPerEther; + let instances: any[]; + + let relayerIncentivize: RelayerIncentivize; + let tendermintLightClient: TendermintLightClient; + let validatorSet: BSCValidatorSet; + let systemReward: SystemReward; + let slashIndicator: SlashIndicator; + let crosschain: CrossChain; + let relayerHub: RelayerHub; + let govHub: GovHub; + + let operator: SignerWithAddress; + let validators: string[]; + let relayerAccount: string; + let signers: SignerWithAddress[]; + + let maxNumOfMaintaining: number; + let maintainSlashScale: number; + before('before', async () => { + signers = await ethers.getSigners(); + log(signers.length); + operator = signers[0]; + relayerAccount = signers[1].address; + validators = signers.slice(0, 100).map((signer) => signer.address); + + const contractPaths = [ + { + name: 'RelayerIncentivize', // 0 + needInit: true, + needUpdate: true, + }, + { + name: 'TendermintLightClient', // 1 + needInit: true, + needUpdate: true, + }, + { + name: 'CrossChain', // 2 + needInit: false, + needUpdate: true, + }, + { + name: 'SystemReward', // 3 + needInit: false, + needUpdate: false, + }, + { + name: 'MockLightClient', // 4 + needInit: false, + needUpdate: false, + }, + { + name: 'TokenHub', // 5 + needInit: true, + needUpdate: true, + }, + { + name: 'TokenManager', // 6 + needInit: false, + needUpdate: true, + }, + { + name: 'RelayerHub', // 7 + needInit: true, + needUpdate: true, + }, + { + name: 'SlashIndicator', // 8 + needInit: true, + needUpdate: true, + }, + { + name: 'GovHub', // 9 + needInit: false, + needUpdate: true, + }, + { + name: 'BSCValidatorSet', // 10 + needInit: true, + needUpdate: true, + }, + ]; + instances = []; + for (let i = 0; i < contractPaths.length; i++) { + const pathObj = contractPaths[i]; + instances.push(await deployContractAndInit(operator, pathObj.name, pathObj.needInit)); + } + + for (let i = 0; i < contractPaths.length; i++) { + const pathObj = contractPaths[i]; + const instance = instances[i]; + + if (!pathObj.needUpdate) { + continue; + } + + let crosschainAddress = instances[2].address; + if (pathObj.name === 'BSCValidatorSet' || pathObj.name === 'GovHub') { + crosschainAddress = operator.address; + } + + await waitTx( + instance.updateContractAddr( + instances[10].address, + instances[8].address, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + crosschainAddress + ) + ); + } + + relayerIncentivize = instances[0]; + tendermintLightClient = instances[1]; + + systemReward = instances[3] as SystemReward; + slashIndicator = instances[8] as SlashIndicator; + await waitTx(systemReward.addOperator(operator.address)); + await waitTx(systemReward.addOperator(tendermintLightClient.address)); + await waitTx(systemReward.addOperator(relayerIncentivize.address)); + + validatorSet = instances[10] as BSCValidatorSet; + relayerHub = instances[7] as RelayerHub; + + crosschain = instances[2] as CrossChain; + await waitTx(crosschain.init()); + + govHub = instances[9] as GovHub; + }); + + beforeEach('beforeEach', async () => {}); + + it('query code size', async () => { + const code = await ethers.provider.getCode(validatorSet.address) + const codeSize = (code.length - 2) / 2 + log(`BSCValidatorSet Mock Template code size: ${codeSize}, UpperLimit: 24567` ) + }); + + it('update validators', async () => { + // do update validators + let packageBytes = validatorUpdateRlpEncode( + validators.slice(1, 22), + validators.slice(1, 22), + validators.slice(1, 22) + ); + + await waitTx(validatorSet.connect(operator).handleSynPackage(STAKE_CHANNEL_ID, packageBytes)); + }); + + it('query all view func', async () => { + expect(await validatorSet.getValidators()).to.deep.eq(validators.slice(1, 22)); + for (let i = 1; i < 50; i++) { + const currentValidatorSetIndex = i - 1 + if (i >= 1 && i < 22) { + expect(await validatorSet.isWorkingValidator(currentValidatorSetIndex)).to.deep.eq(true); + expect(await validatorSet.isCurrentValidator(validators[i])).to.deep.eq(true); + expect(await validatorSet.canEnterMaintenance(validators[i])).to.deep.eq(false); + } else { + expect(await validatorSet.isWorkingValidator(currentValidatorSetIndex)).to.be.eq(false); + expect(await validatorSet.isCurrentValidator(validators[i])).to.deep.eq(false); + expect(await validatorSet.canEnterMaintenance(validators[i])).to.deep.eq(false); + } + expect(await validatorSet.getIncoming(validators[i])).to.deep.eq(0); + } + + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + + }); + + it('common case 1-1 update params', async () => { + await waitTx(relayerHub.connect(operator).register({ value: unit.mul(100) })); + await waitTx( + govHub.updateContractAddr( + instances[10].address, + instances[8].address, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + instances[2].address + ) + ); + + // set maxNumOfMaintaining to 5 + let govChannelSeq = await crosschain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + maxNumOfMaintaining = 5; + let govValue = '0x0000000000000000000000000000000000000000000000000000000000000005'; // 5; + let govPackageBytes = serializeGovPack('maxNumOfMaintaining', govValue, validatorSet.address); + await crosschain + .connect(operator) + .handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID + ); + expect(await validatorSet.maxNumOfMaintaining()).to.be.eq(BigNumber.from(govValue)); + + // set maintainSlashScale to 2 + govChannelSeq = await crosschain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + maintainSlashScale = 2; + govValue = '0x0000000000000000000000000000000000000000000000000000000000000002'; // 2; + govPackageBytes = serializeGovPack('maintainSlashScale', govValue, validatorSet.address); + await crosschain + .connect(operator) + .handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID + ); + expect(await validatorSet.maintainSlashScale()).to.be.eq(BigNumber.from(govValue)); + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + }); + + it('common case 1-2: validator-1 enterMaintenance', async () => { + await waitTx(validatorSet.connect(signers[1]).enterMaintenance()); + const maintainingValidators = await validatorSet.getMaintainingValidators() + expect(maintainingValidators).to.deep.eq([validators[1]]); + }); + + it('common case 1-3: validator-2 enterMaintenance', async () => { + await waitTx(validatorSet.connect(signers[2]).enterMaintenance()); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[2], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(2); + }); + + it('common case 1-4: validator-3 misdemeanor, enterMaintenance', async () => { + await setSlashIndicator(operator.address, validatorSet, instances); + + await validatorSet.connect(operator).misdemeanor(validators[3]); + + const index = await validatorSet.getCurrentValidatorIndex(validators[3]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[2], + validators[3], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(3); + }); + + it('common case 1-5: validator-2 exitMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[2]).exitMaintenance()); + const index = await validatorSet.getCurrentValidatorIndex(validators[2]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[3], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(2); + }); + + it('common case 1-6: validator-4 misdemeanor, enterMaintenance', async () => { + await setSlashIndicator(operator.address, validatorSet, instances); + + await validatorSet.connect(operator).misdemeanor(validators[4]); + const index = await validatorSet.getCurrentValidatorIndex(validators[4]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[3], + validators[4], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(3); + }); + + it('common case 1-7: validator-5 misdemeanor, enterMaintenance', async () => { + await validatorSet.connect(operator).misdemeanor(validators[5]); + const index = await validatorSet.getCurrentValidatorIndex(validators[5]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[3], + validators[4], + validators[5], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + + }); + + it('common case 1-8: validator-6 enterMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[6]).enterMaintenance()); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[3], + validators[4], + validators[5], + validators[6], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + + }); + + it('common case 1-9: validator-7 enterMaintenance failed!', async () => { + expect(validatorSet.connect(signers[7]).enterMaintenance()).to.be.revertedWith( + 'can not enter Temporary Maintenance' + ); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + }); + + it('common case 1-10: validator-7 misdemeanor, enterMaintenance failed!', async () => { + await setSlashIndicator(operator.address, validatorSet, instances); + + await validatorSet.connect(operator).misdemeanor(validators[7]); + const index = await validatorSet.getCurrentValidatorIndex(validators[7]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[1], + validators[3], + validators[4], + validators[5], + validators[6], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + }); + + it('common case 1-11: validator-1 exitMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[1]).exitMaintenance()); + const index = await validatorSet.getCurrentValidatorIndex(validators[1]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[4], + validators[5], + validators[6], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + }); + + it('common case 1-12: validator-1 misdemeanor, enterMaintenance failed!', async () => { + await setSlashIndicator(operator.address, validatorSet, instances); + + await validatorSet.connect(operator).misdemeanor(validators[1]); + const index = await validatorSet.getCurrentValidatorIndex(validators[1]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[4], + validators[5], + validators[6], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + }); + + it('common case 1-13: validator-8 enterMaintenance', async () => { + await mineBlocks(21 * 100 * maintainSlashScale); + + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[8]).enterMaintenance()); + + const index = await validatorSet.getCurrentValidatorIndex(validators[8]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[4], + validators[5], + validators[6], + validators[8], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + }); + + it('common case 1-14: validator-9 enterMaintenance failed!', async () => { + expect(validatorSet.connect(signers[9]).enterMaintenance()).to.be.revertedWith( + 'can not enter Temporary Maintenance' + ); + }); + + it('common case 1-15: validator-1 felony', async () => { + let index = await validatorSet.currentValidatorSetMap(validators[1]); + expect(index.toNumber() > 0).to.be.eq(true); + + await setSlashIndicator(operator.address, validatorSet, instances); + await validatorSet.connect(operator).felony(validators[1]); + + index = await validatorSet.currentValidatorSetMap(validators[1]); + expect(index.toNumber() === 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[4], + validators[5], + validators[6], + validators[8], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + }); + + it('common case 1-16: validator-2 enterMaintenance failed!', async () => { + expect(validatorSet.connect(signers[2]).enterMaintenance()).to.be.revertedWith( + 'can not enter Temporary Maintenance' + ); + }); + + it('common case 1-17: validator-4 exitMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[4]).exitMaintenance()); + const index = await validatorSet.getCurrentValidatorIndex(validators[4]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[5], + validators[6], + validators[8], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + }); + + it('common case 1-18: validator-2 enterMaintenance failed!', async () => { + expect(validatorSet.connect(signers[2]).enterMaintenance()).to.be.revertedWith( + 'can not enter Temporary Maintenance' + ); + }); + + it('common case 1-19: validator-2 misdemeanor, enterMaintenance failed!', async () => { + await setSlashIndicator(operator.address, validatorSet, instances); + await validatorSet.connect(operator).misdemeanor(validators[2]); + const index = await validatorSet.getCurrentValidatorIndex(validators[2]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[5], + validators[6], + validators[8], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + }); + + it('common case 1-20: validator-10 enterMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[10]).enterMaintenance()); + + const index = await validatorSet.getCurrentValidatorIndex(validators[10]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[3], + validators[5], + validators[6], + validators[8], + validators[10], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(5); + }); + + it('common case 1-21: validator-3 exitMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + await waitTx(validatorSet.connect(signers[3]).exitMaintenance()); + const index = await validatorSet.getCurrentValidatorIndex(validators[3]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[5], + validators[6], + validators[8], + validators[10], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + }); + + it('common case 1-22: validator-4 exitMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + expect(validatorSet.connect(signers[4]).exitMaintenance()).to.revertedWith( + 'not in maintenance' + ); + }); + + it('common case 1-23: validator-4 enterMaintenance failed!', async () => { + expect(validatorSet.connect(signers[4]).enterMaintenance()).to.be.revertedWith( + 'can not enter Temporary Maintenance' + ); + }); + + it('common case 1-24: 24 hours ended, clear all maintainInfo', async () => { + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([ + validators[5], + validators[6], + validators[8], + validators[10], + ]); + expect(await validatorSet.numOfMaintaining()).to.be.eq(4); + + await waitTx( + validatorSet.updateContractAddr( + instances[10].address, + instances[8].address, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + operator.address + ) + ); + + await mineBlocks(21 * 50 * maintainSlashScale); + + // do update validators + let packageBytes = validatorUpdateRlpEncode( + validators.slice(2, 23), + validators.slice(2, 23), + validators.slice(2, 23) + ); + await waitTx(validatorSet.connect(operator).handleSynPackage(STAKE_CHANNEL_ID, packageBytes)); + + // validator-5,6 felony, validator-8 misdemeanor + const expectedValidators = validators + .slice(2, 23) + .filter((item) => item !== validators[5] && item !== validators[6]); + expect(await validatorSet.getValidators()).to.deep.eq(expectedValidators); + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + + for (let i = 2; i < 23; i++) { + if (i === 5 || i === 6) { + // because of felony, validator-5,6 are not the current validators + expect(validatorSet.getCurrentValidatorIndex(validators[i])).to.be.revertedWith( + 'only current validators' + ); + continue; + } + const index = await validatorSet.getCurrentValidatorIndex(validators[i]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + + expect(validatorExtra.isMaintaining).to.be.eq(false); + expect(validatorExtra.enterMaintenanceHeight.toNumber() === 0).to.be.eq(true); + } + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([]); + }); + + + it('common case 1-25: query all view func', async () => { + expect(await validatorSet.maxNumOfMaintaining()).to.be.eq(maxNumOfMaintaining) + expect(await validatorSet.maintainSlashScale()).to.be.eq(maintainSlashScale) + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + + for (let i = 2; i < 50; i++) { + if (i >= 2 && i < 23 && i !== 5 && i !== 6) { + expect(await validatorSet.isCurrentValidator(validators[i])).to.deep.eq(true); + } else { + expect(await validatorSet.isCurrentValidator(validators[i])).to.deep.eq(false); + } + expect(await validatorSet.getIncoming(validators[i])).to.deep.eq(0); + } + + expect(await validatorSet.getMaintainingValidators()).to.deep.eq([]); + }); + + + it('common case 2-1 update params', async () => { + await waitTx( + govHub.updateContractAddr( + instances[10].address, + instances[8].address, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + instances[2].address + ) + ); + + // set maxNumOfMaintaining to 5 + let govChannelSeq = await crosschain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + maxNumOfMaintaining = 18; + let govValue = '0x0000000000000000000000000000000000000000000000000000000000000012'; // 18 + let govPackageBytes = serializeGovPack('maxNumOfMaintaining', govValue, validatorSet.address); + await crosschain + .connect(operator) + .handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID + ); + expect(await validatorSet.maxNumOfMaintaining()).to.be.eq(BigNumber.from(govValue)); + + // set maintainSlashScale to 2 + govChannelSeq = await crosschain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + maintainSlashScale = 1; + govValue = '0x0000000000000000000000000000000000000000000000000000000000000001'; // 1 + govPackageBytes = serializeGovPack('maintainSlashScale', govValue, validatorSet.address); + await crosschain + .connect(operator) + .handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID + ); + expect(await validatorSet.maintainSlashScale()).to.be.eq(BigNumber.from(govValue)); + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + }); + + + it('common case 2-2: validator 7 ~ 10 enterMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + for (let i = 7; i < 10; i++) { + await waitTx(validatorSet.connect(signers[i]).enterMaintenance()); + } + + const expectedMaintainingValidators = [] + + for (let i = 7; i < 10; i++) { + const index = await validatorSet.getCurrentValidatorIndex(validators[i]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expectedMaintainingValidators.push(validators[i]); + } + + + expect(await validatorSet.getMaintainingValidators()).to.deep.eq(expectedMaintainingValidators); + expect(await validatorSet.numOfMaintaining()).to.be.eq(3); + + const felonyThreshold = (await slashIndicator.felonyThreshold()).toNumber(); + await mineBlocks( 4 * felonyThreshold * maintainSlashScale / 2); + }); + + + it('common case 2-3: validator 10 ~ 21 enterMaintenance', async () => { + await setSlashIndicator(slashIndicator.address, validatorSet, instances); + + for (let i = 10; i < 22; i++) { + await waitTx(validatorSet.connect(signers[i]).enterMaintenance()); + } + + const expectedMaintainingValidators = [] + for (let i = 7; i < 10; i++) { + expectedMaintainingValidators.push(validators[i]); + } + + for (let i = 10; i < 22; i++) { + const index = await validatorSet.getCurrentValidatorIndex(validators[i]); + const validatorExtra = await validatorSet.validatorExtraSet(index); + expect(validatorExtra.isMaintaining).to.be.eq(true); + expect(validatorExtra.enterMaintenanceHeight.toNumber() > 0).to.be.eq(true); + expectedMaintainingValidators.push(validators[i]); + } + + expect(await validatorSet.getMaintainingValidators()).to.deep.eq(expectedMaintainingValidators); + expect(await validatorSet.numOfMaintaining()).to.be.eq(15); + + const felonyThreshold = (await slashIndicator.felonyThreshold()).toNumber(); + await mineBlocks( 4 * felonyThreshold * maintainSlashScale / 2 + 1); + }); + + it('common case 2-4: update validator set', async () => { + await waitTx( + validatorSet.updateContractAddr( + instances[10].address, + instances[8].address, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + operator.address + ) + ); + + // do update validators + let packageBytes = validatorUpdateRlpEncode( + validators.slice(5, 26), + validators.slice(5, 26), + validators.slice(5, 26), + ); + await waitTx(validatorSet.connect(operator).handleSynPackage(STAKE_CHANNEL_ID, packageBytes)); + + // validator 7 ~ 9 will be felony, their slashCount = 4 * felonyThreshold * maintainSlashScale / workingValidatorCount(4) + const expectedValidators: string[] = [validators[5], validators[6]].concat(validators.slice(10, 26)); + + expect(await validatorSet.getValidators()).to.deep.eq(expectedValidators); + expect(await validatorSet.numOfMaintaining()).to.be.eq(0); + }); + +}); diff --git a/test/test-maintenance/helper.ts b/test/test-maintenance/helper.ts new file mode 100644 index 00000000..e1dc6627 --- /dev/null +++ b/test/test-maintenance/helper.ts @@ -0,0 +1,97 @@ +import { ethers } from 'hardhat'; +import { Signer } from '@ethersproject/abstract-signer'; +import { Contract, ContractReceipt, ContractTransaction } from '@ethersproject/contracts'; +import { BSCValidatorSet } from '../../typechain-types'; + +const RLP = require('rlp'); +import web3 from 'web3'; + +export async function deployContract( + signer: Signer, + factoryPath: string, + ...args: Array +): Promise { + const factory = await ethers.getContractFactory(factoryPath); + const contract = await factory.connect(signer).deploy(...args); + await contract.deployTransaction.wait(1); + return contract; +} + +export async function waitTx(txRequest: Promise): Promise { + const txResponse = await txRequest; + return await txResponse.wait(1); +} + +export const setSlashIndicator = async ( + slashAddress: string, + validatorSet: BSCValidatorSet, + instances: any[] +) => { + await waitTx( + validatorSet.updateContractAddr( + instances[10].address, + slashAddress, + instances[3].address, + instances[4].address, + instances[5].address, + instances[0].address, + instances[7].address, + instances[9].address, + instances[6].address, + instances[2].address + ) + ); +}; + +export function validatorUpdateRlpEncode( + consensusAddrList: any, + feeAddrList: any, + bscFeeAddrList: any +) { + let pkg = []; + pkg.push(0x00); + let n = consensusAddrList.length; + let vals = []; + for (let i = 0; i < n; i++) { + vals.push([ + consensusAddrList[i].toString(), + feeAddrList[i].toString(), + bscFeeAddrList[i].toString(), + 0x0000000000000064, + ]); + } + pkg.push(vals); + return RLP.encode(pkg); +} + +export function buildSyncPackagePrefix(syncRelayFee: any) { + return Buffer.from(web3.utils.hexToBytes('0x00' + toBytes32String(syncRelayFee))); +} + +export function toBytes32String(input: any) { + let initialInputHexStr = web3.utils.toBN(input).toString(16); + const initialInputHexStrLength = initialInputHexStr.length; + + let inputHexStr = initialInputHexStr; + for (let i = 0; i < 64 - initialInputHexStrLength; i++) { + inputHexStr = '0' + inputHexStr; + } + return inputHexStr; +} + +export function serializeGovPack(key: string, value: string, target: string, extra?: string) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if (extra) { + pkg.push(extra); + } + return RLP.encode(pkg); +} + +export async function mineBlocks(addedBlocksCount: number) { + for (let i = 0; i < addedBlocksCount; i++) { + await ethers.provider.send('evm_mine', []); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..0ace95a1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "outDir": "dist", + "typeRoots": ["./typechain", "./node_modules/@types"], + "types": ["@nomiclabs/hardhat-ethers", "@nomiclabs/hardhat-waffle"] + }, + "include": ["./test/test-maintenance", "./typechain"], + "files": ["./hardhat.config.ts"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..65a05e98 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,10826 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" + integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== + dependencies: + "@babel/highlight" "^7.16.7" + +"@babel/compat-data@^7.16.4": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" + integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== + +"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" + integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-compilation-targets" "^7.16.7" + "@babel/helper-module-transforms" "^7.16.7" + "@babel/helpers" "^7.16.7" + "@babel/parser" "^7.16.12" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.10" + "@babel/types" "^7.16.8" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.16.8", "@babel/generator@^7.7.2": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" + integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== + dependencies: + "@babel/types" "^7.16.8" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-compilation-targets@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b" + integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== + dependencies: + "@babel/compat-data" "^7.16.4" + "@babel/helper-validator-option" "^7.16.7" + browserslist "^4.17.5" + semver "^6.3.0" + +"@babel/helper-environment-visitor@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7" + integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-function-name@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f" + integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== + dependencies: + "@babel/helper-get-function-arity" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-get-function-arity@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419" + integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-hoist-variables@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" + integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-imports@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" + integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-module-transforms@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz#7665faeb721a01ca5327ddc6bba15a5cb34b6a41" + integrity sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng== + dependencies: + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-module-imports" "^7.16.7" + "@babel/helper-simple-access" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/helper-validator-identifier" "^7.16.7" + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5" + integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA== + +"@babel/helper-simple-access@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7" + integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-split-export-declaration@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" + integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== + dependencies: + "@babel/types" "^7.16.7" + +"@babel/helper-validator-identifier@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" + integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== + +"@babel/helper-validator-option@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" + integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== + +"@babel/helpers@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.7.tgz#7e3504d708d50344112767c3542fc5e357fffefc" + integrity sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw== + dependencies: + "@babel/template" "^7.16.7" + "@babel/traverse" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/highlight@^7.16.7": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.14.7", "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7": + version "7.16.12" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" + integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8" + integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A== + dependencies: + "@babel/helper-plugin-utils" "^7.16.7" + +"@babel/template@^7.16.7": + version "7.16.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" + integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/parser" "^7.16.7" + "@babel/types" "^7.16.7" + +"@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.7.2": + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" + integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw== + dependencies: + "@babel/code-frame" "^7.16.7" + "@babel/generator" "^7.16.8" + "@babel/helper-environment-visitor" "^7.16.7" + "@babel/helper-function-name" "^7.16.7" + "@babel/helper-hoist-variables" "^7.16.7" + "@babel/helper-split-export-declaration" "^7.16.7" + "@babel/parser" "^7.16.10" + "@babel/types" "^7.16.8" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0": + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" + integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== + dependencies: + "@babel/helper-validator-identifier" "^7.16.7" + to-fast-properties "^2.0.0" + +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + +"@ensdomains/ens@^0.4.4": + version "0.4.5" + resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" + integrity sha512-JSvpj1iNMFjK6K+uVl4unqMoa9rf5jopb8cya5UGBWz23Nw8hSNT7efgUx4BTlAPAgpNlEioUfeTyQ6J9ZvTVw== + dependencies: + bluebird "^3.5.2" + eth-ens-namehash "^2.0.8" + solc "^0.4.20" + testrpc "0.0.1" + web3-utils "^1.0.0-beta.31" + +"@ensdomains/resolver@^0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@ensdomains/resolver/-/resolver-0.2.4.tgz#c10fe28bf5efbf49bff4666d909aed0265efbc89" + integrity sha512-bvaTH34PMCbv6anRa9I/0zjLJgY4EuznbEMgbV77JBCQ9KNC46rzi0avuxpOfu+xDjPEtSFGqVEOr5GlUSGudA== + +"@ethereum-waffle/chai@^3.4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/chai/-/chai-3.4.1.tgz#500b59db766a490cb19a7f74ac75a1c3cf86049b" + integrity sha512-8mjgjWCe8XSCWuyJgVtJY8sm00VTczGBTDxBejgEBWN/J9x7QD8jdmWW8bfxdnqZbxiDCTvRFL58Wmd254BEqQ== + dependencies: + "@ethereum-waffle/provider" "^3.4.0" + ethers "^5.4.7" + +"@ethereum-waffle/compiler@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/compiler/-/compiler-3.4.0.tgz#68917321212563544913de33e408327745cb1284" + integrity sha512-a2wxGOoB9F1QFRE+Om7Cz2wn+pxM/o7a0a6cbwhaS2lECJgFzeN9xEkVrKahRkF4gEfXGcuORg4msP0Asxezlw== + dependencies: + "@resolver-engine/imports" "^0.3.3" + "@resolver-engine/imports-fs" "^0.3.3" + "@typechain/ethers-v5" "^2.0.0" + "@types/mkdirp" "^0.5.2" + "@types/node-fetch" "^2.5.5" + ethers "^5.0.1" + mkdirp "^0.5.1" + node-fetch "^2.6.1" + solc "^0.6.3" + ts-generator "^0.1.1" + typechain "^3.0.0" + +"@ethereum-waffle/ens@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/ens/-/ens-3.3.1.tgz#0f1b7ac4fc156641c18accd60f8ce256e2c475cf" + integrity sha512-xSjNWnT2Iwii3J3XGqD+F5yLEOzQzLHNLGfI5KIXdtQ4FHgReW/AMGRgPPLi+n+SP08oEQWJ3sEKrvbFlwJuaA== + dependencies: + "@ensdomains/ens" "^0.4.4" + "@ensdomains/resolver" "^0.2.4" + ethers "^5.5.2" + +"@ethereum-waffle/mock-contract@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/mock-contract/-/mock-contract-3.3.1.tgz#dfd53a6e184f5e4c5e1119a8aef67f2d88914497" + integrity sha512-h9yChF7IkpJLODg/o9/jlwKwTcXJLSEIq3gewgwUJuBHnhPkJGekcZvsTbximYc+e42QUZrDUATSuTCIryeCEA== + dependencies: + "@ethersproject/abi" "^5.5.0" + ethers "^5.5.2" + +"@ethereum-waffle/provider@^3.4.0": + version "3.4.1" + resolved "https://registry.yarnpkg.com/@ethereum-waffle/provider/-/provider-3.4.1.tgz#d59f5741d5ee96a7d5501f455709b38d81c8be2f" + integrity sha512-5iDte7c9g9N1rTRE/P4npwk1Hus/wA2yH850X6sP30mr1IrwSG9NKn6/2SOQkAVJnh9jqyLVg2X9xCODWL8G4A== + dependencies: + "@ethereum-waffle/ens" "^3.3.1" + ethers "^5.5.2" + ganache-core "^2.13.2" + patch-package "^6.2.2" + postinstall-postinstall "^2.1.0" + +"@ethereumjs/block@^3.5.0", "@ethereumjs/block@^3.6.0": + version "3.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/block/-/block-3.6.0.tgz#5cf89ea748607597a3f8b038abc986e4ac0b05db" + integrity sha512-dqLo1LtsLG+Oelu5S5tWUDG0pah3QUwV5TJZy2cm19BXDr4ka/S9XBSgao0i09gTcuPlovlHgcs6d7EZ37urjQ== + dependencies: + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + ethereumjs-util "^7.1.3" + merkle-patricia-tree "^4.2.2" + +"@ethereumjs/blockchain@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethereumjs/blockchain/-/blockchain-5.5.1.tgz#60f1f50592c06cc47e1704800b88b7d32f609742" + integrity sha512-JS2jeKxl3tlaa5oXrZ8mGoVBCz6YqsGG350XVNtHAtNZXKk7pU3rH4xzF2ru42fksMMqzFLzKh9l4EQzmNWDqA== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/ethash" "^1.1.0" + debug "^2.2.0" + ethereumjs-util "^7.1.3" + level-mem "^5.0.1" + lru-cache "^5.1.1" + semaphore-async-await "^1.5.1" + +"@ethereumjs/common@^2.5.0", "@ethereumjs/common@^2.6.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.6.0.tgz#feb96fb154da41ee2cc2c5df667621a440f36348" + integrity sha512-Cq2qS0FTu6O2VU1sgg+WyU9Ps0M6j/BEMHN+hRaECXCV/r0aI78u4N6p52QW/BDVhwWZpCdrvG8X7NJdzlpNUA== + dependencies: + crc-32 "^1.2.0" + ethereumjs-util "^7.1.3" + +"@ethereumjs/ethash@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/ethash/-/ethash-1.1.0.tgz#7c5918ffcaa9cb9c1dc7d12f77ef038c11fb83fb" + integrity sha512-/U7UOKW6BzpA+Vt+kISAoeDie1vAvY4Zy2KF5JJb+So7+1yKmJeJEHOGSnQIj330e9Zyl3L5Nae6VZyh2TJnAA== + dependencies: + "@ethereumjs/block" "^3.5.0" + "@types/levelup" "^4.3.0" + buffer-xor "^2.0.1" + ethereumjs-util "^7.1.1" + miller-rabin "^4.0.0" + +"@ethereumjs/tx@^3.3.2", "@ethereumjs/tx@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.4.0.tgz#7eb1947eefa55eb9cf05b3ca116fb7a3dbd0bce7" + integrity sha512-WWUwg1PdjHKZZxPPo274ZuPsJCWV3SqATrEKQP1n2DrVYVP1aZIYpo/mFaA0BDoE0tIQmBeimRCEA0Lgil+yYw== + dependencies: + "@ethereumjs/common" "^2.6.0" + ethereumjs-util "^7.1.3" + +"@ethereumjs/vm@^5.6.0": + version "5.6.0" + resolved "https://registry.yarnpkg.com/@ethereumjs/vm/-/vm-5.6.0.tgz#e0ca62af07de820143674c30b776b86c1983a464" + integrity sha512-J2m/OgjjiGdWF2P9bj/4LnZQ1zRoZhY8mRNVw/N3tXliGI8ai1sI1mlDPkLpeUUM4vq54gH6n0ZlSpz8U/qlYQ== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + async-eventemitter "^0.2.4" + core-js-pure "^3.0.1" + debug "^2.2.0" + ethereumjs-util "^7.1.3" + functional-red-black-tree "^1.0.1" + mcl-wasm "^0.7.1" + merkle-patricia-tree "^4.2.2" + rustbn.js "~0.2.0" + +"@ethersproject/abi@5.0.0-beta.153": + version "5.0.0-beta.153" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" + integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== + dependencies: + "@ethersproject/address" ">=5.0.0-beta.128" + "@ethersproject/bignumber" ">=5.0.0-beta.130" + "@ethersproject/bytes" ">=5.0.0-beta.129" + "@ethersproject/constants" ">=5.0.0-beta.128" + "@ethersproject/hash" ">=5.0.0-beta.128" + "@ethersproject/keccak256" ">=5.0.0-beta.127" + "@ethersproject/logger" ">=5.0.0-beta.129" + "@ethersproject/properties" ">=5.0.0-beta.131" + "@ethersproject/strings" ">=5.0.0-beta.130" + +"@ethersproject/abi@5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" + integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== + dependencies: + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/hash" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + +"@ethersproject/abi@5.5.0", "@ethersproject/abi@^5.0.0-beta.146", "@ethersproject/abi@^5.1.2", "@ethersproject/abi@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.5.0.tgz#fb52820e22e50b854ff15ce1647cc508d6660613" + integrity sha512-loW7I4AohP5KycATvc0MgujU6JyCHPqHdeoo9z3Nr9xEiNioxa65ccdm1+fsoJhkuhdRtfcL8cfyGamz2AxZ5w== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/abstract-provider@5.5.1", "@ethersproject/abstract-provider@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.5.1.tgz#2f1f6e8a3ab7d378d8ad0b5718460f85649710c5" + integrity sha512-m+MA/ful6eKbxpr99xUYeRvLkfnlqzrF8SZ46d/xFB1A7ZVknYc/sXJG0RcufF52Qn2jeFj1hhcoQ7IXjNKUqg== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + +"@ethersproject/abstract-signer@5.5.0", "@ethersproject/abstract-signer@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.5.0.tgz#590ff6693370c60ae376bf1c7ada59eb2a8dd08d" + integrity sha512-lj//7r250MXVLKI7sVarXAbZXbv9P50lgmJQGr2/is82EwEb8r7HrxsmMqAjTsztMYy7ohrIhGMIml+Gx4D3mA== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/address@5.5.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.0.4", "@ethersproject/address@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.5.0.tgz#bcc6f576a553f21f3dd7ba17248f81b473c9c78f" + integrity sha512-l4Nj0eWlTUh6ro5IbPTgbpT4wRbdH5l8CQf7icF7sb/SI3Nhd9Y9HzhonTSTi6CefI0necIw7LJqQPopPLZyWw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + +"@ethersproject/base64@5.5.0", "@ethersproject/base64@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.5.0.tgz#881e8544e47ed976930836986e5eb8fab259c090" + integrity sha512-tdayUKhU1ljrlHzEWbStXazDpsx4eg1dBXUSI6+mHlYklOXoXF6lZvw8tnD6oVaWfnMxAgRSKROg3cVKtCcppA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + +"@ethersproject/basex@5.5.0", "@ethersproject/basex@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.5.0.tgz#e40a53ae6d6b09ab4d977bd037010d4bed21b4d3" + integrity sha512-ZIodwhHpVJ0Y3hUCfUucmxKsWQA5TMnavp5j/UOuDdzZWzJlRmuOjcTMIGgHCYuZmHt36BfiSyQPSRskPxbfaQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + +"@ethersproject/bignumber@5.5.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.7", "@ethersproject/bignumber@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.5.0.tgz#875b143f04a216f4f8b96245bde942d42d279527" + integrity sha512-6Xytlwvy6Rn3U3gKEc1vP7nR92frHkv6wtVr95LFR3jREXiCPzdWxKQ1cx4JGQBXxcguAwjA8murlYN2TSiEbg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + bn.js "^4.11.9" + +"@ethersproject/bytes@5.5.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.4", "@ethersproject/bytes@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.5.0.tgz#cb11c526de657e7b45d2e0f0246fb3b9d29a601c" + integrity sha512-ABvc7BHWhZU9PNM/tANm/Qx4ostPGadAuQzWTr3doklZOhDlmcBqclrQe/ZXUIj3K8wC28oYeuRa+A37tX9kog== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/constants@5.5.0", "@ethersproject/constants@>=5.0.0-beta.128", "@ethersproject/constants@^5.0.4", "@ethersproject/constants@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.5.0.tgz#d2a2cd7d94bd1d58377d1d66c4f53c9be4d0a45e" + integrity sha512-2MsRRVChkvMWR+GyMGY4N1sAX9Mt3J9KykCsgUFd/1mwS0UH1qw+Bv9k1UJb3X3YJYFco9H20pjSlOIfCG5HYQ== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + +"@ethersproject/contracts@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.5.0.tgz#b735260d4bd61283a670a82d5275e2a38892c197" + integrity sha512-2viY7NzyvJkh+Ug17v7g3/IJC8HqZBDcOjYARZLdzRxrfGlRgmYgl6xPRKVbEzy1dWKw/iv7chDcS83pg6cLxg== + dependencies: + "@ethersproject/abi" "^5.5.0" + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + +"@ethersproject/hash@5.5.0", "@ethersproject/hash@>=5.0.0-beta.128", "@ethersproject/hash@^5.0.4", "@ethersproject/hash@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.5.0.tgz#7cee76d08f88d1873574c849e0207dcb32380cc9" + integrity sha512-dnGVpK1WtBjmnp3mUT0PlU2MpapnwWI0PibldQEq1408tQBAbZpPidkWoVVuNMOl/lISO3+4hXZWCL3YV7qzfg== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/hdnode@5.5.0", "@ethersproject/hdnode@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.5.0.tgz#4a04e28f41c546f7c978528ea1575206a200ddf6" + integrity sha512-mcSOo9zeUg1L0CoJH7zmxwUG5ggQHU1UrRf8jyTYy6HxdZV+r0PBoL1bxr+JHIPXRzS6u/UW4mEn43y0tmyF8Q== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/json-wallets@5.5.0", "@ethersproject/json-wallets@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.5.0.tgz#dd522d4297e15bccc8e1427d247ec8376b60e325" + integrity sha512-9lA21XQnCdcS72xlBn1jfQdj2A1VUxZzOzi9UkNdnokNKke/9Ya2xA9aIK1SC3PQyBDLt4C+dfps7ULpkvKikQ== + dependencies: + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/pbkdf2" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + aes-js "3.0.0" + scrypt-js "3.0.1" + +"@ethersproject/keccak256@5.5.0", "@ethersproject/keccak256@>=5.0.0-beta.127", "@ethersproject/keccak256@^5.0.3", "@ethersproject/keccak256@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.5.0.tgz#e4b1f9d7701da87c564ffe336f86dcee82983492" + integrity sha512-5VoFCTjo2rYbBe1l2f4mccaRFN/4VQEYFwwn04aJV2h7qf4ZvI2wFxUE1XOX+snbwCLRzIeikOqtAoPwMza9kg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + js-sha3 "0.8.0" + +"@ethersproject/logger@5.5.0", "@ethersproject/logger@>=5.0.0-beta.129", "@ethersproject/logger@^5.0.5", "@ethersproject/logger@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.5.0.tgz#0c2caebeff98e10aefa5aef27d7441c7fd18cf5d" + integrity sha512-rIY/6WPm7T8n3qS2vuHTUBPdXHl+rGxWxW5okDfo9J4Z0+gRRZT0msvUdIJkE4/HS29GUMziwGaaKO2bWONBrg== + +"@ethersproject/networks@5.5.2", "@ethersproject/networks@^5.5.0": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.5.2.tgz#784c8b1283cd2a931114ab428dae1bd00c07630b" + integrity sha512-NEqPxbGBfy6O3x4ZTISb90SjEDkWYDUbEeIFhJly0F7sZjoQMnj5KYzMSkMkLKZ+1fGpx00EDpHQCy6PrDupkQ== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/pbkdf2@5.5.0", "@ethersproject/pbkdf2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.5.0.tgz#e25032cdf02f31505d47afbf9c3e000d95c4a050" + integrity sha512-SaDvQFvXPnz1QGpzr6/HToLifftSXGoXrbpZ6BvoZhmx4bNLHrxDe8MZisuecyOziP1aVEwzC2Hasj+86TgWVg== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + +"@ethersproject/properties@5.5.0", "@ethersproject/properties@>=5.0.0-beta.131", "@ethersproject/properties@^5.0.3", "@ethersproject/properties@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.5.0.tgz#61f00f2bb83376d2071baab02245f92070c59995" + integrity sha512-l3zRQg3JkD8EL3CPjNK5g7kMx4qSwiR60/uk5IVjd3oq1MZR5qUg40CNOoEJoX5wc3DyY5bt9EbMk86C7x0DNA== + dependencies: + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/providers@5.5.2": + version "5.5.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.2.tgz#131ccf52dc17afd0ab69ed444b8c0e3a27297d99" + integrity sha512-hkbx7x/MKcRjyrO4StKXCzCpWer6s97xnm34xkfPiarhtEUVAN4TBBpamM+z66WcTt7H5B53YwbRj1n7i8pZoQ== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/basex" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/networks" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/web" "^5.5.0" + bech32 "1.1.4" + ws "7.4.6" + +"@ethersproject/random@5.5.1", "@ethersproject/random@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.5.1.tgz#7cdf38ea93dc0b1ed1d8e480ccdaf3535c555415" + integrity sha512-YaU2dQ7DuhL5Au7KbcQLHxcRHfgyNgvFV4sQOo0HrtW3Zkrc9ctWNz8wXQ4uCSfSDsqX2vcjhroxU5RQRV0nqA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/rlp@5.5.0", "@ethersproject/rlp@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.5.0.tgz#530f4f608f9ca9d4f89c24ab95db58ab56ab99a0" + integrity sha512-hLv8XaQ8PTI9g2RHoQGf/WSxBfTB/NudRacbzdxmst5VHAqd1sMibWG7SENzT5Dj3yZ3kJYx+WiRYEcQTAkcYA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/sha2@5.5.0", "@ethersproject/sha2@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.5.0.tgz#a40a054c61f98fd9eee99af2c3cc6ff57ec24db7" + integrity sha512-B5UBoglbCiHamRVPLA110J+2uqsifpZaTmid2/7W5rbtYVz6gus6/hSDieIU/6gaKIDcOj12WnOdiymEUHIAOA== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + hash.js "1.1.7" + +"@ethersproject/signing-key@5.5.0", "@ethersproject/signing-key@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.5.0.tgz#2aa37169ce7e01e3e80f2c14325f624c29cedbe0" + integrity sha512-5VmseH7qjtNmDdZBswavhotYbWB0bOwKIlOTSlX14rKn5c11QmJwGt4GHeo7NrL/Ycl7uo9AHvEqs5xZgFBTng== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.7" + +"@ethersproject/solidity@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.5.0.tgz#2662eb3e5da471b85a20531e420054278362f93f" + integrity sha512-9NgZs9LhGMj6aCtHXhtmFQ4AN4sth5HuFXVvAQtzmm0jpSCNOTGtrHZJAeYTh7MBjRR8brylWZxBZR9zDStXbw== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/sha2" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/strings@5.5.0", "@ethersproject/strings@>=5.0.0-beta.130", "@ethersproject/strings@^5.0.4", "@ethersproject/strings@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.5.0.tgz#e6784d00ec6c57710755699003bc747e98c5d549" + integrity sha512-9fy3TtF5LrX/wTrBaT8FGE6TDJyVjOvXynXJz5MT5azq+E6D92zuKNx7i29sWW2FjVOaWjAsiZ1ZWznuduTIIQ== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/transactions@5.5.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.5.0.tgz#7e9bf72e97bcdf69db34fe0d59e2f4203c7a2908" + integrity sha512-9RZYSKX26KfzEd/1eqvv8pLauCKzDTub0Ko4LfIgaERvRuwyaNV78mJs7cpIgZaDl6RJui4o49lHwwCM0526zA== + dependencies: + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/rlp" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + +"@ethersproject/units@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.5.0.tgz#104d02db5b5dc42cc672cc4587bafb87a95ee45e" + integrity sha512-7+DpjiZk4v6wrikj+TCyWWa9dXLNU73tSTa7n0TSJDxkYbV3Yf1eRh9ToMLlZtuctNYu9RDNNy2USq3AdqSbag== + dependencies: + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/constants" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + +"@ethersproject/wallet@5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.5.0.tgz#322a10527a440ece593980dca6182f17d54eae75" + integrity sha512-Mlu13hIctSYaZmUOo7r2PhNSd8eaMPVXe1wxrz4w4FCE4tDYBywDH+bAR1Xz2ADyXGwqYMwstzTrtUVIsKDO0Q== + dependencies: + "@ethersproject/abstract-provider" "^5.5.0" + "@ethersproject/abstract-signer" "^5.5.0" + "@ethersproject/address" "^5.5.0" + "@ethersproject/bignumber" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/hdnode" "^5.5.0" + "@ethersproject/json-wallets" "^5.5.0" + "@ethersproject/keccak256" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/random" "^5.5.0" + "@ethersproject/signing-key" "^5.5.0" + "@ethersproject/transactions" "^5.5.0" + "@ethersproject/wordlists" "^5.5.0" + +"@ethersproject/web@5.5.1", "@ethersproject/web@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.5.1.tgz#cfcc4a074a6936c657878ac58917a61341681316" + integrity sha512-olvLvc1CB12sREc1ROPSHTdFCdvMh0J5GSJYiQg2D0hdD4QmJDy8QYDb1CvoqD/bF1c++aeKv2sR5uduuG9dQg== + dependencies: + "@ethersproject/base64" "^5.5.0" + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@ethersproject/wordlists@5.5.0", "@ethersproject/wordlists@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.5.0.tgz#aac74963aa43e643638e5172353d931b347d584f" + integrity sha512-bL0UTReWDiaQJJYOC9sh/XcRu/9i2jMrzf8VLRmPKx58ckSlOJiohODkECCO50dtLZHcGU6MLXQ4OOrgBwP77Q== + dependencies: + "@ethersproject/bytes" "^5.5.0" + "@ethersproject/hash" "^5.5.0" + "@ethersproject/logger" "^5.5.0" + "@ethersproject/properties" "^5.5.0" + "@ethersproject/strings" "^5.5.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.4.6.tgz#0742e6787f682b22bdad56f9db2a8a77f6a86107" + integrity sha512-jauXyacQD33n47A44KrlOVeiXHEXDqapSdfb9kTekOchH/Pd18kBIO1+xxJQRLuG+LUuljFCwTG92ra4NW7SpA== + dependencies: + "@jest/types" "^27.4.2" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^27.4.6" + jest-util "^27.4.2" + slash "^3.0.0" + +"@jest/test-result@^27.0.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.4.6.tgz#b3df94c3d899c040f602cea296979844f61bdf69" + integrity sha512-fi9IGj3fkOrlMmhQqa/t9xum8jaJOOAi/lZlm6JXSc55rJMXKHxNDN1oCP39B0/DhNOa2OMupF9BcKZnNtXMOQ== + dependencies: + "@jest/console" "^27.4.6" + "@jest/types" "^27.4.2" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/transform@^27.4.6": + version "27.4.6" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.4.6.tgz#153621940b1ed500305eacdb31105d415dc30231" + integrity sha512-9MsufmJC8t5JTpWEQJ0OcOOAXaH5ioaIX6uHVBLBMoCZPfKKQF+EqP8kACAvCZ0Y1h2Zr3uOccg8re+Dr5jxyw== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^27.4.2" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^27.4.6" + jest-regex-util "^27.4.0" + jest-util "^27.4.2" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^27.4.2": + version "27.4.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.4.2.tgz#96536ebd34da6392c2b7c7737d693885b5dd44a5" + integrity sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^16.0.0" + chalk "^4.0.0" + +"@nomiclabs/hardhat-ethers@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.0.4.tgz#288889c338acaf47cabd29020e561d0077b7efcf" + integrity sha512-7LMR344TkdCYkMVF9LuC9VU2NBIi84akQiwqm7OufpWaDgHbWhuanY53rk3SVAW0E4HBk5xn5wl5+bN5f+Mq5w== + +"@nomiclabs/hardhat-etherscan@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.0.0.tgz#06e0d59787f01f1296d829e8d43fece50e7ffff1" + integrity sha512-E5s35dCHmzuY6pFqlgTdDGQr2xIyUJ3f91m6e7HYlPGz0FGzad9Nem/y0L7L3FHG4LPYg1UObkQVUzqBjtyAOA== + dependencies: + "@ethersproject/abi" "^5.1.2" + "@ethersproject/address" "^5.0.2" + cbor "^5.0.2" + debug "^4.1.1" + fs-extra "^7.0.1" + node-fetch "^2.6.0" + semver "^6.3.0" + +"@nomiclabs/hardhat-waffle@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.2.tgz#6030aa6fd9ea05327bf79d1107356af906d8b1e4" + integrity sha512-dnhry6Bj15O8L3pBksTuXfr4RAUIf+BxRxWJXiu+ioSawcQaOcNF4gfMxn6ik0auk3zrsAJLA6m9vqe87d4xvg== + dependencies: + "@types/sinon-chai" "^3.2.3" + "@types/web3" "1.0.19" + +"@openzeppelin/contracts-upgradeable@^4.3.1": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.4.2.tgz#748a5986a02548ef541cabc2ce8c67a890044c40" + integrity sha512-bavxs18L47EmcdnL9I6DzsVSUJO+0/zD6zH7/6qG7QRBugvR3VNVZR+nMvuZlCNwuTTnCa3apR00PYzYr/efAw== + +"@openzeppelin/contracts@^4.3.1": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.4.2.tgz#4e889c9c66e736f7de189a53f8ba5b8d789425c2" + integrity sha512-NyJV7sJgoGYqbtNUWgzzOGW4T6rR19FmX1IJgXGdapGPWsuMelGJn9h03nos0iqfforCbCB0iYIR0MtIuIFLLw== + +"@resolver-engine/core@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0" + integrity sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A== + dependencies: + debug "^3.1.0" + request "^2.85.0" + +"@resolver-engine/core@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.3.3.tgz#590f77d85d45bc7ecc4e06c654f41345db6ca967" + integrity sha512-eB8nEbKDJJBi5p5SrvrvILn4a0h42bKtbCTri3ZxCGt6UvoQyp7HnGOfki944bUjBSHKK3RvgfViHn+kqdXtnQ== + dependencies: + debug "^3.1.0" + is-url "^1.2.4" + request "^2.85.0" + +"@resolver-engine/fs@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.2.1.tgz#f98a308d77568cc02651d03636f46536b941b241" + integrity sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + +"@resolver-engine/fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.3.3.tgz#fbf83fa0c4f60154a82c817d2fe3f3b0c049a973" + integrity sha512-wQ9RhPUcny02Wm0IuJwYMyAG8fXVeKdmhm8xizNByD4ryZlx6PP6kRen+t/haF43cMfmaV7T3Cx6ChOdHEhFUQ== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz#5a81ef3285dbf0411ab3b15205080a1ad7622d9e" + integrity sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ== + dependencies: + "@resolver-engine/fs" "^0.2.1" + "@resolver-engine/imports" "^0.2.2" + debug "^3.1.0" + +"@resolver-engine/imports-fs@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.3.3.tgz#4085db4b8d3c03feb7a425fbfcf5325c0d1e6c1b" + integrity sha512-7Pjg/ZAZtxpeyCFlZR5zqYkz+Wdo84ugB5LApwriT8XFeQoLwGUj4tZFFvvCuxaNCcqZzCYbonJgmGObYBzyCA== + dependencies: + "@resolver-engine/fs" "^0.3.3" + "@resolver-engine/imports" "^0.3.3" + debug "^3.1.0" + +"@resolver-engine/imports@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.2.2.tgz#d3de55a1bb5f3beb7703fdde743298f321175843" + integrity sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg== + dependencies: + "@resolver-engine/core" "^0.2.1" + debug "^3.1.0" + hosted-git-info "^2.6.0" + +"@resolver-engine/imports@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.3.3.tgz#badfb513bb3ff3c1ee9fd56073e3144245588bcc" + integrity sha512-anHpS4wN4sRMwsAbMXhMfOD/y4a4Oo0Cw/5+rue7hSwGWsDOQaAU1ClK1OxjUC35/peazxEl8JaSRRS+Xb8t3Q== + dependencies: + "@resolver-engine/core" "^0.3.3" + debug "^3.1.0" + hosted-git-info "^2.6.0" + path-browserify "^1.0.0" + url "^0.11.0" + +"@sentry/core@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.30.0.tgz#6b203664f69e75106ee8b5a2fe1d717379b331f3" + integrity sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/hub@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.30.0.tgz#2453be9b9cb903404366e198bd30c7ca74cdc100" + integrity sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ== + dependencies: + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/minimal@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.30.0.tgz#ce3d3a6a273428e0084adcb800bc12e72d34637b" + integrity sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sentry/node@^5.18.1": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.30.0.tgz#4ca479e799b1021285d7fe12ac0858951c11cd48" + integrity sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg== + dependencies: + "@sentry/core" "5.30.0" + "@sentry/hub" "5.30.0" + "@sentry/tracing" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + cookie "^0.4.1" + https-proxy-agent "^5.0.0" + lru_map "^0.3.3" + tslib "^1.9.3" + +"@sentry/tracing@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.30.0.tgz#501d21f00c3f3be7f7635d8710da70d9419d4e1f" + integrity sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw== + dependencies: + "@sentry/hub" "5.30.0" + "@sentry/minimal" "5.30.0" + "@sentry/types" "5.30.0" + "@sentry/utils" "5.30.0" + tslib "^1.9.3" + +"@sentry/types@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.30.0.tgz#19709bbe12a1a0115bc790b8942917da5636f402" + integrity sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw== + +"@sentry/utils@5.30.0": + version "5.30.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.30.0.tgz#9a5bd7ccff85ccfe7856d493bffa64cabc41e980" + integrity sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww== + dependencies: + "@sentry/types" "5.30.0" + tslib "^1.9.3" + +"@sindresorhus/is@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" + integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== + +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^7.1.0": + version "7.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz#2524eae70c4910edccf99b2f4e6efc5894aff7b5" + integrity sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg== + dependencies: + "@sinonjs/commons" "^1.7.0" + +"@solidity-parser/parser@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.0.tgz#d51f074efb0acce0e953ec48133561ed710cebc0" + integrity sha512-cX0JJRcmPtNUJpzD2K7FdA7qQsTOk1UZnFx2k7qAg9ZRvuaH5NBe5IEdBMXGlmf2+FmjhqbygJ26H8l2SV7aKQ== + dependencies: + antlr4ts "^0.5.0-alpha.4" + +"@solidity-parser/parser@^0.6.0": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.6.2.tgz#49707fc4e06649d39d6b25bdab2e9093d372ce50" + integrity sha512-kUVUvrqttndeprLoXjI5arWHeiP3uh4XODAKbG+ZaWHCVQeelxCbnXBeWxZ2BPHdXgH0xR9dU1b916JhDhbgAA== + +"@szmarczak/http-timer@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" + integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + dependencies: + defer-to-connect "^1.0.1" + +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + +"@typechain/ethers-v5@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-2.0.0.tgz#cd3ca1590240d587ca301f4c029b67bfccd08810" + integrity sha512-0xdCkyGOzdqh4h5JSf+zoWx85IusEjDcPIwNEHP8mrWSnCae4rvrqB+/gtpdNfX7zjlFlZiMeePn2r63EI3Lrw== + dependencies: + ethers "^5.0.2" + +"@typechain/ethers-v5@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@typechain/ethers-v5/-/ethers-v5-9.0.0.tgz#6aa93bea7425c0463bd8a61eea3643540ef851bd" + integrity sha512-bAanuPl1L2itaUdMvor/QvwnIH+TM/CmG00q17Ilv3ZZMeJ2j8HcarhgJUZ9pBY1teBb85P8cC03dz3mSSx+tQ== + dependencies: + lodash "^4.17.15" + ts-essentials "^7.0.1" + +"@typechain/hardhat@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@typechain/hardhat/-/hardhat-4.0.0.tgz#976d4dcc0d9237602d722801d30adc573c529981" + integrity sha512-SeEKtiHu4Io3LHhE8VV3orJbsj7dwJZX8pzSTv7WQR38P18vOLm2M52GrykVinMpkLK0uVc88ICT58emvfn74w== + dependencies: + fs-extra "^9.1.0" + +"@types/abstract-leveldown@*": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#f055979a99f7654e84d6b8e6267419e9c4cfff87" + integrity sha512-q5veSX6zjUy/DlDhR4Y4cU0k2Ar+DT2LUraP00T19WLmTO6Se1djepCCaqU6nQrwcJ5Hyo/CWqxTzrrFg8eqbQ== + +"@types/babel__traverse@^7.0.4": + version "7.14.2" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43" + integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA== + dependencies: + "@babel/types" "^7.3.0" + +"@types/bn.js@*", "@types/bn.js@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68" + integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA== + dependencies: + "@types/node" "*" + +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": + version "4.11.6" + resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" + integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== + dependencies: + "@types/node" "*" + +"@types/chai@*", "@types/chai@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" + integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== + +"@types/concat-stream@^1.6.0": + version "1.6.1" + resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.1.tgz#24bcfc101ecf68e886aaedce60dfd74b632a1b74" + integrity sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA== + dependencies: + "@types/node" "*" + +"@types/form-data@0.0.33": + version "0.0.33" + resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" + integrity sha1-yayFsqX9GENbjIXZ7LUObWyJP/g= + dependencies: + "@types/node" "*" + +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/level-errors@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/level-errors/-/level-errors-3.0.0.tgz#15c1f4915a5ef763b51651b15e90f6dc081b96a8" + integrity sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ== + +"@types/levelup@^4.3.0": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/levelup/-/levelup-4.3.3.tgz#4dc2b77db079b1cf855562ad52321aa4241b8ef4" + integrity sha512-K+OTIjJcZHVlZQN1HmU64VtrC0jC3dXWQozuEIR9zVvltIk90zaGPM2AgT+fIkChpzHhFE3YnvFLCbLtzAmexA== + dependencies: + "@types/abstract-leveldown" "*" + "@types/level-errors" "*" + "@types/node" "*" + +"@types/lru-cache@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.1.tgz#c48c2e27b65d2a153b19bfc1a317e30872e01eef" + integrity sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw== + +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + +"@types/mocha@^9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" + integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== + +"@types/node-fetch@^2.5.5": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "17.0.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.10.tgz#616f16e9d3a2a3d618136b1be244315d95bd7cab" + integrity sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog== + +"@types/node@^10.0.3": + version "10.17.60" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.60.tgz#35f3d6213daed95da7f0f73e75bcc6980e90597b" + integrity sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw== + +"@types/node@^12.12.6": + version "12.20.42" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.42.tgz#2f021733232c2130c26f9eabbdd3bfd881774733" + integrity sha512-aI3/oo5DzyiI5R/xAhxxRzfZlWlsbbqdgxfTPkqu/Zt+23GXiJvMCyPJT4+xKSXOnLqoL8jJYMLTwvK2M3a5hw== + +"@types/node@^8.0.0": + version "8.10.66" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.66.tgz#dd035d409df322acc83dff62a602f12a5783bbb3" + integrity sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw== + +"@types/pbkdf2@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/pbkdf2/-/pbkdf2-3.1.0.tgz#039a0e9b67da0cdc4ee5dab865caa6b267bb66b1" + integrity sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ== + dependencies: + "@types/node" "*" + +"@types/prettier@^2.1.1", "@types/prettier@^2.1.5": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" + integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== + +"@types/qs@^6.2.31": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + +"@types/secp256k1@^4.0.1": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" + integrity sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w== + dependencies: + "@types/node" "*" + +"@types/sinon-chai@^3.2.3": + version "3.2.8" + resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.8.tgz#5871d09ab50d671d8e6dd72e9073f8e738ac61dc" + integrity sha512-d4ImIQbT/rKMG8+AXpmcan5T2/PNeSjrYhvkwet6z0p8kzYtfgA32xzOBlbU0yqJfq+/0Ml805iFoODO0LP5/g== + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*": + version "10.0.8" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.8.tgz#e43c3722629248470a866c86ecc06e5523ac0b4e" + integrity sha512-XZbSLlox2KM7VaEJPZ5G/fMZXJNuAtYiFOax7UT51quZMAJRWKvugPMqNA0mV3jC9HIYpQSg6qbV+ilQMwLqyA== + dependencies: + "@sinonjs/fake-timers" "^7.1.0" + +"@types/stack-utils@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" + integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + +"@types/underscore@*": + version "1.11.4" + resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.11.4.tgz#62e393f8bc4bd8a06154d110c7d042a93751def3" + integrity sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg== + +"@types/web3@1.0.19": + version "1.0.19" + resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.19.tgz#46b85d91d398ded9ab7c85a5dd57cb33ac558924" + integrity sha512-fhZ9DyvDYDwHZUp5/STa9XW2re0E8GxoioYJ4pEUZ13YHpApSagixj7IAdoYH5uAK+UalGq6Ml8LYzmgRA/q+A== + dependencies: + "@types/bn.js" "*" + "@types/underscore" "*" + +"@types/yargs-parser@*": + version "20.2.1" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.1.tgz#3b9ce2489919d9e4fea439b76916abc34b2df129" + integrity sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw== + +"@types/yargs@^16.0.0": + version "16.0.4" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977" + integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw== + dependencies: + "@types/yargs-parser" "*" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@yarnpkg/lockfile@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" + integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== + +a-sync-waterfall@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" + integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +abstract-leveldown@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" + integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: + version "2.7.2" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" + integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" + integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@^6.2.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" + integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +abstract-leveldown@~2.6.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" + integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== + dependencies: + xtend "~4.0.0" + +abstract-leveldown@~6.2.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.2.3.tgz#036543d87e3710f2528e47040bc3261b77a9a8eb" + integrity sha512-BsLm5vFMRUrrLeCcRc+G0t2qOaTzpoJQLOubq2XM72eNpjF5UdU5o/5NvlNhx95XHcAvcl8OMXr4mlg/fRgUXQ== + dependencies: + buffer "^5.5.0" + immediate "^3.2.3" + level-concat-iterator "~2.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + +adm-zip@^0.4.16: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= + +aes-js@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +ajv@^5.2.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + +ansi-colors@4.1.1, ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-escapes@^4.3.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +antlr4ts@^0.5.0-alpha.4: + version "0.5.0-alpha.4" + resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" + integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== + +anymatch@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" + integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA== + dependencies: + micromatch "^2.1.5" + normalize-path "^2.0.0" + +anymatch@^3.0.3, anymatch@~3.1.1, anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + integrity sha1-ZBqlXft9am8KgUHEucCqULbCTdU= + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8= + dependencies: + arr-flatten "^1.0.1" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.0.1, arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-back@^1.0.3, array-back@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" + integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + dependencies: + typical "^2.6.0" + +array-back@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + +array-back@^3.0.1, array-back@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0" + integrity sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q== + +array-back@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e" + integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg== + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-uniq@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asap@^2.0.3, asap@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-eventemitter@^0.2.2, async-eventemitter@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" + integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== + dependencies: + async "^2.4.0" + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" + integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== + dependencies: + lodash "^4.17.11" + +async@^1.4.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + +async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +at-least-node@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" + integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +await-sleep@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/await-sleep/-/await-sleep-0.0.1.tgz#044532e49f1f4219d2030d79f517d64569a27d50" + integrity sha512-H3X3eAxwGpeNIk/yvFOs8g7500Q1YvzrxjSC9TNgLGtjrMFxPwhDdcT34QNs2iGWpZ+5WKkMJdjDoYs+Sw+TaA== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.0.14, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.17.4" + source-map "^0.5.7" + trim-right "^1.0.1" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babelify@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" + integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= + dependencies: + babel-core "^6.0.14" + object-assign "^4.0.0" + +babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +backoff@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" + integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= + dependencies: + precond "0.2" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base-x@^3.0.2, base-x@^3.0.8: + version "3.0.9" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.9.tgz#6349aaabb58526332de9f60995e548a53fe21320" + integrity sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ== + dependencies: + safe-buffer "^5.0.1" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + +bignumber.js@^9.0.0, bignumber.js@^9.0.1: + version "9.0.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673" + integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw== + +"bignumber.js@git+https://github.com/debris/bignumber.js#master": + version "2.0.7" + resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9" + +"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": + version "2.0.7" + resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip39@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" + integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bip39@^2.2.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c" + integrity sha512-RrnQRG2EgEoqO24ea+Q/fftuPUZLmrEM3qNhhGsA3PbaXaCW791LTzPuVyx/VprXQcTbPJ3K3UeTna8ZnVl2sg== + dependencies: + create-hash "^1.1.0" + pbkdf2 "^3.0.9" + randombytes "^2.0.1" + safe-buffer "^5.0.1" + unorm "^1.3.3" + +bip66@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" + integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= + dependencies: + safe-buffer "^5.0.1" + +blakejs@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.1.tgz#bf313053978b2cd4c444a48795710be05c785702" + integrity sha512-bLG6PHOCZJKNshTjGRBvET0vTciwQE6zFKOKKXPDJfwFBd4Ac0yBfPZqcGvGJap50l7ktvlpFqc2jGVaUgbJgg== + +bluebird@^3.5.0, bluebird@^3.5.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.8.0: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1, bn.js@^5.1.2, bn.js@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + +body-parser@1.19.1, body-parser@^1.16.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.1.tgz#1499abbaa9274af3ecc9f6f10396c995943e31d4" + integrity sha512-8ljfQi5eBk8EJfECMrgqNGWPEY5jWP+1IzkzkGdFFEwFQZZyaZ21UqdaHktgiMlH0xLHqIFtE/u2OYE5dOtViA== + dependencies: + bytes "3.1.1" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.8.1" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.9.6" + raw-body "2.4.2" + type-is "~1.6.18" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc= + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6, browserify-aes@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.17.5: + version "4.19.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.19.1.tgz#4ac0435b35ab655896c31d53018b6dd5e9e4c9a3" + integrity sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A== + dependencies: + caniuse-lite "^1.0.30001286" + electron-to-chromium "^1.4.17" + escalade "^3.1.1" + node-releases "^2.0.1" + picocolors "^1.0.0" + +bs58@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" + integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= + dependencies: + base-x "^3.0.2" + +bs58check@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" + integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== + dependencies: + bs58 "^4.0.0" + create-hash "^1.1.0" + safe-buffer "^5.1.2" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + +buffer@^5.0.5, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bufferutil@^4.0.1: + version "4.0.6" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.6.tgz#ebd6c67c7922a0e902f053e5d8be5ec850e48433" + integrity sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw== + dependencies: + node-gyp-build "^4.3.0" + +bytes@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" + integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== + +bytewise-core@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" + integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= + dependencies: + typewise-core "^1.2" + +bytewise@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" + integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= + dependencies: + bytewise-core "^1.2.2" + typewise "^1.0.3" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cacheable-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" + integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^3.0.0" + lowercase-keys "^2.0.0" + normalize-url "^4.1.0" + responselike "^1.0.2" + +cachedown@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" + integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= + dependencies: + abstract-leveldown "^2.4.1" + lru-cache "^3.2.0" + +call-bind@^1.0.0, call-bind@^1.0.2, call-bind@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30001286: + version "1.0.30001301" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz#ebc9086026534cab0dab99425d9c3b4425e5f450" + integrity sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA== + +caseless@^0.12.0, caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +cbor@^5.0.2: + version "5.2.0" + resolved "https://registry.yarnpkg.com/cbor/-/cbor-5.2.0.tgz#4cca67783ccd6de7b50ab4ed62636712f287a67c" + integrity sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A== + dependencies: + bignumber.js "^9.0.1" + nofilter "^1.0.4" + +chai@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" + integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +"charenc@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" + integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= + +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + +checkpoint-store@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" + integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= + dependencies: + functional-red-black-tree "^1.0.1" + +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + +chokidar@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg= + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +chokidar@^3.4.0, chokidar@^3.4.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +ci-info@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.0.tgz#b4ed1fb6818dea4803a55c623041f9165d2066b2" + integrity sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw== + +cids@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" + integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== + dependencies: + buffer "^5.5.0" + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "^1.0.0" + multihashes "~0.4.15" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw== + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + +clone@2.1.2, clone@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colors@1.4.0, colors@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" + integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.8: + version "1.2.9" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" + integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== + +command-line-args@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + +command-line-args@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.2.0.tgz#087b02748272169741f1fd7c785b295df079b9be" + integrity sha512-4zqtU1hYsSJzcJBOcNZIbW5Fbk9BkjCp1pZVhQKoRaWL5J7N4XphDLwo8aWwdQpTugxwu+jf9u2ZhkXiqp5Z6A== + dependencies: + array-back "^3.1.0" + find-replace "^3.0.0" + lodash.camelcase "^4.3.0" + typical "^4.0.0" + +command-line-usage@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/command-line-usage/-/command-line-usage-6.1.1.tgz#c908e28686108917758a49f45efb4f02f76bc03f" + integrity sha512-F59pEuAR9o1SF/bD0dQBDluhpT4jJQNWUHEuVBqpDmCUo6gPjCi+m9fCWnWZVR/oG6cMTUms4h+3NPl74wGXvA== + dependencies: + array-back "^4.0.1" + chalk "^2.4.2" + table-layout "^1.0.1" + typical "^5.2.0" + +commander@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" + integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +commander@3.0.2, commander@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + +commander@^2.9.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.1, concat-stream@^1.6.0, concat-stream@^1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-hash@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" + integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== + dependencies: + cids "^0.7.1" + multicodec "^0.5.5" + multihashes "^0.4.15" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.4.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.1, cookie@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + +cookiejar@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" + integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-js-pure@^3.0.1: + version "3.20.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.20.3.tgz#6cc4f36da06c61d95254efc54024fe4797fd5d02" + integrity sha512-Q2H6tQ5MtPtcC7f3HxJ48i4Q7T9ybPKgvWyuH7JXIoNa2pm0KuBnycsET/qw1SLLZYfbsbrZQNMeIOClb+6WIA== + +core-js@^2.4.0, core-js@^2.5.0: + version "2.6.12" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +cors@^2.8.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +crc-32@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" + integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA== + dependencies: + exit-on-epipe "~1.0.1" + printj "~1.1.0" + +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-fetch@^2.1.0, cross-fetch@^2.1.1: + version "2.2.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.5.tgz#afaf5729f3b6c78d89c9296115c9f142541a5705" + integrity sha512-xqYAhQb4NhCJSRym03dwxpP1bYXpK3y7UN83Bo2WFi3x1Zmzn0SL/6xGoPr+gpt4WmNrgCCX3HPysvOwFOW36w== + dependencies: + node-fetch "2.6.1" + whatwg-fetch "2.0.4" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +"crypt@>= 0.0.1": + version "0.0.2" + resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" + integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= + +crypto-browserify@3.12.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +crypto-js@^3.1.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.3.0.tgz#846dd1cce2f68aacfa156c8578f926a609b7976b" + integrity sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q== + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@4, debug@^4.1.0, debug@^4.1.1: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== + dependencies: + ms "2.1.2" + +debug@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" + integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== + dependencies: + ms "2.1.2" + +debug@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +decimal.js@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783" + integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ== + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +decompress-response@^3.2.0, decompress-response@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" + integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= + dependencies: + mimic-response "^1.0.0" + +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + +deep-equal@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + 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" + +deep-extend@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +defer-to-connect@^1.0.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" + integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== + +deferred-leveldown@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" + integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== + dependencies: + abstract-leveldown "~2.6.0" + +deferred-leveldown@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" + integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== + dependencies: + abstract-leveldown "~5.0.0" + inherits "^2.0.3" + +deferred-leveldown@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-5.3.0.tgz#27a997ad95408b61161aa69bd489b86c71b78058" + integrity sha512-a59VOT+oDy7vtAbLRCZwWgxu2BaCfd5Hk7wxJd48ei7I+nsg8Orlb9CLG0PMZienk9BSUKgeAqkO2+Lw+1+Ukw== + dependencies: + abstract-leveldown "~6.2.1" + inherits "^2.0.3" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= + dependencies: + repeating "^2.0.0" + +diff-sequences@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.4.0.tgz#d783920ad8d06ec718a060d00196dfef25b132a5" + integrity sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww== + +diff@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" + integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== + +diff@3.5.0, diff@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-walk@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" + integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== + +dotignore@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/dotignore/-/dotignore-0.1.2.tgz#f942f2200d28c3a76fbdd6f0ee9f3257c8a2e905" + integrity sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw== + dependencies: + minimatch "^3.0.4" + +drbg.js@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" + integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= + dependencies: + browserify-aes "^1.0.6" + create-hash "^1.1.2" + create-hmac "^1.1.4" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +electron-to-chromium@^1.3.47, electron-to-chromium@^1.4.17: + version "1.4.51" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz#a432f5a5d983ace79278a33057300cf949627e63" + integrity sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ== + +elliptic@6.5.4, elliptic@>=6.5.3, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.5.4: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +encoding-down@5.0.4, encoding-down@~5.0.0: + version "5.0.4" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" + integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== + dependencies: + abstract-leveldown "^5.0.0" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + xtend "^4.0.1" + +encoding-down@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" + integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== + dependencies: + abstract-leveldown "^6.2.1" + inherits "^2.0.3" + level-codec "^9.0.0" + level-errors "^2.0.0" + +encoding@^0.1.11: + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== + dependencies: + iconv-lite "^0.6.2" + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.0: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +env-paths@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + +eol@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/eol/-/eol-0.9.1.tgz#f701912f504074be35c6117a5c4ade49cd547acd" + integrity sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg== + +errno@~0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.18.5, es-abstract@^1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" + integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.1.1" + get-symbol-description "^1.0.0" + has "^1.0.3" + has-symbols "^1.0.2" + internal-slot "^1.0.3" + is-callable "^1.2.4" + is-negative-zero "^2.0.1" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.1" + is-string "^1.0.7" + is-weakref "^1.0.1" + object-inspect "^1.11.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.4" + string.prototype.trimstart "^1.0.4" + unbox-primitive "^1.0.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eth-block-tracker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" + integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== + dependencies: + eth-query "^2.1.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.3" + ethjs-util "^0.1.3" + json-rpc-engine "^3.6.0" + pify "^2.3.0" + tape "^4.6.3" + +eth-ens-namehash@2.0.8, eth-ens-namehash@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" + integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= + dependencies: + idna-uts46-hx "^2.3.1" + js-sha3 "^0.5.7" + +eth-gas-reporter@^0.2.24: + version "0.2.24" + resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.2.24.tgz#768721fec7de02b566e4ebfd123466d275d7035c" + integrity sha512-RbXLC2bnuPHzIMU/rnLXXlb6oiHEEKu7rq2UrAX/0mfo0Lzrr/kb9QTjWjfz8eNvc+uu6J8AuBwI++b+MLNI2w== + dependencies: + "@ethersproject/abi" "^5.0.0-beta.146" + "@solidity-parser/parser" "^0.14.0" + cli-table3 "^0.5.0" + colors "1.4.0" + ethereumjs-util "6.2.0" + ethers "^4.0.40" + fs-readdir-recursive "^1.1.0" + lodash "^4.17.14" + markdown-table "^1.1.3" + mocha "^7.1.1" + req-cwd "^2.0.0" + request "^2.88.0" + request-promise-native "^1.0.5" + sha1 "^1.1.1" + sync-request "^6.0.0" + +eth-json-rpc-infura@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" + integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== + dependencies: + cross-fetch "^2.1.1" + eth-json-rpc-middleware "^1.5.0" + json-rpc-engine "^3.4.0" + json-rpc-error "^2.0.0" + +eth-json-rpc-middleware@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" + integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== + dependencies: + async "^2.5.0" + eth-query "^2.1.2" + eth-tx-summary "^3.1.2" + ethereumjs-block "^1.6.0" + ethereumjs-tx "^1.3.3" + ethereumjs-util "^5.1.2" + ethereumjs-vm "^2.1.0" + fetch-ponyfill "^4.0.0" + json-rpc-engine "^3.6.0" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + tape "^4.6.3" + +eth-lib@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" + integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + +eth-lib@^0.1.26: + version "0.1.29" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" + integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" + integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= + dependencies: + json-rpc-random-id "^1.0.0" + xtend "^4.0.1" + +eth-sig-util@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" + integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + dependencies: + buffer "^5.2.1" + elliptic "^6.4.0" + ethereumjs-abi "0.6.5" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.0" + tweetnacl-util "^0.15.0" + +eth-sig-util@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" + integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= + dependencies: + ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" + ethereumjs-util "^5.1.1" + +eth-sig-util@^2.5.2: + version "2.5.4" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5" + integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A== + dependencies: + ethereumjs-abi "0.6.8" + ethereumjs-util "^5.1.1" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.0" + +eth-tx-summary@^3.1.2: + version "3.2.4" + resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" + integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== + dependencies: + async "^2.1.2" + clone "^2.0.0" + concat-stream "^1.5.1" + end-of-stream "^1.1.0" + eth-query "^2.0.2" + ethereumjs-block "^1.4.1" + ethereumjs-tx "^1.1.1" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.6.0" + through2 "^2.0.3" + +ethashjs@~0.0.7: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== + dependencies: + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" + miller-rabin "^4.0.0" + +ethereum-bloom-filters@^1.0.6: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz#3ca07f4aed698e75bd134584850260246a5fed8a" + integrity sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA== + dependencies: + js-sha3 "^0.8.0" + +ethereum-common@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" + integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== + +ethereum-common@^0.0.18: + version "0.0.18" + resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" + integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= + +ethereum-cryptography@^0.1.2, ethereum-cryptography@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz#8d6143cfc3d74bf79bbd8edecdf29e4ae20dd191" + integrity sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ== + dependencies: + "@types/pbkdf2" "^3.0.0" + "@types/secp256k1" "^4.0.1" + blakejs "^1.1.0" + browserify-aes "^1.2.0" + bs58check "^2.1.2" + create-hash "^1.2.0" + create-hmac "^1.1.7" + hash.js "^1.1.7" + keccak "^3.0.0" + pbkdf2 "^3.0.17" + randombytes "^2.1.0" + safe-buffer "^5.1.2" + scrypt-js "^3.0.0" + secp256k1 "^4.0.1" + setimmediate "^1.0.5" + +ethereum-input-data-decoder@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ethereum-input-data-decoder/-/ethereum-input-data-decoder-0.3.0.tgz#9c6fcedc984a0477367c657e49943b3d30af48f2" + integrity sha512-i6BDTbHhwODJ1SCh85hVY93KdT49e4iAkuA+xNVnBrywhCsywMPmDf0lM7AErLa0VWjgOqXkIr6wmsn+gRIj/A== + dependencies: + bn.js "^4.11.8" + buffer "^5.2.1" + ethereumjs-abi "^0.6.7" + ethers "^4.0.27" + is-buffer "^2.0.3" + meow "^5.0.0" + +ethereum-waffle@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/ethereum-waffle/-/ethereum-waffle-3.4.0.tgz#990b3c6c26db9c2dd943bf26750a496f60c04720" + integrity sha512-ADBqZCkoSA5Isk486ntKJVjFEawIiC+3HxNqpJqONvh3YXBTNiRfXvJtGuAFLXPG91QaqkGqILEHANAo7j/olQ== + dependencies: + "@ethereum-waffle/chai" "^3.4.0" + "@ethereum-waffle/compiler" "^3.4.0" + "@ethereum-waffle/mock-contract" "^3.3.0" + "@ethereum-waffle/provider" "^3.4.0" + ethers "^5.0.1" + +ethereumjs-abi@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.7, ethereumjs-abi@^0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" + integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": + version "0.6.8" + resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0" + dependencies: + bn.js "^4.11.8" + ethereumjs-util "^6.0.0" + +ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" + integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== + dependencies: + ethereumjs-util "^6.0.0" + rlp "^2.2.1" + safe-buffer "^5.1.1" + +ethereumjs-account@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" + integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== + dependencies: + ethereumjs-util "^5.0.0" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.0, ethereumjs-block@~2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" + integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== + dependencies: + async "^2.0.1" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.1" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" + integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== + dependencies: + async "^2.0.1" + ethereum-common "0.2.0" + ethereumjs-tx "^1.2.2" + ethereumjs-util "^5.0.0" + merkle-patricia-tree "^2.1.2" + +ethereumjs-blockchain@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.4.tgz#30f2228dc35f6dcf94423692a6902604ae34960f" + integrity sha512-zCxaRMUOzzjvX78DTGiKjA+4h2/sF0OYL1QuPux0DHpyq8XiNoF5GYHtb++GUxVlMsMfZV7AVyzbtgcRdIcEPQ== + dependencies: + async "^2.6.1" + ethashjs "~0.0.7" + ethereumjs-block "~2.2.2" + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.1.0" + flow-stoplight "^1.0.0" + level-mem "^3.0.1" + lru-cache "^5.1.1" + rlp "^2.2.2" + semaphore "^1.1.0" + +ethereumjs-common@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" + integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== + +ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz#2065dbe9214e850f2e955a80e650cb6999066979" + integrity sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA== + +ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" + integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== + dependencies: + ethereumjs-common "^1.5.0" + ethereumjs-util "^6.0.0" + +ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: + version "1.3.7" + resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" + integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== + dependencies: + ethereum-common "^0.0.18" + ethereumjs-util "^5.0.0" + +ethereumjs-util@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960" + integrity sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + ethjs-util "0.1.6" + keccak "^2.0.0" + rlp "^2.2.3" + secp256k1 "^3.0.1" + +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" + integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.3" + +ethereumjs-util@^4.3.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.1.tgz#f4bf9b3b515a484e3cc8781d61d9d980f7c83bd0" + integrity sha512-WrckOZ7uBnei4+AKimpuF1B3Fv25OmoRgmYCpGsP7u8PFxXAmAgiJSYT2kRWnt6fVIlKaQlZvuwXp7PIrmn3/w== + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + rlp "^2.0.0" + +ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz#a833f0e5fca7e5b361384dc76301a721f537bf65" + integrity sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ== + dependencies: + bn.js "^4.11.0" + create-hash "^1.1.2" + elliptic "^6.5.2" + ethereum-cryptography "^0.1.3" + ethjs-util "^0.1.3" + rlp "^2.0.0" + safe-buffer "^5.1.1" + +ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.2, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.3.tgz#b55d7b64dde3e3e45749e4c41288238edec32d23" + integrity sha512-y+82tEbyASO0K0X1/SRhbJJoAlfcvq8JbrG4a5cjrOks7HS/36efU/0j2flxCPOUM++HFahk33kr/ZxyC4vNuw== + dependencies: + "@types/bn.js" "^5.1.0" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + rlp "^2.2.4" + +ethereumjs-vm@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.2.0.tgz#e885e861424e373dbc556278f7259ff3fca5edab" + integrity sha512-X6qqZbsY33p5FTuZqCnQ4+lo957iUJMM6Mpa6bL4UW0dxM6WmDSHuI4j/zOp1E2TDKImBGCJA9QPfc08PaNubA== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + core-js-pure "^3.0.1" + ethereumjs-account "^3.0.0" + ethereumjs-block "^2.2.2" + ethereumjs-blockchain "^4.0.3" + ethereumjs-common "^1.5.0" + ethereumjs-tx "^2.1.2" + ethereumjs-util "^6.2.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + util.promisify "^1.0.0" + +ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" + integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== + dependencies: + async "^2.1.2" + async-eventemitter "^0.2.2" + ethereumjs-account "^2.0.3" + ethereumjs-block "~2.2.0" + ethereumjs-common "^1.1.0" + ethereumjs-util "^6.0.0" + fake-merkle-patricia-tree "^1.0.1" + functional-red-black-tree "^1.0.1" + merkle-patricia-tree "^2.3.2" + rustbn.js "~0.2.0" + safe-buffer "^5.1.1" + +ethereumjs-wallet@0.6.5, ethereumjs-wallet@^0.6.0: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" + integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== + dependencies: + aes-js "^3.1.1" + bs58check "^2.1.2" + ethereum-cryptography "^0.1.3" + ethereumjs-util "^6.0.0" + randombytes "^2.0.6" + safe-buffer "^5.1.2" + scryptsy "^1.2.1" + utf8 "^3.0.0" + uuid "^3.3.2" + +ethers@^4.0.27, ethers@^4.0.40: + version "4.0.49" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" + integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== + dependencies: + aes-js "3.0.0" + bn.js "^4.11.9" + elliptic "6.5.4" + hash.js "1.1.3" + js-sha3 "0.5.7" + scrypt-js "2.0.4" + setimmediate "1.0.4" + uuid "2.0.1" + xmlhttprequest "1.8.0" + +ethers@^5.0.1, ethers@^5.0.2, ethers@^5.4.7, ethers@^5.5.2, ethers@^5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.5.3.tgz#1e361516711c0c3244b6210e7e3ecabf0c75fca0" + integrity sha512-fTT4WT8/hTe/BLwRUtl7I5zlpF3XC3P/Xwqxc5AIP2HGlH15qpmjs0Ou78az93b1rLITzXLFxoNX63B8ZbUd7g== + dependencies: + "@ethersproject/abi" "5.5.0" + "@ethersproject/abstract-provider" "5.5.1" + "@ethersproject/abstract-signer" "5.5.0" + "@ethersproject/address" "5.5.0" + "@ethersproject/base64" "5.5.0" + "@ethersproject/basex" "5.5.0" + "@ethersproject/bignumber" "5.5.0" + "@ethersproject/bytes" "5.5.0" + "@ethersproject/constants" "5.5.0" + "@ethersproject/contracts" "5.5.0" + "@ethersproject/hash" "5.5.0" + "@ethersproject/hdnode" "5.5.0" + "@ethersproject/json-wallets" "5.5.0" + "@ethersproject/keccak256" "5.5.0" + "@ethersproject/logger" "5.5.0" + "@ethersproject/networks" "5.5.2" + "@ethersproject/pbkdf2" "5.5.0" + "@ethersproject/properties" "5.5.0" + "@ethersproject/providers" "5.5.2" + "@ethersproject/random" "5.5.1" + "@ethersproject/rlp" "5.5.0" + "@ethersproject/sha2" "5.5.0" + "@ethersproject/signing-key" "5.5.0" + "@ethersproject/solidity" "5.5.0" + "@ethersproject/strings" "5.5.0" + "@ethersproject/transactions" "5.5.0" + "@ethersproject/units" "5.5.0" + "@ethersproject/wallet" "5.5.0" + "@ethersproject/web" "5.5.1" + "@ethersproject/wordlists" "5.5.0" + +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + +ethjs-util@0.1.6, ethjs-util@^0.1.3: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" + integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== + dependencies: + is-hex-prefixed "1.0.0" + strip-hex-prefix "1.0.0" + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +eventemitter3@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" + integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +exit-on-epipe@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692" + integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw== + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s= + dependencies: + is-posix-bracket "^0.1.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc= + dependencies: + fill-range "^2.1.0" + +expect@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.4.6.tgz#f335e128b0335b6ceb4fcab67ece7cbd14c942e6" + integrity sha512-1M/0kAALIaj5LaG66sFJTbRsWTADnylly82cu4bspI0nl+pgP4E6Bh/aqdHlTUjul06K7xQnnrAoqfxVU0+/ag== + dependencies: + "@jest/types" "^27.4.2" + jest-get-type "^27.4.0" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + +express@^4.14.0: + version "4.17.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.2.tgz#c18369f265297319beed4e5558753cc8c1364cb3" + integrity sha512-oxlxJxcQlYwqPWKVJJtvQiwHgosH/LrLSPA+H4UxpyvSS6jC5aH+5MoHFM+KABgTOt0APue4w66Ha8jCUo9QGg== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.4.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.9.6" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.17.2" + serve-static "1.14.2" + setprototypeof "1.2.0" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +ext@^1.1.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.6.0.tgz#3871d50641e874cc172e2b53f919842d19db4c52" + integrity sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg== + dependencies: + type "^2.5.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE= + dependencies: + is-extglob "^1.0.0" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fake-merkle-patricia-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" + integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= + dependencies: + checkpoint-store "^1.1.0" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + +fetch-ponyfill@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" + integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= + dependencies: + node-fetch "~1.7.1" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY= + +fill-range@^2.1.0: + version "2.2.4" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" + integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^3.0.0" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-package-json@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/find-package-json/-/find-package-json-1.2.0.tgz#4057d1b943f82d8445fe52dc9cf456f6b8b58083" + integrity sha512-+SOGcLGYDJHtyqHd87ysBhmaeQ95oWspDKnMXBrnQ9Eq4OkLNqejgoaD8xVWu6GPa0B6roa6KinCMEMcVeqONw== + +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + +find-replace@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-3.0.0.tgz#3e7e23d3b05167a76f770c9fbd5258b0def68c38" + integrity sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ== + dependencies: + array-back "^3.0.1" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-yarn-workspace-root@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" + integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== + dependencies: + fs-extra "^4.0.3" + micromatch "^3.1.4" + +find-yarn-workspace-root@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" + integrity sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ== + dependencies: + micromatch "^4.0.2" + +flat@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" + integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== + dependencies: + is-buffer "~2.0.3" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +flow-stoplight@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" + integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= + +follow-redirects@^1.12.1: + version "1.14.7" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" + integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== + +for-each@^0.3.3, for-each@~0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= + dependencies: + for-in "^1.0.1" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^2.2.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fp-ts@1.19.3: + version "1.19.3" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.3.tgz#261a60d1088fbff01f91256f91d21d0caaaaa96f" + integrity sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg== + +fp-ts@^1.0.0: + version "1.19.5" + resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-1.19.5.tgz#3da865e585dfa1fdfd51785417357ac50afc520a" + integrity sha512-wDNqTimnzs8QqpldiId9OavWK2NptormjXnRJTQecNjzwfyp6P/8s/zG8e4h3ja3oqkKaY72UlTjQYt/1yXf9A== + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +fs-extra@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" + integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + klaw "^1.0.0" + path-is-absolute "^1.0.0" + rimraf "^2.2.8" + +fs-extra@^4.0.2, fs-extra@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" + integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^7.0.0, fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-readdir-recursive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" + integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.0.0: + version "1.2.13" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@^2.3.2, fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +ganache-core@^2.13.2: + version "2.13.2" + resolved "https://registry.yarnpkg.com/ganache-core/-/ganache-core-2.13.2.tgz#27e6fc5417c10e6e76e2e646671869d7665814a3" + integrity sha512-tIF5cR+ANQz0+3pHWxHjIwHqFXcVo0Mb+kcsNhglNFALcYo49aQpnS9dqHartqPfMFjiHh/qFoD3mYK0d/qGgw== + dependencies: + abstract-leveldown "3.0.0" + async "2.6.2" + bip39 "2.5.0" + cachedown "1.0.0" + clone "2.1.2" + debug "3.2.6" + encoding-down "5.0.4" + eth-sig-util "3.0.0" + ethereumjs-abi "0.6.8" + ethereumjs-account "3.0.0" + ethereumjs-block "2.2.2" + ethereumjs-common "1.5.0" + ethereumjs-tx "2.1.2" + ethereumjs-util "6.2.1" + ethereumjs-vm "4.2.0" + heap "0.2.6" + keccak "3.0.1" + level-sublevel "6.6.4" + levelup "3.1.1" + lodash "4.17.20" + lru-cache "5.1.1" + merkle-patricia-tree "3.0.0" + patch-package "6.2.2" + seedrandom "3.0.1" + source-map-support "0.5.12" + tmp "0.1.0" + web3-provider-engine "14.2.1" + websocket "1.0.32" + optionalDependencies: + ethereumjs-wallet "0.6.5" + web3 "1.2.11" + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-port@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + integrity sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw= + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= + +get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== + dependencies: + pump "^3.0.0" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q= + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg= + dependencies: + is-glob "^2.0.0" + +glob-parent@~5.1.0, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@7.1.7, glob@~7.1.7: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +got@9.6.0: + version "9.6.0" + resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" + integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== + dependencies: + "@sindresorhus/is" "^0.14.0" + "@szmarczak/http-timer" "^1.1.2" + cacheable-request "^6.0.0" + decompress-response "^3.3.0" + duplexer3 "^0.1.4" + get-stream "^4.1.0" + lowercase-keys "^1.0.1" + mimic-response "^1.0.1" + p-cancelable "^1.0.0" + to-readable-stream "^1.0.0" + url-parse-lax "^3.0.0" + +got@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" + integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== + dependencies: + decompress-response "^3.2.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-plain-obj "^1.1.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + isurl "^1.0.0-alpha5" + lowercase-keys "^1.0.0" + p-cancelable "^0.3.0" + p-timeout "^1.1.1" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + url-parse-lax "^1.0.0" + url-to-options "^1.0.1" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: + version "4.2.9" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" + integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== + +growl@1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" + integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +hardhat-gas-reporter@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.7.tgz#b0e06a4f5a4da2369354991b6fa32ff002170573" + integrity sha512-calJH1rbhUFwCnw0odJb3Cw+mDmBIsHdVyutsHhA3RY6JELyFVaVxCnITYGr/crkmHqt4tQCYROy7ty6DTLkuA== + dependencies: + array-uniq "1.0.3" + eth-gas-reporter "^0.2.24" + sha1 "^1.1.1" + +hardhat-watcher@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/hardhat-watcher/-/hardhat-watcher-2.1.1.tgz#8b05fec429ed45da11808bbf6054a90f3e34c51a" + integrity sha512-zilmvxAYD34IofBrwOliQn4z92UiDmt2c949DW4Gokf0vS0qk4YTfVCi/LmUBICThGygNANE3WfnRTpjCJGtDA== + dependencies: + chokidar "^3.4.3" + +hardhat@^2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.8.3.tgz#94cccc92d18c6361d9fbbc5d77a4fabf0166a396" + integrity sha512-VxqiVTSayRoeLHly8zKnlvtWoG8sroTP4vl8GHuj7OjfAdrHu4Blk7NBJ5+Rl8cmMEp6CuZtDaDmcHJIRTwEPA== + dependencies: + "@ethereumjs/block" "^3.6.0" + "@ethereumjs/blockchain" "^5.5.0" + "@ethereumjs/common" "^2.6.0" + "@ethereumjs/tx" "^3.4.0" + "@ethereumjs/vm" "^5.6.0" + "@ethersproject/abi" "^5.1.2" + "@sentry/node" "^5.18.1" + "@solidity-parser/parser" "^0.14.0" + "@types/bn.js" "^5.1.0" + "@types/lru-cache" "^5.1.0" + abort-controller "^3.0.0" + adm-zip "^0.4.16" + ansi-escapes "^4.3.0" + chalk "^2.4.2" + chokidar "^3.4.0" + ci-info "^2.0.0" + debug "^4.1.1" + enquirer "^2.3.0" + env-paths "^2.2.0" + eth-sig-util "^2.5.2" + ethereum-cryptography "^0.1.2" + ethereumjs-abi "^0.6.8" + ethereumjs-util "^7.1.3" + find-up "^2.1.0" + fp-ts "1.19.3" + fs-extra "^7.0.1" + glob "^7.1.3" + https-proxy-agent "^5.0.0" + immutable "^4.0.0-rc.12" + io-ts "1.10.4" + lodash "^4.17.11" + merkle-patricia-tree "^4.2.2" + mnemonist "^0.38.0" + mocha "^7.2.0" + node-fetch "^2.6.0" + qs "^6.7.0" + raw-body "^2.4.1" + resolve "1.17.0" + semver "^6.3.0" + slash "^3.0.0" + solc "0.7.3" + source-map-support "^0.5.13" + stacktrace-parser "^0.1.10" + "true-case-path" "^2.2.1" + tsort "0.0.1" + uuid "^8.3.2" + ws "^7.4.6" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-bigints@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" + integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbol-support-x@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" + integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== + +has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + +has-to-string-tag-x@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" + integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== + dependencies: + has-symbol-support-x "^1.4.1" + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.3, has@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" + integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.0" + +hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +heap@0.2.6: + version "0.2.6" + resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" + integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= + +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +http-basic@^8.1.1: + version "8.1.3" + resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-8.1.3.tgz#a7cabee7526869b9b710136970805b1004261bbf" + integrity sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw== + dependencies: + caseless "^0.12.0" + concat-stream "^1.6.2" + http-response-object "^3.0.1" + parse-cache-control "^1.0.1" + +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + +http-errors@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" + integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.1" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= + +http-response-object@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.2.tgz#7f435bb210454e4360d074ef1f989d5ea8aa9810" + integrity sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA== + dependencies: + "@types/node" "^10.0.3" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iconv-lite@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +idna-uts46-hx@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" + integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== + dependencies: + punycode "2.1.0" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +immediate@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.3.0.tgz#1aef225517836bcdf7f2a2de2600c79ff0269266" + integrity sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q== + +immediate@~3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +immutable@^4.0.0-rc.12: + version "4.0.0" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" + integrity sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + +io-ts@1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-1.10.4.tgz#cd5401b138de88e4f920adbcb7026e2d1967e6e2" + integrity sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g== + dependencies: + fp-ts "^1.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arguments@^1.0.4: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" + integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.3, is-buffer@~2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" + integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-core-module@^2.2.0, is-core-module@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" + integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + dependencies: + has "^1.0.3" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-dotfile@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" + integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE= + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ= + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA= + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== + +is-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" + integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-function@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08" + integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ== + +is-generator-function@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM= + dependencies: + is-extglob "^1.0.0" + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hex-prefixed@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" + integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= + +is-negative-zero@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" + integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.2.tgz#a56552e1c665c9e950b4a025461da87e72f86fcf" + integrity sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA== + +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU= + +is-regex@^1.0.4, is-regex@^1.1.4, is-regex@~1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-retry-allowed@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" + integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== + +is-shared-array-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" + integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== + +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.3, is-typed-array@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" + integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + +is-typedarray@^1.0.0, is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-url@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-weakref@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-wsl@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isomorphic-fetch@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-instrument@^5.0.4: + version "5.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz#7b49198b657b27a730b8e9cb601f1e1bff24c59a" + integrity sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +isurl@^1.0.0-alpha5: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" + integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== + dependencies: + has-to-string-tag-x "^1.2.0" + is-object "^1.0.1" + +jest-diff@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.4.6.tgz#93815774d2012a2cbb6cf23f84d48c7a2618f98d" + integrity sha512-zjaB0sh0Lb13VyPsd92V7HkqF6yKRH9vm33rwBt7rPYrpQvS1nCvlIy2pICbKta+ZjWngYLNn4cCK4nyZkjS/w== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.4.0" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" + +jest-get-type@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.4.0.tgz#7503d2663fffa431638337b3998d39c5e928e9b5" + integrity sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ== + +jest-haste-map@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.4.6.tgz#c60b5233a34ca0520f325b7e2cc0a0140ad0862a" + integrity sha512-0tNpgxg7BKurZeFkIOvGCkbmOHbLFf4LUQOxrQSMjvrQaQe3l6E8x6jYC1NuWkGo5WDdbr8FEzUxV2+LWNawKQ== + dependencies: + "@jest/types" "^27.4.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^27.4.0" + jest-serializer "^27.4.0" + jest-util "^27.4.2" + jest-worker "^27.4.6" + micromatch "^4.0.4" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.3.2" + +jest-matcher-utils@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.4.6.tgz#53ca7f7b58170638590e946f5363b988775509b8" + integrity sha512-XD4PKT3Wn1LQnRAq7ZsTI0VRuEc9OrCPFiO1XL7bftTGmfNF0DcEwMHRgqiu7NGf8ZoZDREpGrCniDkjt79WbA== + dependencies: + chalk "^4.0.0" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + pretty-format "^27.4.6" + +jest-message-util@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.4.6.tgz#9fdde41a33820ded3127465e1a5896061524da31" + integrity sha512-0p5szriFU0U74czRSFjH6RyS7UYIAkn/ntwMuOwTGWrQIOh5NzXXrq72LOqIkJKKvFbPq+byZKuBz78fjBERBA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^27.4.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.4" + pretty-format "^27.4.6" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-regex-util@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.4.0.tgz#e4c45b52653128843d07ad94aec34393ea14fbca" + integrity sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg== + +jest-serializer@^27.4.0: + version "27.4.0" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.4.0.tgz#34866586e1cae2388b7d12ffa2c7819edef5958a" + integrity sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^27.0.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.4.6.tgz#e2a3b4fff8bdce3033f2373b2e525d8b6871f616" + integrity sha512-fafUCDLQfzuNP9IRcEqaFAMzEe7u5BF7mude51wyWv7VRex60WznZIC7DfKTgSIlJa8aFzYmXclmN328aqSDmQ== + dependencies: + "@babel/core" "^7.7.2" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/traverse" "^7.7.2" + "@babel/types" "^7.0.0" + "@jest/transform" "^27.4.6" + "@jest/types" "^27.4.2" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.1.5" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^27.4.6" + graceful-fs "^4.2.4" + jest-diff "^27.4.6" + jest-get-type "^27.4.0" + jest-haste-map "^27.4.6" + jest-matcher-utils "^27.4.6" + jest-message-util "^27.4.6" + jest-util "^27.4.2" + natural-compare "^1.4.0" + pretty-format "^27.4.6" + semver "^7.3.2" + +jest-util@^27.0.6, jest-util@^27.4.2: + version "27.4.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.4.2.tgz#ed95b05b1adfd761e2cda47e0144c6a58e05a621" + integrity sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA== + dependencies: + "@jest/types" "^27.4.2" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.4" + picomatch "^2.2.3" + +jest-worker@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.4.6.tgz#5d2d93db419566cb680752ca0792780e71b3273e" + integrity sha512-gHWJF/6Xi5CTG5QCvROr6GcmpIqNYpDJyc8A1h/DyXqH1tD6SnRCM0d3U5msV31D2LB/U+E0M+W4oyvKV44oNw== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +js-sha3@0.5.7, js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= + +js-sha3@0.8.0, js-sha3@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" + integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== + +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" + integrity sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8= + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-buffer@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" + integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + +json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" + integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== + dependencies: + async "^2.0.1" + babel-preset-env "^1.7.0" + babelify "^7.3.0" + json-rpc-error "^2.0.0" + promise-to-callback "^1.0.0" + safe-event-emitter "^1.0.1" + +json-rpc-error@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" + integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= + dependencies: + inherits "^2.0.1" + +json-rpc-random-id@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" + integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keccak@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.1.tgz#ae30a0e94dbe43414f741375cff6d64c8bea0bff" + integrity sha512-epq90L9jlFWCW7+pQa6JOnKn2Xgl2mtI664seYR6MHskvI9agt7AnDqmAlp9TqU4/caMYbA08Hi5DMZAl5zdkA== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +keccak@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b" + integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q== + dependencies: + bindings "^1.5.0" + inherits "^2.0.4" + nan "^2.14.0" + safe-buffer "^5.2.0" + +keccak@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-3.0.2.tgz#4c2c6e8c54e04f2670ee49fa734eb9da152206e0" + integrity sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ== + dependencies: + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + readable-stream "^3.6.0" + +keyv@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" + integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== + dependencies: + json-buffer "3.0.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +klaw-sync@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" + integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== + dependencies: + graceful-fs "^4.1.11" + +klaw@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" + integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= + optionalDependencies: + graceful-fs "^4.1.9" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + +level-codec@^9.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" + integrity sha512-UyIwNb1lJBChJnGfjmO0OR+ezh2iVu1Kas3nvBS/BzGnx79dv6g7unpKIDNPMhfdTEGoc7mC8uAu51XEtX+FHQ== + dependencies: + buffer "^5.6.0" + +level-codec@~7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" + integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== + +level-concat-iterator@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" + integrity sha512-OTKKOqeav2QWcERMJR7IS9CUo1sHnke2C0gkSmcR7QuEtFNLLzHQAvnMw8ykvEcv0Qtkg0p7FOwP1v9e5Smdcw== + +level-errors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" + integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== + dependencies: + errno "~0.1.1" + +level-errors@^2.0.0, level-errors@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== + dependencies: + errno "~0.1.1" + +level-errors@~1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" + integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== + dependencies: + errno "~0.1.1" + +level-iterator-stream@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" + integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.5" + xtend "^4.0.0" + +level-iterator-stream@~1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" + integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= + dependencies: + inherits "^2.0.1" + level-errors "^1.0.3" + readable-stream "^1.0.33" + xtend "^4.0.0" + +level-iterator-stream@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" + integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== + dependencies: + inherits "^2.0.1" + readable-stream "^2.3.6" + xtend "^4.0.0" + +level-iterator-stream@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-4.0.2.tgz#7ceba69b713b0d7e22fcc0d1f128ccdc8a24f79c" + integrity sha512-ZSthfEqzGSOMWoUGhTXdX9jv26d32XJuHz/5YnuHZzH6wldfWMOVwI9TBtKcya4BKTyTt3XVA0A3cF3q5CY30Q== + dependencies: + inherits "^2.0.4" + readable-stream "^3.4.0" + xtend "^4.0.2" + +level-mem@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" + integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== + dependencies: + level-packager "~4.0.0" + memdown "~3.0.0" + +level-mem@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-5.0.1.tgz#c345126b74f5b8aa376dc77d36813a177ef8251d" + integrity sha512-qd+qUJHXsGSFoHTziptAKXoLX87QjR7v2KMbqncDXPxQuCdsQlzmyX+gwrEHhlzn08vkf8TyipYyMmiC6Gobzg== + dependencies: + level-packager "^5.0.3" + memdown "^5.0.0" + +level-packager@^5.0.3: + version "5.1.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" + integrity sha512-HMwMaQPlTC1IlcwT3+swhqf/NUO+ZhXVz6TY1zZIIZlIR0YSn8GtAAWmIvKjNY16ZkEg/JcpAuQskxsXqC0yOQ== + dependencies: + encoding-down "^6.3.0" + levelup "^4.3.2" + +level-packager@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" + integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== + dependencies: + encoding-down "~5.0.0" + levelup "^3.0.0" + +level-post@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" + integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== + dependencies: + ltgt "^2.1.2" + +level-sublevel@6.6.4: + version "6.6.4" + resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" + integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== + dependencies: + bytewise "~1.1.0" + level-codec "^9.0.0" + level-errors "^2.0.0" + level-iterator-stream "^2.0.3" + ltgt "~2.1.1" + pull-defer "^0.2.2" + pull-level "^2.0.3" + pull-stream "^3.6.8" + typewiselite "~1.0.0" + xtend "~4.0.0" + +level-supports@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" + integrity sha512-rXM7GYnW8gsl1vedTJIbzOrRv85c/2uCMpiiCzO2fndd06U/kUXEEU9evYn4zFggBOg36IsBW8LzqIpETwwQzg== + dependencies: + xtend "^4.0.2" + +level-ws@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" + integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= + dependencies: + readable-stream "~1.0.15" + xtend "~2.1.1" + +level-ws@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-1.0.0.tgz#19a22d2d4ac57b18cc7c6ecc4bd23d899d8f603b" + integrity sha512-RXEfCmkd6WWFlArh3X8ONvQPm8jNpfA0s/36M4QzLqrLEIt1iJE9WBHLZ5vZJK6haMjJPJGJCQWfjMNnRcq/9Q== + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.8" + xtend "^4.0.1" + +level-ws@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-2.0.0.tgz#207a07bcd0164a0ec5d62c304b4615c54436d339" + integrity sha512-1iv7VXx0G9ec1isqQZ7y5LmoZo/ewAsyDHNA8EFDW5hqH2Kqovm33nSFkSdnLLAK+I5FlT+lo5Cw9itGe+CpQA== + dependencies: + inherits "^2.0.3" + readable-stream "^3.1.0" + xtend "^4.0.1" + +levelup@3.1.1, levelup@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" + integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== + dependencies: + deferred-leveldown "~4.0.0" + level-errors "~2.0.0" + level-iterator-stream "~3.0.0" + xtend "~4.0.0" + +levelup@^1.2.1: + version "1.3.9" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" + integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== + dependencies: + deferred-leveldown "~1.2.1" + level-codec "~7.0.0" + level-errors "~1.0.3" + level-iterator-stream "~1.3.0" + prr "~1.0.1" + semver "~5.4.1" + xtend "~4.0.0" + +levelup@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" + integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== + dependencies: + deferred-leveldown "~5.3.0" + level-errors "~2.0.0" + level-iterator-stream "~4.0.0" + level-supports "~1.0.0" + xtend "~4.0.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.assign@^4.0.3, lodash.assign@^4.0.6: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= + +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + +lodash@4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +lodash@>=4.17.19, lodash@^4.14.2, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +looper@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" + integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= + +looper@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" + integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== + +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + +lru-cache@5.1.1, lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + dependencies: + pseudomap "^1.0.1" + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +lru_map@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" + integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= + +ltgt@^2.1.2, ltgt@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" + integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= + +ltgt@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" + integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +map-age-cleaner@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-table@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" + integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== + +math-random@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" + integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== + +mcl-wasm@^0.7.1: + version "0.7.9" + resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f" + integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@>=4.0.0: + version "9.0.2" + resolved "https://registry.yarnpkg.com/mem/-/mem-9.0.2.tgz#bbc2d40be045afe30749681e8f5d554cee0c0354" + integrity sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A== + dependencies: + map-age-cleaner "^0.1.3" + mimic-fn "^4.0.0" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + +memdown@^1.0.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" + integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= + dependencies: + abstract-leveldown "~2.7.1" + functional-red-black-tree "^1.0.1" + immediate "^3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memdown@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" + integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== + dependencies: + abstract-leveldown "~6.2.1" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.2.0" + +memdown@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" + integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== + dependencies: + abstract-leveldown "~5.0.0" + functional-red-black-tree "~1.0.1" + immediate "~3.2.3" + inherits "~2.0.1" + ltgt "~2.2.0" + safe-buffer "~5.1.1" + +memorystream@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" + integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= + +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merkle-patricia-tree@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-3.0.0.tgz#448d85415565df72febc33ca362b8b614f5a58f8" + integrity sha512-soRaMuNf/ILmw3KWbybaCjhx86EYeBbD8ph0edQCTed0JN/rxDt1EBN52Ajre3VyGo+91f8+/rfPIRQnnGMqmQ== + dependencies: + async "^2.6.1" + ethereumjs-util "^5.2.0" + level-mem "^3.0.1" + level-ws "^1.0.0" + readable-stream "^3.0.6" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" + integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== + dependencies: + async "^1.4.2" + ethereumjs-util "^5.0.0" + level-ws "0.0.0" + levelup "^1.2.1" + memdown "^1.0.0" + readable-stream "^2.0.0" + rlp "^2.0.0" + semaphore ">=1.0.1" + +merkle-patricia-tree@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-4.2.2.tgz#6dec17855370172458244c2f42c989dd60b773a3" + integrity sha512-eqZYNTshcYx9aESkSPr71EqwsR/QmpnObDEV4iLxkt/x/IoLYZYjJvKY72voP/27Vy61iMOrfOG6jrn7ttXD+Q== + dependencies: + "@types/levelup" "^4.3.0" + ethereumjs-util "^7.1.2" + level-mem "^5.0.1" + level-ws "^2.0.0" + readable-stream "^3.6.0" + rlp "^2.2.4" + semaphore-async-await "^1.5.1" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +micromatch@^2.1.5: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU= + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2, micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" + integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== + +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.34" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" + integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== + dependencies: + mime-db "1.51.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +mimic-response@^1.0.0, mimic-response@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@>=1.2.3, minimist@^1.2.0, minimist@^1.2.5, minimist@~1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mkdirp@0.5.5, mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mnemonist@^0.38.0: + version "0.38.5" + resolved "https://registry.yarnpkg.com/mnemonist/-/mnemonist-0.38.5.tgz#4adc7f4200491237fe0fa689ac0b86539685cade" + integrity sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg== + dependencies: + obliterator "^2.0.0" + +mocha-chai-jest-snapshot@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/mocha-chai-jest-snapshot/-/mocha-chai-jest-snapshot-1.1.3.tgz#ac7b280961a9da08b529d0f8488e90a4cbe9ece8" + integrity sha512-i2Vb+6mXKBMapNAbVUiM11CPJgkJ1BKwouH98Bcx0trgAcVZxdRt4pNlbLZogjQEj/gCmjrW5Y8hmYWWDoXwGg== + dependencies: + "@jest/test-result" "^27.0.6" + chalk "^4.1.2" + find-package-json "^1.2.0" + jest-snapshot "^27.0.6" + jest-util "^27.0.6" + slash "^3.0.0" + yargs "^17.1.1" + +mocha@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +mocha@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" + integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== + dependencies: + browser-stdout "1.3.0" + commander "2.11.0" + debug "3.1.0" + diff "3.3.1" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.3" + he "1.1.1" + mkdirp "0.5.1" + supports-color "4.4.0" + +mocha@^7.1.1, mocha@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + chokidar "3.3.0" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "3.0.0" + minimatch "3.0.4" + mkdirp "0.5.5" + ms "2.1.1" + node-environment-flags "1.0.6" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "1.6.0" + +mocha@^9.1.4: + version "9.1.4" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.1.4.tgz#5a332d6ade6345b975fd97b5b39139854c8e1b32" + integrity sha512-+q2aV5VlJZuLgCWoBvGI5zEwPF9eEI0kr/sAA9Jm4xMND7RfIEyF8JE7C0JIg8WXRG+P1sdIAb5ccoHPlXLzcw== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.2" + debug "4.3.2" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.7" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.1.25" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.1.5" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +mock-fs@^4.1.0: + version "4.14.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" + integrity sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3, ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +multibase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" + integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multibase@~0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" + integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== + dependencies: + base-x "^3.0.8" + buffer "^5.5.0" + +multicodec@^0.5.5: + version "0.5.7" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" + integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== + dependencies: + varint "^5.0.0" + +multicodec@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" + integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== + dependencies: + buffer "^5.6.0" + varint "^5.0.0" + +multihashes@^0.4.15, multihashes@~0.4.15: + version "0.4.21" + resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" + integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== + dependencies: + buffer "^5.5.0" + multibase "^0.7.0" + varint "^5.0.0" + +nan@^2.12.1, nan@^2.14.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= + +nanoid@3.1.25: + version "3.1.25" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.25.tgz#09ca32747c0e543f0e1814b7d3793477f9c8e152" + integrity sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-addon-api@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== + +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +node-fetch@2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-fetch@^1.0.1, node-fetch@~1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +node-fetch@^2.6.0, node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" + integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q== + +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-releases@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" + integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== + +nofilter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-1.0.4.tgz#78d6f4b6a613e7ced8b015cec534625f7667006e" + integrity sha512-N8lidFp+fCz+TD51+haYdbDGrcBWwuHX40F5+z0qkUjMJ5Tp+rdSuAkMJ9N9eoolDlEVTf6u5icM+cNKkKW2mA== + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.0, normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-url@^4.1.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + +nunjucks@^3.2.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.3.tgz#1b33615247290e94e28263b5d855ece765648a31" + integrity sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ== + dependencies: + a-sync-waterfall "^1.0.0" + asap "^2.0.3" + commander "^5.1.0" + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4, object-assign@^4.0.0, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.11.0, object-inspect@^1.9.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" + integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== + +object-inspect@~1.11.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.1.tgz#d4bd7d7de54b9a75599f59a00bd698c1f1c6549b" + integrity sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA== + +object-is@^1.0.1: + version "1.1.5" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" + integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-keys@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" + integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" + integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo= + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +obliterator@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/obliterator/-/obliterator-2.0.1.tgz#fbdd873bf39fc4f365a53b1fc86617a22526987c" + integrity sha512-XnkiCrrBcIZQitJPAI36mrrpEUvatbte8hLcTcQwKA1v9NkCKasSi+UAguLsLDs/out7MoRzAlmz7VXvY6ph6w== + +oboe@2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" + integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= + dependencies: + http-https "^1.0.0" + +oboe@2.1.5: + version "2.1.5" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.5.tgz#5554284c543a2266d7a38f17e073821fbde393cd" + integrity sha1-VVQoTFQ6ImbXo48X4HOCH73jk80= + dependencies: + http-https "^1.0.0" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +open@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + +openzeppelin-solidity@v3.0.0-rc.0: + version "3.0.0-rc.0" + resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-3.0.0-rc.0.tgz#8e8328749ad5f4e8e65a8364e5e12b956e0a22f1" + integrity sha512-cftpu1YvJgYbYcUVlTAOi+JvMF+hkvwdjLtA3ZLiBjVfEsf5HQGKL293dr/F31PRZSGurH+31Y0RxOPUvExGQQ== + +original-require@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" + integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= + dependencies: + lcid "^1.0.0" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-cancelable@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" + integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== + +p-cancelable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" + integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-timeout@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" + integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= + dependencies: + p-finally "^1.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-cache-control@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" + integrity sha1-juqz5U+laSD+Fro493+iGqzC104= + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw= + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-headers@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.4.tgz#9eaf2d02bed2d1eff494331ce3df36d7924760bf" + integrity sha512-psZ9iZoCNFLrgRjZ1d8mn0h9WRqJwFxM9q3x7iUjN/YT2OksthDJ5TiPCu2F38kS4zutqfW+YdVVkBZZx3/1aw== + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +patch-package@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" + integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^1.2.1" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +patch-package@^6.2.2: + version "6.4.7" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.4.7.tgz#2282d53c397909a0d9ef92dae3fdeb558382b148" + integrity sha512-S0vh/ZEafZ17hbhgqdnpunKDfzHQibQizx9g8yEf5dcVk3KOflOfdufRXQX8CSEkyOQwuM/bNz1GwKvFj54kaQ== + dependencies: + "@yarnpkg/lockfile" "^1.1.0" + chalk "^2.4.2" + cross-spawn "^6.0.5" + find-yarn-workspace-root "^2.0.0" + fs-extra "^7.0.1" + is-ci "^2.0.0" + klaw-sync "^6.0.0" + minimist "^1.2.0" + open "^7.4.2" + rimraf "^2.6.3" + semver "^5.6.0" + slash "^2.0.0" + tmp "^0.0.33" + +path-browserify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6, path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9: + version "3.1.2" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" + integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +pegjs@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" + integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pirates@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" + integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postinstall-postinstall@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postinstall-postinstall/-/postinstall-postinstall-2.1.0.tgz#4f7f77441ef539d1512c40bd04c71b06a4704ca3" + integrity sha512-7hQX6ZlZXIoRiWNrbMQaLzUUfH+sSx39u8EJ9HYuDc1kLo9IXKWjM5RSquZN1ad5GnH8CGFM78fsAAQi3OKEEQ== + +precond@0.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" + integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= + +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= + +prettier@^2.1.2, prettier@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + +pretty-format@^27.4.6: + version "27.4.6" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.4.6.tgz#1b784d2f53c68db31797b2348fa39b49e31846b7" + integrity sha512-NblstegA1y/RJW2VyML+3LlpFjzx62cUrtBIKIWDXEDkjNeleA7Od7nrzcs/VLQvAeV4CgSYhrN39DRN88Qi/g== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + +printj@~1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" + integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +promise-to-callback@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" + integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= + dependencies: + is-fn "^1.0.0" + set-immediate-shim "^1.0.1" + +promise@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" + integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== + dependencies: + asap "~2.0.6" + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +pseudomap@^1.0.1, pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pull-cat@^1.1.9: + version "1.1.11" + resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" + integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= + +pull-defer@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" + integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== + +pull-level@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" + integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== + dependencies: + level-post "^1.0.7" + pull-cat "^1.1.9" + pull-live "^1.0.1" + pull-pushable "^2.0.0" + pull-stream "^3.4.0" + pull-window "^2.1.4" + stream-to-pull-stream "^1.7.1" + +pull-live@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" + integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= + dependencies: + pull-cat "^1.1.9" + pull-stream "^3.4.0" + +pull-pushable@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" + integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= + +pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: + version "3.6.14" + resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" + integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== + +pull-window@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" + integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= + dependencies: + looper "^2.0.0" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +qs@6.9.6: + version "6.9.6" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" + integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== + +qs@^6.4.0, qs@^6.7.0: + version "6.10.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" + integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +query-string@^5.0.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== + dependencies: + decode-uri-component "^0.2.0" + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= + +randomatic@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" + integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== + dependencies: + is-number "^4.0.0" + kind-of "^6.0.0" + math-random "^1.0.1" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.2, raw-body@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" + integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== + dependencies: + bytes "3.1.1" + http-errors "1.8.1" + iconv-lite "0.4.24" + unpipe "1.0.0" + +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +readable-stream@^1.0.33: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.2.2, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.0, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readable-stream@~1.0.15: + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readdirp@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + +reduce-flatten@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" + integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== + +regenerate@^1.2.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" + integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== + dependencies: + is-equal-shallow "^0.1.3" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307" + integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.5.2, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +req-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" + integrity sha1-1AgrTURZgDZkD7c93qAe1T20nrw= + dependencies: + req-from "^2.0.0" + +req-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" + integrity sha1-10GI5H+TeW9Kpx327jWuaJ8+DnA= + dependencies: + resolve-from "^3.0.0" + +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.5: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.67.0, request@^2.79.0, request@^2.85.0, request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= + +require-from-string@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + +resolve@^1.10.0, resolve@^1.8.1: + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + dependencies: + is-core-module "^2.8.1" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@~1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +responselike@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" + integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= + dependencies: + lowercase-keys "^1.0.0" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= + dependencies: + through "~2.3.4" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +rimraf@^2.2.8, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4, rlp@^2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" + integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== + dependencies: + bn.js "^5.2.0" + +rustbn.js@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" + integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== + +safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-event-emitter@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" + integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== + dependencies: + events "^3.0.0" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scrypt-js@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" + integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== + +scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" + integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + integrity sha1-oyJfpLJST4AnAHYeKFW987LZIWM= + dependencies: + pbkdf2 "^3.0.3" + +secp256k1@^3.0.1: + version "3.8.0" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" + integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== + dependencies: + 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.5.2" + nan "^2.14.0" + safe-buffer "^5.1.2" + +secp256k1@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== + dependencies: + elliptic "^6.5.4" + node-addon-api "^2.0.0" + node-gyp-build "^4.2.0" + +seedrandom@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" + integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== + +semaphore-async-await@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" + integrity sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo= + +semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" + integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.3.2: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + +semver@~5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== + +send@0.17.2: + version "0.17.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" + integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "1.8.1" + mime "1.6.0" + ms "2.1.3" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +serve-static@1.14.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" + integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.2" + +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha1@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848" + integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg= + dependencies: + charenc ">= 0.0.1" + crypt ">= 0.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.6" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" + integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sol-digger@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/sol-digger/-/sol-digger-0.0.2.tgz#406c4a9d31e269e7f88eb1c2ea101318e5e09025" + integrity sha1-QGxKnTHiaef4jrHC6hATGOXgkCU= + +sol-explore@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.1.tgz#b59f073c69fe332560d5a10c32ba8ca7f2986cfb" + integrity sha1-tZ8HPGn+MyVg1aEMMrqMp/KYbPs= + +solc@0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a" + integrity sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + follow-redirects "^1.12.1" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solc@^0.4.2, solc@^0.4.20: + version "0.4.26" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" + integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== + dependencies: + fs-extra "^0.30.0" + memorystream "^0.3.1" + require-from-string "^1.1.0" + semver "^5.3.0" + yargs "^4.7.1" + +solc@^0.6.3: + version "0.6.12" + resolved "https://registry.yarnpkg.com/solc/-/solc-0.6.12.tgz#48ac854e0c729361b22a7483645077f58cba080e" + integrity sha512-Lm0Ql2G9Qc7yPP2Ba+WNmzw2jwsrd3u4PobHYlSOxaut3TtUbj9+5ZrT6f4DUpNPEoBaFUOEg9Op9C0mk7ge9g== + dependencies: + command-exists "^1.2.8" + commander "3.0.2" + fs-extra "^0.30.0" + js-sha3 "0.8.0" + memorystream "^0.3.1" + require-from-string "^2.0.0" + semver "^5.5.0" + tmp "0.0.33" + +solidity-bytes-utils@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/solidity-bytes-utils/-/solidity-bytes-utils-0.0.8.tgz#245f21a004610023a9241f8c09b3ca408373f4b8" + integrity sha512-TQi6HFM2PDLLckVXQCzcQGZN8VrQsLA2aRIHNqZkbN/K7pmOSgit/7CnuatiLpM7i8Yy7Vibt5oFBA+sMWEZBA== + dependencies: + truffle-hdwallet-provider "0.0.3" + +solium-plugin-security@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/solium-plugin-security/-/solium-plugin-security-0.1.1.tgz#2a87bcf8f8c3abf7d198e292e4ac080284e3f3f6" + integrity sha512-kpLirBwIq4mhxk0Y/nn5cQ6qdJTI+U1LO3gpoNIcqNaW+sI058moXBe2UiHs+9wvF9IzYD49jcKhFTxcR9u9SQ== + +solium@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/solium/-/solium-1.2.5.tgz#d036c30e2901e22137bbf342f106b17529ff22a8" + integrity sha512-NuNrm7fp8JcDN/P+SAdM5TVa4wYDtwVtLY/rG4eBOZrC5qItsUhmQKR/YhjszaEW4c8tNUYhkhQcwOsS25znpw== + dependencies: + ajv "^5.2.2" + chokidar "^1.6.0" + colors "^1.1.2" + commander "^2.9.0" + diff "^3.5.0" + eol "^0.9.1" + js-string-escape "^1.0.1" + lodash "^4.14.2" + sol-digger "0.0.2" + sol-explore "1.6.1" + solium-plugin-security "0.1.1" + solparse "2.2.8" + text-table "^0.2.0" + +solparse@2.2.8: + version "2.2.8" + resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" + integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== + dependencies: + mocha "^4.0.1" + pegjs "^0.10.0" + yargs "^10.0.3" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@0.5.12: + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== + dependencies: + source-map "^0.5.6" + +source-map-support@^0.5.13: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + +source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" + integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" + integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + dependencies: + escape-string-regexp "^2.0.0" + +stacktrace-parser@^0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +stream-to-pull-stream@^1.7.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" + integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== + dependencies: + looper "^3.0.0" + pull-stream "^3.2.3" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-format@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" + integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@~1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.5.tgz#a587bcc8bfad8cb9829a577f5de30dd170c1682c" + integrity sha512-Lnh17webJVsD6ECeovpVN17RlAKjmz4rF9S+8Y45CkMc/ufVpTkU3vZIyIC7sllQ1FCvObZnnCdNs/HXTUOTlg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.1" + +string.prototype.trimend@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" + integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" + integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-hex-prefix@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" + integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= + dependencies: + is-hex-prefixed "1.0.0" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" + integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== + dependencies: + has-flag "^2.0.0" + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== + dependencies: + has-flag "^3.0.0" + +supports-color@8.1.1, supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +swarm-js@^0.1.40: + version "0.1.40" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" + integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + eth-lib "^0.1.26" + fs-extra "^4.0.2" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar "^4.0.2" + xhr-request "^1.0.1" + +sync-request@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.1.0.tgz#e96217565b5e50bbffe179868ba75532fb597e68" + integrity sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw== + dependencies: + http-response-object "^3.0.1" + sync-rpc "^1.2.1" + then-request "^6.0.0" + +sync-rpc@^1.2.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7" + integrity sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw== + dependencies: + get-port "^3.1.0" + +table-layout@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/table-layout/-/table-layout-1.0.2.tgz#c4038a1853b0136d63365a734b6931cf4fad4a04" + integrity sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A== + dependencies: + array-back "^4.0.1" + deep-extend "~0.6.0" + typical "^5.2.0" + wordwrapjs "^4.0.0" + +tape@^4.4.0, tape@^4.6.3: + version "4.14.0" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.14.0.tgz#e4d46097e129817175b90925f2385f6b1bcfa826" + integrity sha512-z0+WrUUJuG6wIdWrl4W3rTte2CR26G6qcPOj3w1hfRdcmhF3kHBhOBW9VHsPVAkz08ZmGzp7phVpDupbLzrYKQ== + dependencies: + call-bind "~1.0.2" + deep-equal "~1.1.1" + defined "~1.0.0" + dotignore "~0.1.2" + for-each "~0.3.3" + glob "~7.1.7" + has "~1.0.3" + inherits "~2.0.4" + is-regex "~1.1.3" + minimist "~1.2.5" + object-inspect "~1.11.0" + resolve "~1.20.0" + resumer "~0.0.0" + string.prototype.trim "~1.2.4" + through "~2.3.8" + +tar@^4.0.2: + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + +testrpc@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/testrpc/-/testrpc-0.0.1.tgz#83e2195b1f5873aec7be1af8cbe6dcf39edb7aed" + integrity sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +then-request@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.2.tgz#ec18dd8b5ca43aaee5cb92f7e4c1630e950d4f0c" + integrity sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA== + dependencies: + "@types/concat-stream" "^1.6.0" + "@types/form-data" "0.0.33" + "@types/node" "^8.0.0" + "@types/qs" "^6.2.31" + caseless "~0.12.0" + concat-stream "^1.6.0" + form-data "^2.2.0" + http-basic "^8.1.1" + http-response-object "^3.0.1" + promise "^8.0.0" + qs "^6.4.0" + +through2@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +timed-out@^4.0.0, timed-out@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= + +tmp@0.0.33, tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +tmp@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" + integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== + dependencies: + rimraf "^2.6.3" + +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-readable-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" + integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= + +"true-case-path@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-2.2.1.tgz#c5bf04a5bbec3fd118be4084461b3a27c4d796bf" + integrity sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q== + +truffle-assertions@0.9.2: + version "0.9.2" + resolved "https://registry.yarnpkg.com/truffle-assertions/-/truffle-assertions-0.9.2.tgz#0f8360f53ad92b6d8fdb8ceb5dce54c1fc392e23" + integrity sha512-9g2RhaxU2F8DeWhqoGQvL/bV8QVoSnQ6PY+ZPvYRP5eF7+/8LExb4mjLx/FeliLTjc3Tv1SABG05Gu5qQ/ErmA== + dependencies: + assertion-error "^1.1.0" + lodash.isequal "^4.5.0" + +truffle-flattener@1.4.4: + version "1.4.4" + resolved "https://registry.yarnpkg.com/truffle-flattener/-/truffle-flattener-1.4.4.tgz#747a99204001f7d6dce43ea92771e1ff6ac3eafb" + integrity sha512-S/WmvubzlUj1mn56wEI6yo1bmPpKDNdEe5rtyVC1C5iNfZWobD/V69pAYI15IBDJrDqUyh+iXgpTkzov50zpQw== + dependencies: + "@resolver-engine/imports-fs" "^0.2.2" + "@solidity-parser/parser" "^0.6.0" + find-up "^2.1.0" + mkdirp "^1.0.4" + tsort "0.0.1" + +truffle-hdwallet-provider@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.3.tgz#0e1de02104b73d3875e1cf7093305b4ea8a2d843" + integrity sha1-Dh3gIQS3PTh14c9wkzBbTqii2EM= + dependencies: + bip39 "^2.2.0" + ethereumjs-wallet "^0.6.0" + web3 "^0.18.2" + web3-provider-engine "^8.4.0" + +truffle@5.1.14: + version "5.1.14" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.14.tgz#18dde420cd88d8214451d59d1cf554c83f54dcd4" + integrity sha512-6rIy335igwHOR0a8xEtPZdlCPBAvDcMIuVQVWAVtPqDy7xMTxGm4A0C4YRsEvZUc5V8GfCBfQb/GQ5AXlXI+6w== + dependencies: + app-module-path "^2.2.0" + mocha "5.2.0" + original-require "1.0.1" + +ts-command-line-args@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.2.0.tgz#655e10451b06c86d318e9467546da4d19b773a55" + integrity sha512-RedEejZyhiEAOgBkIVxB4QC/SRYtl98D7b7epWB9e6E+TmK8KstXBu3WdnhGbMHicLkHoG7sCAmu+F+ASzLFHA== + dependencies: + chalk "^4.1.0" + command-line-args "^5.1.1" + command-line-usage "^6.1.0" + string-format "^2.0.0" + +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-essentials@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-7.0.3.tgz#686fd155a02133eedcc5362dc8b5056cde3e5a38" + integrity sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ== + +ts-generator@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.1.1.tgz#af46f2fb88a6db1f9785977e9590e7bcd79220ab" + integrity sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^2.1.1" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^2.1.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + +ts-node@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" + integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + yn "3.1.1" + +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsort@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" + integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl-util@^0.15.0: + version "0.15.1" + resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" + integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +tweetnacl@^1.0.0, tweetnacl@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" + integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== + +type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.5.0.tgz#0a2e78c2e77907b252abe5f298c1b01c63f0db3d" + integrity sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw== + +typechain@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-3.0.0.tgz#d5a47700831f238e43f7429b987b4bb54849b92e" + integrity sha512-ft4KVmiN3zH4JUFu2WJBrwfHeDf772Tt2d8bssDTo/YcckKW2D+OwFrHXRC6hJvO3mHjFQTihoMV6fJOi0Hngg== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.1.1" + +typechain@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-7.0.0.tgz#258ca136de1d451368bde01c318976a83062f110" + integrity sha512-ILfvBBFJ7j9aIk0crX03+N2GmzoDN1gtk32G1+XrasjuvXS0XAw2XxwQeQMMgKwlnxViJjIkG87sTMYXPkXA9g== + dependencies: + "@types/prettier" "^2.1.1" + debug "^4.1.1" + fs-extra "^7.0.0" + glob "^7.1.6" + js-sha3 "^0.8.0" + lodash "^4.17.15" + mkdirp "^1.0.4" + prettier "^2.1.2" + ts-command-line-args "^2.2.0" + ts-essentials "^7.0.1" + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^4.5.5: + version "4.5.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" + integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== + +typewise-core@^1.2, typewise-core@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" + integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= + +typewise@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" + integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= + dependencies: + typewise-core "^1.2.0" + +typewiselite@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" + integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= + +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + +typical@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" + integrity sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw== + +typical@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/typical/-/typical-5.2.0.tgz#4daaac4f2b5315460804f0acf6cb69c52bb93066" + integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== + +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== + +unbox-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" + integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== + dependencies: + function-bind "^1.1.1" + has-bigints "^1.0.1" + has-symbols "^1.0.2" + which-boxed-primitive "^1.0.2" + +underscore@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unorm@^1.3.3: + version "1.6.0" + resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" + integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= + dependencies: + prepend-http "^1.0.1" + +url-parse-lax@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" + integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + dependencies: + prepend-http "^2.0.0" + +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= + +url-to-options@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" + integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +utf-8-validate@^5.0.2: + version "5.0.8" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58" + integrity sha512-k4dW/Qja1BYDl2qD4tOMB9PFVha/UJtxTc1cXYOe3WwA/2m0Yn4qB7wLMpJyLJ/7DR0XnTut3HsCSzDT4ZvKgA== + dependencies: + node-gyp-build "^4.3.0" + +utf8@3.0.0, utf8@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" + integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== + +utf8@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" + integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.1.1.tgz#77832f57ced2c9478174149cae9b96e9918cd54b" + integrity sha512-/s3UsZUrIfa6xDhr7zZhnE9SLQ5RIXyYfiVnMMyMDzOc8WhWN4Nbh36H842OyurKbCDAesZOJaVyvmSl6fhGQw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + for-each "^0.3.3" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.1" + +util@^0.12.0: + version "0.12.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" + integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + safe-buffer "^5.1.2" + which-typed-array "^1.1.2" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= + +uuid@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +varint@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" + integrity sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +walker@^1.0.7: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + +web3-bzz@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" + integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + underscore "1.9.1" + +web3-bzz@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.7.0.tgz#0b754d787a1700f0580fa741fc707d19d1447ff4" + integrity sha512-XPhTWUnZa8gnARfiqaag3jJ9+6+a66Li8OikgBUJoMUqPuQTCJPncTbGYqOJIfRFGavEAdlMnfYXx9lvgv2ZPw== + dependencies: + "@types/node" "^12.12.6" + got "9.6.0" + swarm-js "^0.1.40" + +web3-core-helpers@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" + integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.11" + web3-utils "1.2.11" + +web3-core-helpers@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.7.0.tgz#0eaef7bc55ff7ec5ba726181d0e8529be5d60903" + integrity sha512-kFiqsZFHJliKF8VKZNjt2JvKu3gu7h3N1/ke3EPhdp9Li/rLmiyzFVr6ApryZ1FSjbSx6vyOkibG3m6xQ5EHJA== + dependencies: + web3-eth-iban "1.7.0" + web3-utils "1.7.0" + +web3-core-method@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" + integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-utils "1.2.11" + +web3-core-method@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.7.0.tgz#5e98030ac9e0d96c6ff1ba93fde1292a332b1b81" + integrity sha512-43Om+kZX8wU5u1pJ28TltF9e9pSTRph6b8wrOb6wgXAfPHqMulq6UTBJWjXXIRVN46Eiqv0nflw35hp9bbgnbA== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + web3-core-helpers "1.7.0" + web3-core-promievent "1.7.0" + web3-core-subscriptions "1.7.0" + web3-utils "1.7.0" + +web3-core-promievent@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" + integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== + dependencies: + eventemitter3 "4.0.4" + +web3-core-promievent@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.7.0.tgz#e2c6c38f29b912cc549a2a3f806636a3393983eb" + integrity sha512-xPH66XeC0K0k29GoRd0vyPQ07yxERPRd4yVPrbMzGAz/e9E4M3XN//XK6+PdfGvGw3fx8VojS+tNIMiw+PujbQ== + dependencies: + eventemitter3 "4.0.4" + +web3-core-requestmanager@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" + integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.11" + web3-providers-http "1.2.11" + web3-providers-ipc "1.2.11" + web3-providers-ws "1.2.11" + +web3-core-requestmanager@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.7.0.tgz#5b62b413471d6d2a789ee33d587d280178979c7e" + integrity sha512-rA3dBTBPrt+eIfTAQ2/oYNTN/2wbZaYNR3pFZGqG8+2oCK03+7oQyz4sWISKy/nYQhURh4GK01rs9sN4o/Tq9w== + dependencies: + util "^0.12.0" + web3-core-helpers "1.7.0" + web3-providers-http "1.7.0" + web3-providers-ipc "1.7.0" + web3-providers-ws "1.7.0" + +web3-core-subscriptions@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" + integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-core-subscriptions@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.7.0.tgz#30475d8ed5f51a170e5df02085f721925622a795" + integrity sha512-6giF8pyJrPmWrRpc2WLoVCvQdMMADp20ZpAusEW72axauZCNlW1XfTjs0i4QHQBfdd2lFp65qad9IuATPhuzrQ== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.7.0" + +web3-core@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" + integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-requestmanager "1.2.11" + web3-utils "1.2.11" + +web3-core@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.7.0.tgz#67b7839130abd19476e7f614ea6ec4c64d08eb00" + integrity sha512-U/CRL53h3T5KHl8L3njzCBT7fCaHkbE6BGJe3McazvFldRbfTDEHXkUJCyM30ZD0RoLi3aDfTVeFIusmEyCctA== + dependencies: + "@types/bn.js" "^4.11.5" + "@types/node" "^12.12.6" + bignumber.js "^9.0.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-requestmanager "1.7.0" + web3-utils "1.7.0" + +web3-eth-abi@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" + integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.11" + +web3-eth-abi@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.7.0.tgz#4fac9c7d9e5a62b57f8884b37371f515c766f3f4" + integrity sha512-heqR0bWxgCJwjWIhq2sGyNj9bwun5+Xox/LdZKe+WMyTSy0cXDXEAgv3XKNkXC4JqdDt/ZlbTEx4TWak4TRMSg== + dependencies: + "@ethersproject/abi" "5.0.7" + web3-utils "1.7.0" + +web3-eth-accounts@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" + integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== + dependencies: + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-common "^1.3.2" + ethereumjs-tx "^2.1.1" + scrypt-js "^3.0.1" + underscore "1.9.1" + uuid "3.3.2" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-eth-accounts@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.7.0.tgz#d0a6f2cfbd61dd6014224056070b7f8d1d63c0ab" + integrity sha512-Zwm7TlQXdXGRuS6+ib1YsR5fQwpfnFyL6UAZg1zERdrUrs3IkCZSL3yCP/8ZYbAjdTEwWljoott2iSqXNH09ug== + dependencies: + "@ethereumjs/common" "^2.5.0" + "@ethereumjs/tx" "^3.3.2" + crypto-browserify "3.12.0" + eth-lib "0.2.8" + ethereumjs-util "^7.0.10" + scrypt-js "^3.0.1" + uuid "3.3.2" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-utils "1.7.0" + +web3-eth-contract@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" + integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== + dependencies: + "@types/bn.js" "^4.11.5" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-promievent "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-utils "1.2.11" + +web3-eth-contract@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.7.0.tgz#3795767a65d7b87bd22baea3e18aafdd928d5313" + integrity sha512-2LY1Xwxu5rx468nqHuhvupQAIpytxIUj3mGL9uexszkhrQf05THVe3i4OnUCzkeN6B2cDztNOqLT3j9SSnVQDg== + dependencies: + "@types/bn.js" "^4.11.5" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-promievent "1.7.0" + web3-core-subscriptions "1.7.0" + web3-eth-abi "1.7.0" + web3-utils "1.7.0" + +web3-eth-ens@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" + integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-promievent "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-contract "1.2.11" + web3-utils "1.2.11" + +web3-eth-ens@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.7.0.tgz#49c5300935b026578aaaf9664e5e5529d4c76a68" + integrity sha512-I1bikYJJWQ/FJZIAvwsGOvzAgcRIkosWG4s1L6veRoXaU8OEJFeh4s00KcfHDxg7GWZZGbUSbdbzKpwRbWnvkg== + dependencies: + content-hash "^2.5.2" + eth-ens-namehash "2.0.8" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-promievent "1.7.0" + web3-eth-abi "1.7.0" + web3-eth-contract "1.7.0" + web3-utils "1.7.0" + +web3-eth-iban@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" + integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== + dependencies: + bn.js "^4.11.9" + web3-utils "1.2.11" + +web3-eth-iban@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.7.0.tgz#b56cd58587457d3339730e0cb42772a37141b434" + integrity sha512-1PFE/Og+sPZaug+M9TqVUtjOtq0HecE+SjDcsOOysXSzslNC2CItBGkcRwbvUcS+LbIkA7MFsuqYxOL0IV/gyA== + dependencies: + bn.js "^4.11.9" + web3-utils "1.7.0" + +web3-eth-personal@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" + integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth-personal@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.7.0.tgz#260c9b6af6e0bea772c6a9a5d58c8d62c035ed99" + integrity sha512-Dr9RZTNOR80PhrPKGdktDUXpOgExEcCcosBj080lKCJFU1paSPj9Zfnth3u6BtIOXyKsVFTrpqekqUDyAwXnNw== + dependencies: + "@types/node" "^12.12.6" + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-net "1.7.0" + web3-utils "1.7.0" + +web3-eth@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" + integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== + dependencies: + underscore "1.9.1" + web3-core "1.2.11" + web3-core-helpers "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-eth-abi "1.2.11" + web3-eth-accounts "1.2.11" + web3-eth-contract "1.2.11" + web3-eth-ens "1.2.11" + web3-eth-iban "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-utils "1.2.11" + +web3-eth@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.7.0.tgz#4adbed9b28ab7f81cb11e3586a12d01ab6e812aa" + integrity sha512-3uYwjMjn/MZjKIzXCt4YL9ja/k9X5shfa4lKparZhZE6uesmu+xmSmrEFXA/e9qcveF50jkV7frjkT8H+cLYtw== + dependencies: + web3-core "1.7.0" + web3-core-helpers "1.7.0" + web3-core-method "1.7.0" + web3-core-subscriptions "1.7.0" + web3-eth-abi "1.7.0" + web3-eth-accounts "1.7.0" + web3-eth-contract "1.7.0" + web3-eth-ens "1.7.0" + web3-eth-iban "1.7.0" + web3-eth-personal "1.7.0" + web3-net "1.7.0" + web3-utils "1.7.0" + +web3-net@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" + integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-utils "1.2.11" + +web3-net@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.7.0.tgz#694a0c7988f7efc336bab0ee413eb4522efee3b2" + integrity sha512-8pmfU1Se7DmG40Pu8nOCKlhuI12VsVzCtdFDnLAai0zGVAOUuuOCK71B2aKm6u9amWBJjtOlyrCwvsG+QEd6dw== + dependencies: + web3-core "1.7.0" + web3-core-method "1.7.0" + web3-utils "1.7.0" + +web3-provider-engine@14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" + integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== + dependencies: + async "^2.5.0" + backoff "^2.5.0" + clone "^2.0.0" + cross-fetch "^2.1.0" + eth-block-tracker "^3.0.0" + eth-json-rpc-infura "^3.1.0" + eth-sig-util "^1.4.2" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.1.5" + ethereumjs-vm "^2.3.4" + json-rpc-error "^2.0.0" + json-stable-stringify "^1.0.1" + promise-to-callback "^1.0.0" + readable-stream "^2.2.9" + request "^2.85.0" + semaphore "^1.0.3" + ws "^5.1.1" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-provider-engine@^8.4.0: + version "8.6.1" + resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-8.6.1.tgz#4d86e19e30caaf97df351511ec0f60136e5b30eb" + integrity sha1-TYbhnjDKr5ffNRUR7A9gE25bMOs= + dependencies: + async "^2.1.2" + clone "^2.0.0" + ethereumjs-block "^1.2.2" + ethereumjs-tx "^1.2.0" + ethereumjs-util "^5.0.1" + ethereumjs-vm "^2.0.2" + isomorphic-fetch "^2.2.0" + request "^2.67.0" + semaphore "^1.0.3" + solc "^0.4.2" + tape "^4.4.0" + web3 "^0.16.0" + xhr "^2.2.0" + xtend "^4.0.1" + +web3-providers-http@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" + integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== + dependencies: + web3-core-helpers "1.2.11" + xhr2-cookies "1.1.0" + +web3-providers-http@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.7.0.tgz#0661261eace122a0ed5853f8be5379d575a9130c" + integrity sha512-Y9reeEiApfvQKLUUtrU4Z0c+H6b7BMWcsxjgoXndI1C5NB297mIUfltXxfXsh5C/jk5qn4Q3sJp3SwQTyVjH7Q== + dependencies: + web3-core-helpers "1.7.0" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" + integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + +web3-providers-ipc@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.7.0.tgz#152dc1231eb4f17426498d4d5d973c865eab03d9" + integrity sha512-U5YLXgu6fvAK4nnMYqo9eoml3WywgTym0dgCdVX/n1UegLIQ4nctTubBAuWQEJzmAzwh+a6ValGcE7ZApTRI7Q== + dependencies: + oboe "2.1.5" + web3-core-helpers "1.7.0" + +web3-providers-ws@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" + integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== + dependencies: + eventemitter3 "4.0.4" + underscore "1.9.1" + web3-core-helpers "1.2.11" + websocket "^1.0.31" + +web3-providers-ws@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.7.0.tgz#99c2de9f6b5ac56e926794ef9074c7442d937372" + integrity sha512-0a8+lVV3JBf+eYnGOsdzOpftK1kis5X7s35QAdoaG5SDapnEylXFlR4xDSSSU88ZwMwvse8hvng2xW6A7oeWxw== + dependencies: + eventemitter3 "4.0.4" + web3-core-helpers "1.7.0" + websocket "^1.0.32" + +web3-shh@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" + integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== + dependencies: + web3-core "1.2.11" + web3-core-method "1.2.11" + web3-core-subscriptions "1.2.11" + web3-net "1.2.11" + +web3-shh@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.7.0.tgz#ed9d085b670bb5a938f2847393478e33df3ec95c" + integrity sha512-RZhxcevALIPK178VZCpwMBvQeW+IoWtRJ4EMdegpbnETeZaC3aRUcs6vKnrf0jXJjm4J/E2Dt438Y1Ord/1IMw== + dependencies: + web3-core "1.7.0" + web3-core-method "1.7.0" + web3-core-subscriptions "1.7.0" + web3-net "1.7.0" + +web3-utils@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" + integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== + dependencies: + bn.js "^4.11.9" + eth-lib "0.2.8" + 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" + +web3-utils@1.7.0, web3-utils@^1.0.0-beta.31: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.7.0.tgz#c59f0fd43b2449357296eb54541810b99b1c771c" + integrity sha512-O8Tl4Ky40Sp6pe89Olk2FsaUkgHyb5QAXuaKo38ms3CxZZ4d3rPGfjP9DNKGm5+IUgAZBNpF1VmlSmNCqfDI1w== + dependencies: + bn.js "^4.11.9" + ethereum-bloom-filters "^1.0.6" + ethereumjs-util "^7.1.0" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + utf8 "3.0.0" + +web3@1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" + integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== + dependencies: + web3-bzz "1.2.11" + web3-core "1.2.11" + web3-eth "1.2.11" + web3-eth-personal "1.2.11" + web3-net "1.2.11" + web3-shh "1.2.11" + web3-utils "1.2.11" + +web3@^0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-0.16.0.tgz#a4554175cd462943035b1f1d39432f741c6b6019" + integrity sha1-pFVBdc1GKUMDWx8dOUMvdBxrYBk= + dependencies: + bignumber.js "git+https://github.com/debris/bignumber.js#master" + crypto-js "^3.1.4" + utf8 "^2.1.1" + xmlhttprequest "*" + +web3@^0.18.2: + version "0.18.4" + resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" + integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= + dependencies: + bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" + crypto-js "^3.1.4" + utf8 "^2.1.1" + xhr2 "*" + xmlhttprequest "*" + +web3@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.7.0.tgz#5867cd10a2bebb5c33fc218368e3f6f826f6897e" + integrity sha512-n39O7QQNkpsjhiHMJ/6JY6TaLbdX+2FT5iGs8tb3HbIWOhPm4+a7UDbr5Lkm+gLa9aRKWesZs5D5hWyEvg4aJA== + dependencies: + web3-bzz "1.7.0" + web3-core "1.7.0" + web3-eth "1.7.0" + web3-eth-personal "1.7.0" + web3-net "1.7.0" + web3-shh "1.7.0" + web3-utils "1.7.0" + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + +websocket@1.0.32: + version "1.0.32" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.32.tgz#1f16ddab3a21a2d929dec1687ab21cfdc6d3dbb1" + integrity sha512-i4yhcllSP4wrpoPMU2N0TQ/q0O94LRG/eUQjEAamRltjQ1oT1PFFKOG4i877OlJgCG8rw6LrrowJp+TYCEWF7Q== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +websocket@^1.0.31, websocket@^1.0.32: + version "1.0.34" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" + integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== + dependencies: + bufferutil "^4.0.1" + debug "^2.2.0" + es5-ext "^0.10.50" + typedarray-to-buffer "^3.1.5" + utf-8-validate "^5.0.2" + yaeti "^0.0.6" + +whatwg-fetch@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== + +whatwg-fetch@>=0.10.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" + integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which-typed-array@^1.1.2: + version "1.1.7" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.7.tgz#2761799b9a22d4b8660b3c1b40abaa7739691793" + integrity sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-abstract "^1.18.5" + foreach "^2.0.5" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.7" + +which@1.3.1, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +window-size@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" + integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= + +wordwrapjs@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.1.tgz#d9790bccfb110a0fc7836b5ebce0937b37a8b98f" + integrity sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA== + dependencies: + reduce-flatten "^2.0.0" + typical "^5.2.0" + +workerpool@6.1.5: + version "6.1.5" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.5.tgz#0f7cf076b6215fd7e1da903ff6f22ddd1886b581" + integrity sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw== + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +ws@7.4.6: + version "7.4.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" + integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== + +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" + integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ultron "~1.1.0" + +ws@^5.1.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.3.tgz#05541053414921bc29c63bee14b8b0dd50b07b3d" + integrity sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA== + dependencies: + async-limiter "~1.0.0" + +ws@^7.4.6: + version "7.5.6" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.6.tgz#e59fc509fb15ddfb65487ee9765c5a51dec5fe7b" + integrity sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA== + +xhr-request-promise@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" + integrity sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg== + dependencies: + xhr-request "^1.1.0" + +xhr-request@^1.0.1, xhr-request@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= + dependencies: + cookiejar "^2.1.1" + +xhr2@*: + version "0.2.1" + resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.1.tgz#4e73adc4f9cfec9cbd2157f73efdce3a5f108a93" + integrity sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw== + +xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: + version "2.6.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" + integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== + dependencies: + global "~4.4.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" + +xmlhttprequest@*, xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= + +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +xtend@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" + integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= + dependencies: + object-keys "~0.4.0" + +y18n@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" + integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + +yargs-parser@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" + integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= + dependencies: + camelcase "^3.0.0" + lodash.assign "^4.0.6" + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-parser@^21.0.0: + version "21.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.0.tgz#a485d3966be4317426dd56bdb6a30131b281dc55" + integrity sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA== + +yargs-parser@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" + integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== + dependencies: + camelcase "^4.1.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@13.3.2, yargs@^13.3.0: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^10.0.3: + version "10.1.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" + integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^8.1.0" + +yargs@^17.1.1: + version "17.3.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9" + integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + +yargs@^4.7.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" + integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= + dependencies: + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + lodash.assign "^4.0.3" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.1" + which-module "^1.0.0" + window-size "^0.2.0" + y18n "^3.2.1" + yargs-parser "^2.4.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 96107ced2b2ae0d4b6b6338a8d7c29a584ada2c5 Mon Sep 17 00:00:00 2001 From: Roshan <48975233+loverush@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:06:50 +0800 Subject: [PATCH 03/48] [WIP]Fast Finality: reward distribution and slash parts (#8) * [WIP]Fast Finality: reward distribution and slash parts * Update codes * Fix review comments and update test * Fix code errors related contract SystemReward and BSCValidatorSet * Fix code errors related invalid opcode and add new api * Optimize gasused of updateValidator and update test * Optimize gasused of updateValidator and update test * Minor error fixed * Fix review comments and update scripts * Fix init issue * Fix external view issue and update test * Fix review comments --- .gitignore | 1 + .prettierignore | 4 +- .prettierrc | 6 +- contracts/BSCValidatorSet.sol | 466 ++-- contracts/BSCValidatorSet.template | 411 ++-- contracts/CrossChain.sol | 48 +- contracts/CrossChain.template | 48 +- contracts/RelayerIncentivize.sol | 78 +- contracts/RelayerIncentivize.template | 78 +- contracts/SlashIndicator.sol | 165 +- contracts/SlashIndicator.template | 168 +- contracts/System.sol | 2 +- contracts/System.template | 12 +- contracts/SystemReward.sol | 44 +- contracts/SystemReward.template | 52 +- contracts/TendermintLightClient.sol | 52 +- contracts/TendermintLightClient.template | 52 +- contracts/TokenHub.sol | 278 +-- contracts/TokenHub.template | 278 +-- contracts/interface/IBSCValidatorSet.sol | 5 +- test/BSCValidatorSet.js | 969 +++++--- test/GovHub.js | 970 +++++--- test/RelayerHub.js | 52 +- test/Slash.js | 453 ++-- test/SystemReward.js | 50 +- test/TestRelayerIncentivize.js | 742 +++--- test/TestTendermintLightClient.js | 31 +- test/TestTokenHub.js | 2749 +++++++++++++--------- test/ToolTest.js | 17 +- truffle-config.js | 4 +- 30 files changed, 5039 insertions(+), 3246 deletions(-) diff --git a/.gitignore b/.gitignore index ba50d26e..8dce3875 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ cache artifacts .env +.DS_Store types typechain-types diff --git a/.prettierignore b/.prettierignore index ba025543..8a9521ce 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,5 @@ -artifacts +/contracts/artifacts +build cache node_modules +typechain-types \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 2caa9822..f9ca8909 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,15 +1,15 @@ { - "printWidth": 100, + "printWidth": 120, "trailingComma": "es5", "semi": true, - "singleQuote": true, + "singleQuote": false, "tabWidth": 2, "overrides": [ { "files": "*.sol", "options": { "semi": true, - "printWidth": 100 + "printWidth": 120 } } ] diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index e625c318..05855b42 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -1,4 +1,5 @@ pragma solidity 0.6.4; +pragma experimental ABIEncoderV2; import "./System.sol"; import "./lib/BytesToTypes.sol"; @@ -49,7 +50,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // key is the `consensusAddress` of `Validator`, // value is the index of the element in `currentValidatorSet`. - mapping(address =>uint256) public currentValidatorSetMap; + mapping(address => uint256) public currentValidatorSetMap; uint256 public numOfJailed; uint256 public constant BURN_RATIO_SCALE = 10000; @@ -69,16 +70,23 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // Corresponds strictly to currentValidatorSet // validatorExtraSet[index] = the `ValidatorExtra` info of currentValidatorSet[index] ValidatorExtra[] public validatorExtraSet; + // BEP-131 candidate validator uint256 public numOfCabinets; uint256 public maxNumOfCandidates; uint256 public maxNumOfWorkingCandidates; - struct Validator{ + // BEP-126 Fast Finality + uint256 public constant FINALITY_REWARD_RATIO = 10; + + uint256 public finalityRewardRatio; + uint256 public previousHeight; + + struct Validator { address consensusAddress; address payable feeAddress; address BBCFeeAddress; - uint64 votingPower; + uint64 votingPower; // only in state bool jailed; @@ -90,14 +98,18 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 enterMaintenanceHeight; // the height from where the validator enters Maintenance bool isMaintaining; + // BEP-126 Fast Finality + bytes voteAddress; + // reserve for future use - uint256[20] slots; + uint256[19] slots; } /*********************** cross chain package **************************/ struct IbcValidatorSetPackage { - uint8 packageType; + uint8 packageType; Validator[] validatorSet; + bytes[] voteAddrs; } /*********************** modifiers **************************/ @@ -115,8 +127,13 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica validatorExtraSet.push(validatorExtra); } } + _; + } + modifier oncePerBlock() { + require(block.number > previousHeight, "can not distribute finality reward twice in one block"); _; + previousHeight = block.number; } /*********************** events **************************/ @@ -141,26 +158,28 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event validatorExitMaintenance(address indexed validator); /*********************** init **************************/ - function init() external onlyNotInit{ - (IbcValidatorSetPackage memory validatorSetPkg, bool valid)= decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); + function init() external onlyNotInit { + (IbcValidatorSetPackage memory validatorSetPkg, bool valid) = decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); require(valid, "failed to parse init validatorSet"); - for (uint i;i0) { - Validator storage validator = currentValidatorSet[index-1]; + if (index > 0) { + Validator storage validator = currentValidatorSet[index - 1]; if (validator.jailed) { - emit deprecatedDeposit(valAddr,value); + emit deprecatedDeposit(valAddr, value); } else { totalInComing = totalInComing.add(value); validator.incoming = validator.incoming.add(value); - emit validatorDeposit(valAddr,value); + emit validatorDeposit(valAddr, value); } } else { // get incoming from deprecated validator; - emit deprecatedDeposit(valAddr,value); + emit deprecatedDeposit(valAddr, value); } } function jailValidator(Validator memory v) internal returns (uint32) { uint256 index = currentValidatorSetMap[v.consensusAddress]; - if (index==0 || currentValidatorSet[index-1].jailed) { + if (index == 0 || currentValidatorSet[index - 1].jailed) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } uint n = currentValidatorSet.length; - bool shouldKeep = (numOfJailed >= n-1); + bool shouldKeep = (numOfJailed >= n - 1); // will not jail if it is the last valid validator if (shouldKeep) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } numOfJailed ++; - currentValidatorSet[index-1].jailed = true; + currentValidatorSet[index - 1].jailed = true; emit validatorJailed(v.consensusAddress); return CODE_OK; } - function updateValidatorSet(Validator[] memory validatorSet) internal returns (uint32) { + function updateValidatorSet(Validator[] memory validatorSet, bytes[] memory voteAddrs) internal returns (uint32) { { // do verify. - (bool valid, string memory errMsg) = checkValidatorSet(validatorSet); - if (!valid) { - emit failReasonWithStr(errMsg); + if (validatorSet.length > MAX_NUM_OF_VALIDATORS) { + emit failReasonWithStr("the number of validators exceed the limit"); return ERROR_FAIL_CHECK_VALIDATORS; } + for (uint i; i < validatorSet.length; ++i) { + for (uint j; j < i; j++) { + if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) { + emit failReasonWithStr("duplicate consensus address of validatorSet"); + return ERROR_FAIL_CHECK_VALIDATORS; + } + } + } } // step 0: force all maintaining validators to exit `Temporary Maintenance` // - 1. validators exit maintenance // - 2. clear all maintainInfo // - 3. get unjailed validators from validatorSet - Validator[] memory validatorSetTemp = _forceMaintainingValidatorsExit(validatorSet); - - //step 1: do calculate distribution, do not make it as an internal function for saving gas. - uint crossSize; - uint directSize; - uint validatorsNum = currentValidatorSet.length; - for (uint i; i < validatorsNum; ++i) { - if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { - crossSize ++; - } else if (currentValidatorSet[i].incoming > 0) { - directSize ++; - } - } - - //cross transfer - address[] memory crossAddrs = new address[](crossSize); - uint256[] memory crossAmounts = new uint256[](crossSize); - uint256[] memory crossIndexes = new uint256[](crossSize); - address[] memory crossRefundAddrs = new address[](crossSize); - uint256 crossTotal; - // direct transfer - address payable[] memory directAddrs = new address payable[](directSize); - uint256[] memory directAmounts = new uint256[](directSize); - crossSize = 0; - directSize = 0; - uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); - if (relayFee > DUSTY_INCOMING) { - emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); - return ERROR_RELAYFEE_TOO_LARGE; - } - for (uint i; i < validatorsNum; ++i) { - if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { - crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; - uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; - crossAmounts[crossSize] = value.sub(relayFee); - crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; - crossIndexes[crossSize] = i; - crossTotal = crossTotal.add(value); - crossSize ++; - } else if (currentValidatorSet[i].incoming > 0) { - directAddrs[directSize] = currentValidatorSet[i].feeAddress; - directAmounts[directSize] = currentValidatorSet[i].incoming; - directSize ++; - } - } - - //step 2: do cross chain transfer - bool failCross = false; - if (crossTotal > 0) { - try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value:crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { - if (success) { - emit batchTransfer(crossTotal); - } else { - emit batchTransferFailed(crossTotal, "batch transfer return false"); + (Validator[] memory validatorSetTemp, bytes[] memory voteAddrsTemp) = _forceMaintainingValidatorsExit(validatorSet, voteAddrs); + + { + //step 1: do calculate distribution, do not make it as an internal function for saving gas. + uint crossSize; + uint directSize; + uint validatorsNum = currentValidatorSet.length; + for (uint i; i < validatorsNum; ++i) { + if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { + crossSize ++; + } else if (currentValidatorSet[i].incoming > 0) { + directSize ++; } - }catch Error(string memory reason) { - failCross = true; - emit batchTransferFailed(crossTotal, reason); - }catch (bytes memory lowLevelData) { - failCross = true; - emit batchTransferLowerFailed(crossTotal, lowLevelData); } - } - if (failCross) { - for (uint i; i< crossIndexes.length;++i) { - uint idx = crossIndexes[i]; - bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); - if (success) { - emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); - } else { - emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + //cross transfer + address[] memory crossAddrs = new address[](crossSize); + uint256[] memory crossAmounts = new uint256[](crossSize); + uint256[] memory crossIndexes = new uint256[](crossSize); + address[] memory crossRefundAddrs = new address[](crossSize); + uint256 crossTotal; + // direct transfer + address payable[] memory directAddrs = new address payable[](directSize); + uint256[] memory directAmounts = new uint256[](directSize); + crossSize = 0; + directSize = 0; + uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); + if (relayFee > DUSTY_INCOMING) { + emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); + return ERROR_RELAYFEE_TOO_LARGE; + } + for (uint i; i < validatorsNum; ++i) { + if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { + crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; + uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; + crossAmounts[crossSize] = value.sub(relayFee); + crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; + crossIndexes[crossSize] = i; + crossTotal = crossTotal.add(value); + crossSize ++; + } else if (currentValidatorSet[i].incoming > 0) { + directAddrs[directSize] = currentValidatorSet[i].feeAddress; + directAmounts[directSize] = currentValidatorSet[i].incoming; + directSize ++; } } - } - // step 3: direct transfer - if (directAddrs.length>0) { - for (uint i;i 0) { + try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value : crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { + if (success) { + emit batchTransfer(crossTotal); + } else { + emit batchTransferFailed(crossTotal, "batch transfer return false"); + } + }catch Error(string memory reason) { + failCross = true; + emit batchTransferFailed(crossTotal, reason); + }catch (bytes memory lowLevelData) { + failCross = true; + emit batchTransferLowerFailed(crossTotal, lowLevelData); + } + } + + if (failCross) { + for (uint i; i < crossIndexes.length; ++i) { + uint idx = crossIndexes[i]; + bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); + if (success) { + emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + } else { + emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + } + } + } + + // step 3: direct transfer + if (directAddrs.length > 0) { + for (uint i; i < directAddrs.length; ++i) { + bool success = directAddrs[i].send(directAmounts[i]); + if (success) { + emit directTransfer(directAddrs[i], directAmounts[i]); + } else { + emit directTransferFail(directAddrs[i], directAmounts[i]); + } } } } // step 4: do dusk transfer - if (address(this).balance>0) { + if (address(this).balance > 0) { emit systemTransfer(address(this).balance); address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance); } // step 5: do update validator set state totalInComing = 0; numOfJailed = 0; - if (validatorSetTemp.length>0) { - doUpdateState(validatorSetTemp); + if (validatorSetTemp.length > 0) { + doUpdateState(validatorSetTemp, voteAddrsTemp); } // step 6: clean slash contract @@ -362,46 +390,83 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return CODE_OK; } - function shuffle(address[] memory validators, uint256 epochNumber, uint startIdx, uint offset, uint limit, uint modNumber) internal pure { - for (uint i; i 0) { uint256 epochNumber = block.number / EPOCH; - shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); - shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, - _maxNumOfWorkingCandidates, validators.length-_numOfCabinets+_maxNumOfWorkingCandidates); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, _numOfCabinets - _maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length - _numOfCabinets + _maxNumOfWorkingCandidates); } address[] memory miningValidators = new address[](_numOfCabinets); - for (uint i; i<_numOfCabinets; ++i) { + bytes[] memory miningVoteAddrs = new bytes[](_numOfCabinets); + for (uint i; i < _numOfCabinets; ++i) { miningValidators[i] = validators[i]; + miningVoteAddrs[i] = voteAddrs[i]; } - return miningValidators; + return (miningValidators, miningVoteAddrs); } - function getValidators() public view returns(address[] memory) { + function getValidators() public view returns (address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; for (uint i; i 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; - if (workingValidatorCount > _numOfCabinets) { - workingValidatorCount = _numOfCabinets; + function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyInit { + if (finalityRewardRatio == 0) { + finalityRewardRatio = FINALITY_REWARD_RATIO; } - if (workingValidatorCount == 0) { - workingValidatorCount = 1; + + uint256 totalValue; + totalValue = (address(SYSTEM_REWARD_ADDR).balance * finalityRewardRatio) / 100; + totalValue = ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(payable(address(this)), totalValue); + if (totalValue == 0) { + return; + } + + uint256 totalWeight; + for (uint256 i = 0; i < weights.length; i++) { + totalWeight += weights[i]; + } + if (totalWeight == 0) { + return; } + + uint256 value; + address valAddr; + uint256 index; + + for (uint256 i = 0; i < valAddrs.length; i++) { + value = (totalValue * weights[i]) / totalWeight; + valAddr = valAddrs[i]; + index = currentValidatorSetMap[valAddr]; + if (index > 0) { + Validator storage validator = currentValidatorSet[index - 1]; + if (validator.jailed) { + emit deprecatedDeposit(valAddr, value); + } else { + totalInComing = totalInComing.add(value); + validator.incoming = validator.incoming.add(value); + emit validatorDeposit(valAddr, value); + } + } else { + // get incoming from deprecated validator; + emit deprecatedDeposit(valAddr, value); + } + } + } + /*********************** For slash **************************/ function misdemeanor(address validator) external onlySlash initValidatorExtraSet override { uint256 validatorIndex = _misdemeanor(validator); @@ -470,7 +570,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - function felony(address validator)external onlySlash initValidatorExtraSet override{ + function felony(address validator) external onlySlash initValidatorExtraSet override { uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { return; @@ -538,7 +638,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov{ + function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov { if (Memory.compareStrings(key, "expireTimeSecondGap")) { require(value.length == 32, "length of expireTimeSecondGap mismatch"); uint256 newExpireTimeSecondGap = BytesToTypes.bytesToUint256(32, value); @@ -557,7 +657,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (_numOfCabinets == 0) { _numOfCabinets = INIT_NUM_OF_CABINETS; } - require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCaninates"); + require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCabinets"); maxNumOfMaintaining = newMaxNumOfMaintaining; } else if (Memory.compareStrings(key, "maintainSlashScale")) { require(value.length == 32, "length of maintainSlashScale mismatch"); @@ -582,6 +682,11 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica require(newNumOfCabinets > 0, "the numOfCabinets must be greater than 0"); require(newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS"); numOfCabinets = newNumOfCabinets; + } else if (Memory.compareStrings(key, "finalityRewardRatio")) { + require(value.length == 32, "length of finalityRewardRatio mismatch"); + uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); + require(newFinalityRewardRatio >= 10 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); } @@ -589,75 +694,58 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** Internal Functions **************************/ - - function checkValidatorSet(Validator[] memory validatorSet) private pure returns(bool, string memory) { - if (validatorSet.length > MAX_NUM_OF_VALIDATORS){ - return (false, "the number of validators exceed the limit"); - } - for (uint i; i < validatorSet.length; ++i) { - for (uint j = 0; jm) { - for (uint i = m; i < n; ++i) { + for (uint i = m; i < n; i++) { currentValidatorSet.pop(); validatorExtraSet.pop(); } } - uint k = n < m ? n:m; + uint k = n < m ? n : m; for (uint i; i < k; ++i) { - if (!isSameValidator(validatorSet[i], currentValidatorSet[i])) { - currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; - currentValidatorSet[i] = validatorSet[i]; - } else { - currentValidatorSet[i].incoming = 0; - } + currentValidatorSetMap[validatorSet[i].consensusAddress] = i + 1; + currentValidatorSet[i] = validatorSet[i]; + validatorExtraSet[i].voteAddress = voteAddrs[i]; + validatorExtraSet[i].isMaintaining = false; + validatorExtraSet[i].enterMaintenanceHeight = 0; } if (m>n) { - ValidatorExtra memory validatorExtra; + ValidatorExtra memory _validatorExtra; for (uint i = n; i < m; ++i) { + _validatorExtra.voteAddress = voteAddrs[i]; currentValidatorSet.push(validatorSet[i]); - validatorExtraSet.push(validatorExtra); - currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; + validatorExtraSet.push(_validatorExtra); + currentValidatorSetMap[validatorSet[i].consensusAddress] = i + 1; } } // make sure all new validators are cleared maintainInfo // should not happen, still protect numOfMaintaining = 0; - n = currentValidatorSet.length; - for (uint i; i < n; ++i) { - validatorExtraSet[i].isMaintaining = false; - validatorExtraSet[i].enterMaintenanceHeight = 0; - } } - function isSameValidator(Validator memory v1, Validator memory v2) private pure returns(bool) { - return v1.consensusAddress == v2.consensusAddress && v1.feeAddress == v2.feeAddress && v1.BBCFeeAddress == v2.BBCFeeAddress && v1.votingPower == v2.votingPower; + function getVoteAddresses(uint length) internal view returns (bytes[] memory) { + uint n = currentValidatorSet.length; + bytes[] memory voteAddrs = new bytes[](length); + if (validatorExtraSet.length != n) { + return voteAddrs; + } + uint index = 0; + for (uint i = 0; i < n; i++) { + if (isWorkingValidator(i)) { + voteAddrs[index] = validatorExtraSet[i].voteAddress; + index ++; + } + } + return voteAddrs; } function _misdemeanor(address validator) private returns (uint256) { @@ -723,7 +811,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return true; } - function _forceMaintainingValidatorsExit(Validator[] memory _validatorSet) private returns (Validator[] memory unjailedValidatorSet){ + function _forceMaintainingValidatorsExit(Validator[] memory _validatorSet, bytes[] memory _voteAddrs) private returns (Validator[] memory unjailedValidatorSet, bytes[] memory unjailedVoteAddrs){ uint256 numOfFelony = 0; address validator; bool isFelony; @@ -762,15 +850,17 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // 2. get unjailed validators from validatorSet unjailedValidatorSet = new Validator[](_validatorSet.length - numOfFelony); + unjailedVoteAddrs = new bytes[](_validatorSet.length - numOfFelony); i = 0; for (uint index; index < _validatorSet.length; ++index) { if (!_validatorSet[index].jailed) { unjailedValidatorSet[i] = _validatorSet[index]; - i++; + unjailedVoteAddrs[i] = _voteAddrs[index]; + ++i; } } - return unjailedValidatorSet; + return (unjailedValidatorSet, unjailedVoteAddrs); } function _enterMaintenance(address validator, uint256 index) private { @@ -825,13 +915,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica validatorSetPkg.packageType = uint8(iter.next().toUint()); } else if (idx == 1) { RLPDecode.RLPItem[] memory items = iter.next().toList(); - validatorSetPkg.validatorSet =new Validator[](items.length); - for (uint j;j previousHeight, "can not distribute finality reward twice in one block"); _; + previousHeight = block.number; } /*********************** events **************************/ @@ -141,26 +157,28 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event validatorExitMaintenance(address indexed validator); /*********************** init **************************/ - function init() external onlyNotInit{ - (IbcValidatorSetPackage memory validatorSetPkg, bool valid)= decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); + function init() external onlyNotInit { + (IbcValidatorSetPackage memory validatorSetPkg, bool valid) = decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); require(valid, "failed to parse init validatorSet"); for (uint i;i MAX_NUM_OF_VALIDATORS) { + emit failReasonWithStr("the number of validators exceed the limit"); return ERROR_FAIL_CHECK_VALIDATORS; } + for (uint i = 0; i < validatorSet.length; i++) { + for (uint j = 0; j < i; j++) { + if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) { + emit failReasonWithStr("duplicate consensus address of validatorSet"); + return ERROR_FAIL_CHECK_VALIDATORS; + } + } + } } // step 0: force all maintaining validators to exit `Temporary Maintenance` // - 1. validators exit maintenance // - 2. clear all maintainInfo // - 3. get unjailed validators from validatorSet - Validator[] memory validatorSetTemp = _forceMaintainingValidatorsExit(validatorSet); - - //step 1: do calculate distribution, do not make it as an internal function for saving gas. - uint crossSize; - uint directSize; - uint validatorsNum = currentValidatorSet.length; - for (uint i; i < validatorsNum; ++i) { - if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { - crossSize ++; - } else if (currentValidatorSet[i].incoming > 0) { - directSize ++; - } - } - - //cross transfer - address[] memory crossAddrs = new address[](crossSize); - uint256[] memory crossAmounts = new uint256[](crossSize); - uint256[] memory crossIndexes = new uint256[](crossSize); - address[] memory crossRefundAddrs = new address[](crossSize); - uint256 crossTotal; - // direct transfer - address payable[] memory directAddrs = new address payable[](directSize); - uint256[] memory directAmounts = new uint256[](directSize); - crossSize = 0; - directSize = 0; - uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); - if (relayFee > DUSTY_INCOMING) { - emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); - return ERROR_RELAYFEE_TOO_LARGE; - } - for (uint i; i < validatorsNum; ++i) { - if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { - crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; - uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; - crossAmounts[crossSize] = value.sub(relayFee); - crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; - crossIndexes[crossSize] = i; - crossTotal = crossTotal.add(value); - crossSize ++; - } else if (currentValidatorSet[i].incoming > 0) { - directAddrs[directSize] = currentValidatorSet[i].feeAddress; - directAmounts[directSize] = currentValidatorSet[i].incoming; - directSize ++; - } - } - - //step 2: do cross chain transfer - bool failCross = false; - if (crossTotal > 0) { - try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value:crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { - if (success) { - emit batchTransfer(crossTotal); - } else { - emit batchTransferFailed(crossTotal, "batch transfer return false"); + (Validator[] memory validatorSetTemp, bytes[] memory voteAddrsTemp) = _forceMaintainingValidatorsExit(validatorSet, voteAddrs); + + { + //step 1: do calculate distribution, do not make it as an internal function for saving gas. + uint crossSize; + uint directSize; + uint validatorsNum = currentValidatorSet.length; + for (uint i; i < validatorsNum; ++i) { + if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { + crossSize ++; + } else if (currentValidatorSet[i].incoming > 0) { + directSize ++; } - }catch Error(string memory reason) { - failCross = true; - emit batchTransferFailed(crossTotal, reason); - }catch (bytes memory lowLevelData) { - failCross = true; - emit batchTransferLowerFailed(crossTotal, lowLevelData); } - } - if (failCross) { - for (uint i; i< crossIndexes.length;++i) { - uint idx = crossIndexes[i]; - bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); - if (success) { - emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); - } else { - emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + //cross transfer + address[] memory crossAddrs = new address[](crossSize); + uint256[] memory crossAmounts = new uint256[](crossSize); + uint256[] memory crossIndexes = new uint256[](crossSize); + address[] memory crossRefundAddrs = new address[](crossSize); + uint256 crossTotal; + // direct transfer + address payable[] memory directAddrs = new address payable[](directSize); + uint256[] memory directAmounts = new uint256[](directSize); + crossSize = 0; + directSize = 0; + uint256 relayFee = ITokenHub(TOKEN_HUB_ADDR).getMiniRelayFee(); + if (relayFee > DUSTY_INCOMING) { + emit failReasonWithStr("fee is larger than DUSTY_INCOMING"); + return ERROR_RELAYFEE_TOO_LARGE; + } + for (uint i; i < validatorsNum; ++i) { + if (currentValidatorSet[i].incoming >= DUSTY_INCOMING) { + crossAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; + uint256 value = currentValidatorSet[i].incoming - currentValidatorSet[i].incoming % PRECISION; + crossAmounts[crossSize] = value.sub(relayFee); + crossRefundAddrs[crossSize] = currentValidatorSet[i].BBCFeeAddress; + crossIndexes[crossSize] = i; + crossTotal = crossTotal.add(value); + crossSize ++; + } else if (currentValidatorSet[i].incoming > 0) { + directAddrs[directSize] = currentValidatorSet[i].feeAddress; + directAmounts[directSize] = currentValidatorSet[i].incoming; + directSize ++; } } - } - // step 3: direct transfer - if (directAddrs.length>0) { - for (uint i;i 0) { + try ITokenHub(TOKEN_HUB_ADDR).batchTransferOutBNB{value : crossTotal}(crossAddrs, crossAmounts, crossRefundAddrs, uint64(block.timestamp + expireTimeSecondGap)) returns (bool success) { + if (success) { + emit batchTransfer(crossTotal); + } else { + emit batchTransferFailed(crossTotal, "batch transfer return false"); + } + }catch Error(string memory reason) { + failCross = true; + emit batchTransferFailed(crossTotal, reason); + }catch (bytes memory lowLevelData) { + failCross = true; + emit batchTransferLowerFailed(crossTotal, lowLevelData); + } + } + + if (failCross) { + for (uint i; i< crossIndexes.length;++i) { + uint idx = crossIndexes[i]; + bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); + if (success) { + emit directTransfer(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + } else { + emit directTransferFail(currentValidatorSet[idx].feeAddress, currentValidatorSet[idx].incoming); + } + } + } + + // step 3: direct transfer + if (directAddrs.length>0) { + for (uint i;i0) { - doUpdateState(validatorSetTemp); + doUpdateState(validatorSetTemp, voteAddrsTemp); } // step 6: clean slash contract @@ -362,18 +389,51 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return CODE_OK; } - function shuffle(address[] memory validators, uint256 epochNumber, uint startIdx, uint offset, uint limit, uint modNumber) internal pure { + function shuffle(address[] memory validators, bytes[] memory voteAddrs, uint256 epochNumber, uint startIdx, uint offset, uint limit, uint modNumber) internal pure { for (uint i; i 0) { uint256 epochNumber = block.number / EPOCH; - shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); - shuffle(validators, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, - _maxNumOfWorkingCandidates, validators.length-_numOfCabinets+_maxNumOfWorkingCandidates); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, _numOfCabinets - _maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length - _numOfCabinets + _maxNumOfWorkingCandidates); } address[] memory miningValidators = new address[](_numOfCabinets); + bytes[] memory miningVoteAddrs = new bytes[](_numOfCabinets); for (uint i; i<_numOfCabinets; ++i) { miningValidators[i] = validators[i]; + miningVoteAddrs[i] = voteAddrs[i]; } - return miningValidators; + return (miningValidators, miningVoteAddrs); } - function getValidators() public view returns(address[] memory) { + function getValidators() public view returns (address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; for (uint i; i 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; - if (workingValidatorCount > _numOfCabinets) { - workingValidatorCount = _numOfCabinets; + function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyInit { + if (finalityRewardRatio == 0) { + finalityRewardRatio = FINALITY_REWARD_RATIO; } - if (workingValidatorCount == 0) { - workingValidatorCount = 1; + + uint256 totalValue; + totalValue = (address(SYSTEM_REWARD_ADDR).balance * finalityRewardRatio) / 100; + totalValue = ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(payable(address(this)), totalValue); + if (totalValue == 0) { + return; + } + + uint256 totalWeight; + for (uint256 i = 0; i < weights.length; i++) { + totalWeight += weights[i]; + } + if (totalWeight == 0) { + return; + } + + uint256 value; + address valAddr; + uint256 index; + + for (uint256 i = 0; i < valAddrs.length; i++) { + value = (totalValue * weights[i]) / totalWeight; + valAddr = valAddrs[i]; + index = currentValidatorSetMap[valAddr]; + if (index > 0) { + Validator storage validator = currentValidatorSet[index - 1]; + if (validator.jailed) { + emit deprecatedDeposit(valAddr, value); + } else { + totalInComing = totalInComing.add(value); + validator.incoming = validator.incoming.add(value); + emit validatorDeposit(valAddr, value); + } + } else { + // get incoming from deprecated validator; + emit deprecatedDeposit(valAddr, value); + } } + } + /*********************** For slash **************************/ function misdemeanor(address validator) external onlySlash initValidatorExtraSet override { uint256 validatorIndex = _misdemeanor(validator); @@ -557,7 +656,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (_numOfCabinets == 0) { _numOfCabinets = INIT_NUM_OF_CABINETS; } - require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCaninates"); + require(newMaxNumOfMaintaining < _numOfCabinets, "the maxNumOfMaintaining must be less than numOfCabinets"); maxNumOfMaintaining = newMaxNumOfMaintaining; } else if (Memory.compareStrings(key, "maintainSlashScale")) { require(value.length == 32, "length of maintainSlashScale mismatch"); @@ -582,6 +681,11 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica require(newNumOfCabinets > 0, "the numOfCabinets must be greater than 0"); require(newNumOfCabinets <= MAX_NUM_OF_VALIDATORS, "the numOfCabinets must be less than MAX_NUM_OF_VALIDATORS"); numOfCabinets = newNumOfCabinets; + } else if (Memory.compareStrings(key, "finalityRewardRatio")) { + require(value.length == 32, "length of finalityRewardRatio mismatch"); + uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); + require(newFinalityRewardRatio >= 10 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); } @@ -589,37 +693,14 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** Internal Functions **************************/ - - function checkValidatorSet(Validator[] memory validatorSet) private pure returns(bool, string memory) { - if (validatorSet.length > MAX_NUM_OF_VALIDATORS){ - return (false, "the number of validators exceed the limit"); - } - for (uint i; i < validatorSet.length; ++i) { - for (uint j = 0; jm) { @@ -630,18 +711,18 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } uint k = n < m ? n:m; for (uint i; i < k; ++i) { - if (!isSameValidator(validatorSet[i], currentValidatorSet[i])) { - currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; - currentValidatorSet[i] = validatorSet[i]; - } else { - currentValidatorSet[i].incoming = 0; - } + currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; + currentValidatorSet[i] = validatorSet[i]; + validatorExtraSet[i].voteAddress = voteAddrs[i]; + validatorExtraSet[i].isMaintaining = false; + validatorExtraSet[i].enterMaintenanceHeight = 0; } if (m>n) { - ValidatorExtra memory validatorExtra; - for (uint i = n; i < m; ++i) { + ValidatorExtra memory _validatorExtra; + for (uint i = n; i < m; i++) { + _validatorExtra.voteAddress = voteAddrs[i]; currentValidatorSet.push(validatorSet[i]); - validatorExtraSet.push(validatorExtra); + validatorExtraSet.push(_validatorExtra); currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; } } @@ -656,8 +737,20 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - function isSameValidator(Validator memory v1, Validator memory v2) private pure returns(bool) { - return v1.consensusAddress == v2.consensusAddress && v1.feeAddress == v2.feeAddress && v1.BBCFeeAddress == v2.BBCFeeAddress && v1.votingPower == v2.votingPower; + function getVoteAddresses(uint length) internal view returns (bytes[] memory) { + uint n = currentValidatorSet.length; + bytes[] memory voteAddrs = new bytes[](length); + if (validatorExtraSet.length != n) { + return voteAddrs; + } + uint index = 0; + for (uint i = 0; i < n; i++) { + if (isWorkingValidator(i)) { + voteAddrs[index] = validatorExtraSet[i].voteAddress; + index ++; + } + } + return voteAddrs; } function _misdemeanor(address validator) private returns (uint256) { @@ -723,7 +816,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return true; } - function _forceMaintainingValidatorsExit(Validator[] memory _validatorSet) private returns (Validator[] memory unjailedValidatorSet){ + function _forceMaintainingValidatorsExit(Validator[] memory _validatorSet, bytes[] memory _voteAddrs) private returns (Validator[] memory unjailedValidatorSet, bytes[] memory unjailedVoteAddrs){ uint256 numOfFelony = 0; address validator; bool isFelony; @@ -762,15 +855,17 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // 2. get unjailed validators from validatorSet unjailedValidatorSet = new Validator[](_validatorSet.length - numOfFelony); + unjailedVoteAddrs = new bytes[](_validatorSet.length - numOfFelony); i = 0; for (uint index; index < _validatorSet.length; ++index) { if (!_validatorSet[index].jailed) { unjailedValidatorSet[i] = _validatorSet[index]; + unjailedVoteAddrs[i] = _voteAddrs[index]; i++; } } - return unjailedValidatorSet; + return (unjailedValidatorSet, unjailedVoteAddrs); } function _enterMaintenance(address validator, uint256 index) private { @@ -825,13 +920,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica validatorSetPkg.packageType = uint8(iter.next().toUint()); } else if (idx == 1) { RLPDecode.RLPItem[] memory items = iter.next().toList(); - validatorSetPkg.validatorSet =new Validator[](items.length); - for (uint j;j previousTxHeight) { oracleSequence++; txCounter = 1; - previousTxHeight=block.number; + previousTxHeight = block.number; } else { txCounter++; - if (txCounter>batchSizeForOracle) { + if (txCounter > batchSizeForOracle) { oracleSequence++; txCounter = 1; } @@ -287,7 +287,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte } require(isContract(handlerContract), "address is not a contract"); - channelHandlerContractMap[channelId]=handlerContract; + channelHandlerContractMap[channelId] = handlerContract; registeredContractChannelMap[handlerContract][channelId] = true; isRelayRewardFromSystemReward[channelId] = isRewardFromSystem; emit addChannel(channelId, handlerContract); @@ -306,7 +306,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte bool isEnable = (status == 1); address handlerContract = channelHandlerContractMap[channelId]; - if (handlerContract != address(0x00)) { //channel existing + if (handlerContract != address(0x00)) {//channel existing registeredContractChannelMap[handlerContract][channelId] = isEnable; emit enableOrDisableChannel(channelId, isEnable); } diff --git a/contracts/CrossChain.template b/contracts/CrossChain.template index c363268a..9b6234c1 100644 --- a/contracts/CrossChain.template +++ b/contracts/CrossChain.template @@ -13,7 +13,7 @@ import "./System.sol"; {% else %}import "./MerkleProof.sol"; {% endif %} -contract CrossChain is System, ICrossChain, IParamSubscriber{ +contract CrossChain is System, ICrossChain, IParamSubscriber { // constant variables string constant public STORE_NAME = "ibc"; @@ -50,7 +50,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ uint64 expectedSequence = channelReceiveSequenceMap[_channelID]; require(_sequence == expectedSequence, "sequence not in order"); - channelReceiveSequenceMap[_channelID]=expectedSequence+1; + channelReceiveSequenceMap[_channelID] = expectedSequence + 1; _; } @@ -60,7 +60,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ } modifier channelSupported(uint8 _channelID) { - require(channelHandlerContractMap[_channelID]!=address(0x0), "channel is not supported"); + require(channelHandlerContractMap[_channelID] != address(0x0), "channel is not supported"); _; } @@ -71,7 +71,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ // | length | prefix | sourceChainID| destinationChainID | channelID | sequence | // | 32 bytes | 1 byte | 2 bytes | 2 bytes | 1 bytes | 8 bytes | - function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns(bytes memory) { + function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns (bytes memory) { uint256 fullCROSS_CHAIN_KEY_PREFIX = CROSS_CHAIN_KEY_PREFIX | _channelID; bytes memory key = new bytes(14); @@ -121,37 +121,37 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ batchSizeForOracle = INIT_BATCH_SIZE; - oracleSequence = -1; + oracleSequence = - 1; previousTxHeight = 0; txCounter = 0; - alreadyInit=true; + alreadyInit = true; } -function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { + function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns (bytes memory) { uint256 payloadLength = msgBytes.length + 33; bytes memory payload = new bytes(payloadLength); uint256 ptr; assembly { ptr := payload } - ptr+=33; + ptr += 33; assembly { mstore(ptr, relayFee) } - ptr-=32; + ptr -= 32; assembly { mstore(ptr, packageType) } - ptr-=1; + ptr -= 1; assembly { mstore(ptr, payloadLength) } - ptr+=65; + ptr += 65; (uint256 src,) = Memory.fromBytes(msgBytes); Memory.copy(src, ptr, msgBytes.length); @@ -160,7 +160,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte // | type | relayFee |package | // | 1 byte | 32 bytes | bytes | - function decodePayloadHeader(bytes memory payload) internal pure returns(bool, uint8, uint256, bytes memory) { + function decodePayloadHeader(bytes memory payload) internal pure returns (bool, uint8, uint256, bytes memory) { if (payload.length < 33) { return (false, 0, 0, new bytes(0)); } @@ -171,27 +171,27 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte } uint8 packageType; - ptr+=1; + ptr += 1; assembly { packageType := mload(ptr) } uint256 relayFee; - ptr+=32; + ptr += 32; assembly { relayFee := mload(ptr) } - ptr+=32; - bytes memory msgBytes = new bytes(payload.length-33); - (uint256 dst, ) = Memory.fromBytes(msgBytes); - Memory.copy(ptr, dst, payload.length-33); + ptr += 32; + bytes memory msgBytes = new bytes(payload.length - 33); + (uint256 dst,) = Memory.fromBytes(msgBytes); + Memory.copy(ptr, dst, payload.length - 33); return (true, packageType, relayFee, msgBytes); } function handlePackage(bytes calldata payload, bytes calldata proof, uint64 height, uint64 packageSequence, uint8 channelId) onlyInit onlyRelayer - sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { + sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { bytes memory payloadLocal = payload; // fix error: stack too deep, try removing local variables bytes memory proofLocal = proof; // fix error: stack too deep, try removing local variables require(MerkleProof.validateMerkleProof(ILightClient(LIGHT_CLIENT_ADDR).getAppHash(height), STORE_NAME, generateKey(packageSequence, channelId), payloadLocal, proofLocal), "invalid merkle proof"); @@ -208,7 +208,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte if (packageType == SYN_PACKAGE) { address handlerContract = channelHandlerContractMap[channelIdLocal]; try IApplication(handlerContract).handleSynPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { - if (responsePayload.length!=0) { + if (responsePayload.length != 0) { sendPackage(channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(ACK_PACKAGE, 0, responsePayload)); channelSendSequenceMap[channelIdLocal] = channelSendSequenceMap[channelIdLocal] + 1; } @@ -245,10 +245,10 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte if (block.number > previousTxHeight) { oracleSequence++; txCounter = 1; - previousTxHeight=block.number; + previousTxHeight = block.number; } else { txCounter++; - if (txCounter>batchSizeForOracle) { + if (txCounter > batchSizeForOracle) { oracleSequence++; txCounter = 1; } @@ -288,7 +288,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte } require(isContract(handlerContract), "address is not a contract"); - channelHandlerContractMap[channelId]=handlerContract; + channelHandlerContractMap[channelId] = handlerContract; registeredContractChannelMap[handlerContract][channelId] = true; isRelayRewardFromSystemReward[channelId] = isRewardFromSystem; emit addChannel(channelId, handlerContract); @@ -307,7 +307,7 @@ function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgByte bool isEnable = (status == 1); address handlerContract = channelHandlerContractMap[channelId]; - if (handlerContract != address(0x00)) { //channel existing + if (handlerContract != address(0x00)) {//channel existing registeredContractChannelMap[handlerContract][channelId] = isEnable; emit enableOrDisableChannel(channelId, isEnable); } diff --git a/contracts/RelayerIncentivize.sol b/contracts/RelayerIncentivize.sol index 345df464..531c7373 100644 --- a/contracts/RelayerIncentivize.sol +++ b/contracts/RelayerIncentivize.sol @@ -31,11 +31,11 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { mapping(address => uint256) public packageRelayersSubmitCount; address payable[] public packageRelayerAddressRecord; - uint256 public collectedRewardForHeaderRelayer=0; - uint256 public collectedRewardForTransferRelayer=0; + uint256 public collectedRewardForHeaderRelayer = 0; + uint256 public collectedRewardForTransferRelayer = 0; - uint256 public roundSequence=0; - uint256 public countInRound=0; + uint256 public roundSequence = 0; + uint256 public countInRound = 0; mapping(address => uint256) public relayerRewardVault; @@ -47,14 +47,14 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function init() onlyNotInit external { require(!alreadyInit, "already initialized"); - headerRelayerRewardRateMolecule=HEADER_RELAYER_REWARD_RATE_MOLECULE; - headerRelayerRewardRateDenominator=HEADER_RELAYER_REWARD_RATE_DENOMINATOR; - callerCompensationMolecule=CALLER_COMPENSATION_MOLECULE; - callerCompensationDenominator=CALLER_COMPENSATION_DENOMINATOR; + headerRelayerRewardRateMolecule = HEADER_RELAYER_REWARD_RATE_MOLECULE; + headerRelayerRewardRateDenominator = HEADER_RELAYER_REWARD_RATE_DENOMINATOR; + callerCompensationMolecule = CALLER_COMPENSATION_MOLECULE; + callerCompensationDenominator = CALLER_COMPENSATION_DENOMINATOR; alreadyInit = true; } - receive() external payable{} + receive() external payable {} function addReward(address payable headerRelayerAddr, address payable packageRelayer, uint256 amount, bool fromSystemReward) onlyInit onlyCrossChainContract external override returns (bool) { @@ -65,7 +65,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } else { actualAmount = ISystemReward(TOKEN_HUB_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), amount); if (dynamicExtraIncentiveAmount > 0) { - actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); + actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); } } @@ -75,17 +75,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { collectedRewardForHeaderRelayer = collectedRewardForHeaderRelayer.add(reward); collectedRewardForTransferRelayer = collectedRewardForTransferRelayer.add(actualAmount).sub(reward); - if (headerRelayersSubmitCount[headerRelayerAddr]==0) { + if (headerRelayersSubmitCount[headerRelayerAddr] == 0) { headerRelayerAddressRecord.push(headerRelayerAddr); } headerRelayersSubmitCount[headerRelayerAddr]++; - if (packageRelayersSubmitCount[packageRelayer]==0) { + if (packageRelayersSubmitCount[packageRelayer] == 0) { packageRelayerAddressRecord.push(packageRelayer); } packageRelayersSubmitCount[packageRelayer]++; - if (countInRound>=ROUND_SIZE) { + if (countInRound >= ROUND_SIZE) { emit distributeCollectedReward(roundSequence, collectedRewardForHeaderRelayer, collectedRewardForTransferRelayer); uint256 callerHeaderReward = distributeHeaderRelayerReward(); @@ -100,17 +100,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } function claimRelayerReward(address relayerAddr) external { - uint256 reward = relayerRewardVault[relayerAddr]; - require(reward > 0, "no relayer reward"); - relayerRewardVault[relayerAddr] = 0; - address payable recipient = address(uint160(relayerAddr)); - if (!recipient.send(reward)) { - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(reward); - emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); - return; - } - emit rewardToRelayer(relayerAddr, reward); + uint256 reward = relayerRewardVault[relayerAddr]; + require(reward > 0, "no relayer reward"); + relayerRewardVault[relayerAddr] = 0; + address payable recipient = address(uint160(relayerAddr)); + if (!recipient.send(reward)) { + address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); + systemPayable.transfer(reward); + emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); + return; + } + emit rewardToRelayer(relayerAddr, reward); } function calculateRewardForHeaderRelayer(uint256 reward) internal view returns (uint256) { @@ -120,7 +120,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributeHeaderRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForHeaderRelayer; - uint256 totalWeight=0; + uint256 totalWeight = 0; address payable[] memory relayers = headerRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -151,7 +151,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributePackageRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForTransferRelayer; - uint256 totalWeight=0; + uint256 totalWeight = 0; address payable[] memory relayers = packageRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -179,19 +179,19 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { return callerReward; } - function calculateTransferRelayerWeight(uint256 count) public pure returns(uint256) { + function calculateTransferRelayerWeight(uint256 count) public pure returns (uint256) { if (count <= MAXIMUM_WEIGHT) { return count; - } else if (MAXIMUM_WEIGHT < count && count <= 2*MAXIMUM_WEIGHT) { + } else if (MAXIMUM_WEIGHT < count && count <= 2 * MAXIMUM_WEIGHT) { return MAXIMUM_WEIGHT; - } else if (2*MAXIMUM_WEIGHT < count && count <= (2*MAXIMUM_WEIGHT + 3*MAXIMUM_WEIGHT/4)) { - return 3*MAXIMUM_WEIGHT - count; + } else if (2 * MAXIMUM_WEIGHT < count && count <= (2 * MAXIMUM_WEIGHT + 3 * MAXIMUM_WEIGHT / 4)) { + return 3 * MAXIMUM_WEIGHT - count; } else { - return count/4; + return count / 4; } } - function calculateHeaderRelayerWeight(uint256 count) public pure returns(uint256) { + function calculateHeaderRelayerWeight(uint256 count) public pure returns (uint256) { if (count <= MAXIMUM_WEIGHT) { return count; } else { @@ -199,32 +199,32 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } } - function updateParam(string calldata key, bytes calldata value) override external onlyGov{ + function updateParam(string calldata key, bytes calldata value) override external onlyGov { require(alreadyInit, "contract has not been initialized"); - if (Memory.compareStrings(key,"headerRelayerRewardRateMolecule")) { + if (Memory.compareStrings(key, "headerRelayerRewardRateMolecule")) { require(value.length == 32, "length of headerRelayerRewardRateMolecule mismatch"); uint256 newHeaderRelayerRewardRateMolecule = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateMolecule <= headerRelayerRewardRateDenominator, "new headerRelayerRewardRateMolecule shouldn't be greater than headerRelayerRewardRateDenominator"); headerRelayerRewardRateMolecule = newHeaderRelayerRewardRateMolecule; - } else if (Memory.compareStrings(key,"headerRelayerRewardRateDenominator")) { + } else if (Memory.compareStrings(key, "headerRelayerRewardRateDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newHeaderRelayerRewardRateDenominator = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateDenominator != 0 && newHeaderRelayerRewardRateDenominator >= headerRelayerRewardRateMolecule, "the new headerRelayerRewardRateDenominator must not be zero and no less than headerRelayerRewardRateMolecule"); headerRelayerRewardRateDenominator = newHeaderRelayerRewardRateDenominator; - } else if (Memory.compareStrings(key,"callerCompensationMolecule")) { + } else if (Memory.compareStrings(key, "callerCompensationMolecule")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationMolecule = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationMolecule <= callerCompensationDenominator, "new callerCompensationMolecule shouldn't be greater than callerCompensationDenominator"); callerCompensationMolecule = newCallerCompensationMolecule; - } else if (Memory.compareStrings(key,"callerCompensationDenominator")) { + } else if (Memory.compareStrings(key, "callerCompensationDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationDenominator = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationDenominator != 0 && newCallerCompensationDenominator >= callerCompensationMolecule, "the newCallerCompensationDenominator must not be zero and no less than callerCompensationMolecule"); callerCompensationDenominator = newCallerCompensationDenominator; - } else if (Memory.compareStrings(key,"dynamicExtraIncentiveAmount")) { + } else if (Memory.compareStrings(key, "dynamicExtraIncentiveAmount")) { require(value.length == 32, "length of dynamicExtraIncentiveAmount mismatch"); uint256 newDynamicExtraIncentiveAmount = BytesToTypes.bytesToUint256(32, value); - require(newDynamicExtraIncentiveAmount >= 0 , "the newDynamicExtraIncentiveAmount must be no less than zero"); + require(newDynamicExtraIncentiveAmount >= 0, "the newDynamicExtraIncentiveAmount must be no less than zero"); dynamicExtraIncentiveAmount = newDynamicExtraIncentiveAmount; } else { require(false, "unknown param"); diff --git a/contracts/RelayerIncentivize.template b/contracts/RelayerIncentivize.template index 9e0b8465..baac5ca5 100644 --- a/contracts/RelayerIncentivize.template +++ b/contracts/RelayerIncentivize.template @@ -31,11 +31,11 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { mapping(address => uint256) public packageRelayersSubmitCount; address payable[] public packageRelayerAddressRecord; - uint256 public collectedRewardForHeaderRelayer=0; - uint256 public collectedRewardForTransferRelayer=0; + uint256 public collectedRewardForHeaderRelayer = 0; + uint256 public collectedRewardForTransferRelayer = 0; - uint256 public roundSequence=0; - uint256 public countInRound=0; + uint256 public roundSequence = 0; + uint256 public countInRound = 0; mapping(address => uint256) public relayerRewardVault; @@ -47,14 +47,14 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function init() onlyNotInit external { require(!alreadyInit, "already initialized"); - headerRelayerRewardRateMolecule=HEADER_RELAYER_REWARD_RATE_MOLECULE; - headerRelayerRewardRateDenominator=HEADER_RELAYER_REWARD_RATE_DENOMINATOR; - callerCompensationMolecule=CALLER_COMPENSATION_MOLECULE; - callerCompensationDenominator=CALLER_COMPENSATION_DENOMINATOR; + headerRelayerRewardRateMolecule = HEADER_RELAYER_REWARD_RATE_MOLECULE; + headerRelayerRewardRateDenominator = HEADER_RELAYER_REWARD_RATE_DENOMINATOR; + callerCompensationMolecule = CALLER_COMPENSATION_MOLECULE; + callerCompensationDenominator = CALLER_COMPENSATION_DENOMINATOR; alreadyInit = true; } - receive() external payable{} + receive() external payable {} {% if mock %} function addReward(address payable headerRelayerAddr, address payable packageRelayer, uint256 amount, bool fromSystemReward) external override returns (bool) { @@ -67,7 +67,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } else { actualAmount = ISystemReward(TOKEN_HUB_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), amount); if (dynamicExtraIncentiveAmount > 0) { - actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); + actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); } } @@ -77,17 +77,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { collectedRewardForHeaderRelayer = collectedRewardForHeaderRelayer.add(reward); collectedRewardForTransferRelayer = collectedRewardForTransferRelayer.add(actualAmount).sub(reward); - if (headerRelayersSubmitCount[headerRelayerAddr]==0) { + if (headerRelayersSubmitCount[headerRelayerAddr] == 0) { headerRelayerAddressRecord.push(headerRelayerAddr); } headerRelayersSubmitCount[headerRelayerAddr]++; - if (packageRelayersSubmitCount[packageRelayer]==0) { + if (packageRelayersSubmitCount[packageRelayer] == 0) { packageRelayerAddressRecord.push(packageRelayer); } packageRelayersSubmitCount[packageRelayer]++; - if (countInRound>=ROUND_SIZE) { + if (countInRound >= ROUND_SIZE) { emit distributeCollectedReward(roundSequence, collectedRewardForHeaderRelayer, collectedRewardForTransferRelayer); uint256 callerHeaderReward = distributeHeaderRelayerReward(); @@ -102,17 +102,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } function claimRelayerReward(address relayerAddr) external { - uint256 reward = relayerRewardVault[relayerAddr]; - require(reward > 0, "no relayer reward"); - relayerRewardVault[relayerAddr] = 0; - address payable recipient = address(uint160(relayerAddr)); - if (!recipient.send(reward)) { - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(reward); - emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); - return; - } - emit rewardToRelayer(relayerAddr, reward); + uint256 reward = relayerRewardVault[relayerAddr]; + require(reward > 0, "no relayer reward"); + relayerRewardVault[relayerAddr] = 0; + address payable recipient = address(uint160(relayerAddr)); + if (!recipient.send(reward)) { + address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); + systemPayable.transfer(reward); + emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); + return; + } + emit rewardToRelayer(relayerAddr, reward); } function calculateRewardForHeaderRelayer(uint256 reward) internal view returns (uint256) { @@ -122,7 +122,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributeHeaderRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForHeaderRelayer; - uint256 totalWeight=0; + uint256 totalWeight = 0; address payable[] memory relayers = headerRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -153,7 +153,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributePackageRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForTransferRelayer; - uint256 totalWeight=0; + uint256 totalWeight = 0; address payable[] memory relayers = packageRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -181,19 +181,19 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { return callerReward; } - function calculateTransferRelayerWeight(uint256 count) public pure returns(uint256) { + function calculateTransferRelayerWeight(uint256 count) public pure returns (uint256) { if (count <= MAXIMUM_WEIGHT) { return count; - } else if (MAXIMUM_WEIGHT < count && count <= 2*MAXIMUM_WEIGHT) { + } else if (MAXIMUM_WEIGHT < count && count <= 2 * MAXIMUM_WEIGHT) { return MAXIMUM_WEIGHT; - } else if (2*MAXIMUM_WEIGHT < count && count <= (2*MAXIMUM_WEIGHT + 3*MAXIMUM_WEIGHT/4)) { - return 3*MAXIMUM_WEIGHT - count; + } else if (2 * MAXIMUM_WEIGHT < count && count <= (2 * MAXIMUM_WEIGHT + 3 * MAXIMUM_WEIGHT / 4)) { + return 3 * MAXIMUM_WEIGHT - count; } else { - return count/4; + return count / 4; } } - function calculateHeaderRelayerWeight(uint256 count) public pure returns(uint256) { + function calculateHeaderRelayerWeight(uint256 count) public pure returns (uint256) { if (count <= MAXIMUM_WEIGHT) { return count; } else { @@ -201,32 +201,32 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } } - function updateParam(string calldata key, bytes calldata value) override external onlyGov{ + function updateParam(string calldata key, bytes calldata value) override external onlyGov { require(alreadyInit, "contract has not been initialized"); - if (Memory.compareStrings(key,"headerRelayerRewardRateMolecule")) { + if (Memory.compareStrings(key, "headerRelayerRewardRateMolecule")) { require(value.length == 32, "length of headerRelayerRewardRateMolecule mismatch"); uint256 newHeaderRelayerRewardRateMolecule = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateMolecule <= headerRelayerRewardRateDenominator, "new headerRelayerRewardRateMolecule shouldn't be greater than headerRelayerRewardRateDenominator"); headerRelayerRewardRateMolecule = newHeaderRelayerRewardRateMolecule; - } else if (Memory.compareStrings(key,"headerRelayerRewardRateDenominator")) { + } else if (Memory.compareStrings(key, "headerRelayerRewardRateDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newHeaderRelayerRewardRateDenominator = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateDenominator != 0 && newHeaderRelayerRewardRateDenominator >= headerRelayerRewardRateMolecule, "the new headerRelayerRewardRateDenominator must not be zero and no less than headerRelayerRewardRateMolecule"); headerRelayerRewardRateDenominator = newHeaderRelayerRewardRateDenominator; - } else if (Memory.compareStrings(key,"callerCompensationMolecule")) { + } else if (Memory.compareStrings(key, "callerCompensationMolecule")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationMolecule = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationMolecule <= callerCompensationDenominator, "new callerCompensationMolecule shouldn't be greater than callerCompensationDenominator"); callerCompensationMolecule = newCallerCompensationMolecule; - } else if (Memory.compareStrings(key,"callerCompensationDenominator")) { + } else if (Memory.compareStrings(key, "callerCompensationDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationDenominator = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationDenominator != 0 && newCallerCompensationDenominator >= callerCompensationMolecule, "the newCallerCompensationDenominator must not be zero and no less than callerCompensationMolecule"); callerCompensationDenominator = newCallerCompensationDenominator; - } else if (Memory.compareStrings(key,"dynamicExtraIncentiveAmount")) { + } else if (Memory.compareStrings(key, "dynamicExtraIncentiveAmount")) { require(value.length == 32, "length of dynamicExtraIncentiveAmount mismatch"); uint256 newDynamicExtraIncentiveAmount = BytesToTypes.bytesToUint256(32, value); - require(newDynamicExtraIncentiveAmount >= 0 , "the newDynamicExtraIncentiveAmount must be no less than zero"); + require(newDynamicExtraIncentiveAmount >= 0, "the newDynamicExtraIncentiveAmount must be no less than zero"); dynamicExtraIncentiveAmount = newDynamicExtraIncentiveAmount; } else { require(false, "unknown param"); diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 953cadcb..f48ffef9 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -1,16 +1,21 @@ pragma solidity 0.6.4; +pragma experimental ABIEncoderV2; + import "./System.sol"; import "./lib/BytesToTypes.sol"; +import "./lib/BytesLib.sol"; +import "./lib/TypesToBytes.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; import "./interface/IApplication.sol"; import "./interface/IBSCValidatorSet.sol"; import "./interface/IParamSubscriber.sol"; import "./interface/ICrossChain.sol"; +import "./interface/ISystemReward.sol"; import "./lib/CmnPkg.sol"; import "./lib/RLPEncode.sol"; -contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication{ +contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplication { using RLPEncode for *; uint256 public constant MISDEMEANOR_THRESHOLD = 50; @@ -28,6 +33,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication uint256 public misdemeanorThreshold; uint256 public felonyThreshold; + // BEP-126 Fast Finality + uint256 public constant FINALITY_DISTANCE = 11; + uint256 public constant FINALITY_SLASH_REWARD_RATIO = 20; + + uint256 public finalityDistance; + uint256 public finalitySlashRewardRatio; + event validatorSlashed(address indexed validator); event indicatorCleaned(); event paramChange(string key, bytes value); @@ -42,6 +54,17 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bool exist; } + // Proof that a validator misbehaved in fast finality + struct FinalityEvidence { + uint256 numA; + bytes32 headerA; + bytes sigA; + uint256 numB; + bytes32 headerB; + bytes sigB; + address valAddr; + } + modifier oncePerBlock() { require(block.number > previousHeight, "can not slash twice in one block"); _; @@ -50,19 +73,19 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication modifier onlyZeroGasPrice() { - require(tx.gasprice == 0 , "gasprice is not zero"); + require(tx.gasprice == 0, "gasprice is not zero"); _; } - - function init() external onlyNotInit{ + + function init() external onlyNotInit { misdemeanorThreshold = MISDEMEANOR_THRESHOLD; felonyThreshold = FELONY_THRESHOLD; alreadyInit = true; } /*********************** Implement cross chain app ********************************/ - function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns(bytes memory) { + function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns (bytes memory) { require(false, "receive unexpected syn package"); } @@ -82,7 +105,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } /*********************** External func ********************************/ - function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ + function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice { if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { return; } @@ -106,52 +129,51 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit validatorSlashed(validator); } - // To prevent validator misbehaving and leaving, do not clean slash record to zero, but decrease by felonyThreshold/DECREASE_RATE . // Clean is an effective implement to reorganize "validators" and "indicators". - function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit{ - if(validators.length == 0){ + function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit { + if (validators.length == 0) { return; } uint i = 0; - uint j = validators.length-1; - for (;i <= j;) { + uint j = validators.length - 1; + for (; i <= j;) { bool findLeft = false; bool findRight = false; - for(;i felonyThreshold/DECREASE_RATE){ - leftIndicator.count = leftIndicator.count - felonyThreshold/DECREASE_RATE; + if (leftIndicator.count > felonyThreshold / DECREASE_RATE) { + leftIndicator.count = leftIndicator.count - felonyThreshold / DECREASE_RATE; indicators[validators[i]] = leftIndicator; - }else{ + } else { findLeft = true; break; } } - for(;i<=j;j--){ + for (; i <= j; j--) { Indicator memory rightIndicator = indicators[validators[j]]; - if(rightIndicator.count > felonyThreshold/DECREASE_RATE){ - rightIndicator.count = rightIndicator.count - felonyThreshold/DECREASE_RATE; + if (rightIndicator.count > felonyThreshold / DECREASE_RATE) { + rightIndicator.count = rightIndicator.count - felonyThreshold / DECREASE_RATE; indicators[validators[j]] = rightIndicator; findRight = true; break; - }else{ + } else { delete indicators[validators[j]]; validators.pop(); } // avoid underflow - if(j==0){ + if (j == 0) { break; } } // swap element in array - if (findLeft && findRight){ + if (findLeft && findRight) { delete indicators[validators[i]]; validators[i] = validators[j]; validators.pop(); } // avoid underflow - if(j==0){ + if (j == 0) { break; } // move to next @@ -161,30 +183,117 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit indicatorCleaned(); } + function submitFinalityViolationEvidence(FinalityEvidence calldata _evidence) external onlyInit onlyRelayer { + if (finalityDistance == 0 || finalitySlashRewardRatio == 0) { + finalityDistance = FINALITY_DISTANCE; + finalitySlashRewardRatio = FINALITY_SLASH_REWARD_RATIO; + } + + require( + (_evidence.numA < _evidence.numB && _evidence.numA + finalityDistance >= _evidence.numB) || + (_evidence.numB < _evidence.numA && _evidence.numB + finalityDistance >= _evidence.numA), + "too long distance between blocks" + ); + require( + _evidence.numA < block.number && _evidence.numA + 256 > block.number && + _evidence.numB < block.number && _evidence.numB + 256 > block.number, + "block number out of range" + ); + + bytes32 _headerA = blockhash(_evidence.numA); + bytes32 _headerB = blockhash(_evidence.numB); + if (_headerA != _evidence.headerA && _headerB != _evidence.headerB) { + revert(string(abi.encodePacked("neither header is in local fork"))); + } else if (_headerA == _evidence.headerA && _headerB == _evidence.headerB) { + revert(string(abi.encodePacked("both headers are in local fork"))); + } + + // BLS verification + (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); + bytes memory voteAddress; + bool exist; + for (uint i = 0; i < vals.length; i++) { + if (vals[i] == _evidence.valAddr) { + exist = true; + voteAddress = voteAddrs[i]; + break; + } + } + require(exist, "validator not exist"); + + bytes memory input; + bytes memory output; + + // to avoid too deep stack + { + bytes memory bytesNumA; + bytes memory bytesNumB; + bytes memory bytesHeaderA; + bytes memory bytesHeaderB; + TypesToBytes.uintToBytes(32, _evidence.numA, bytesNumA); + TypesToBytes.bytes32ToBytes(32, _evidence.headerA, bytesHeaderA); + TypesToBytes.uintToBytes(32, _evidence.numB, bytesNumB); + TypesToBytes.bytes32ToBytes(32, _evidence.headerB, bytesHeaderB); + + input = BytesLib.concat(bytesNumA, bytesHeaderA); + input = BytesLib.concat(input, _evidence.sigA); + input = BytesLib.concat(input, bytesNumB); + input = BytesLib.concat(input, bytesHeaderB); + input = BytesLib.concat(input, _evidence.sigB); + input = BytesLib.concat(input, voteAddress); + } + + // call the precompiled contract to verify the BLS signature + // the precompiled contract's address is 0x64 + assembly { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { + revert(0, 0) + } + } + + uint256 amount = (address(SYSTEM_REWARD_ADDR).balance * finalitySlashRewardRatio) / 100; + ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, amount); + IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); + emit validatorSlashed(_evidence.valAddr); + + } + function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ - if (Memory.compareStrings(key,"misdemeanorThreshold")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { + if (Memory.compareStrings(key, "misdemeanorThreshold")) { require(value.length == 32, "length of misdemeanorThreshold mismatch"); uint256 newMisdemeanorThreshold = BytesToTypes.bytesToUint256(32, value); require(newMisdemeanorThreshold >= 1 && newMisdemeanorThreshold < felonyThreshold, "the misdemeanorThreshold out of range"); misdemeanorThreshold = newMisdemeanorThreshold; - } else if (Memory.compareStrings(key,"felonyThreshold")) { + } else if (Memory.compareStrings(key, "felonyThreshold")) { require(value.length == 32, "length of felonyThreshold mismatch"); uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); felonyThreshold = newFelonyThreshold; + } else if (Memory.compareStrings(key, "finalityDistance")) { + require(value.length == 32, "length of finalityDistance mismatch"); + uint256 newFinalityDistance = BytesToTypes.bytesToUint256(32, value); + require(newFinalityDistance >= 1 && newFinalityDistance <= 21, "the finality distance out of range"); + finalityDistance = newFinalityDistance; + } else if (Memory.compareStrings(key, "finalitySlashRewardRatio")) { + require(value.length == 32, "length of finalitySlashRewardRatio mismatch"); + uint256 newFinalitySlashRewardRatio = BytesToTypes.bytesToUint256(32, value); + require(newFinalitySlashRewardRatio >= 10 && newFinalitySlashRewardRatio < 100, "the finality slash reward ratio out of range"); + finalitySlashRewardRatio = newFinalitySlashRewardRatio; } else { require(false, "unknown param"); } - emit paramChange(key,value); + emit paramChange(key, value); } /*********************** query api ********************************/ - function getSlashIndicator(address validator) external view returns (uint256,uint256) { + function getSlashIndicator(address validator) external view returns (uint256, uint256) { Indicator memory indicator = indicators[validator]; return (indicator.height, indicator.count); } @@ -198,7 +307,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication return elements.encodeList(); } - function getSlashThresholds() override(ISlashIndicator) external view returns (uint256, uint256) { + function getSlashThresholds() external view override(ISlashIndicator) returns (uint256, uint256) { return (misdemeanorThreshold, felonyThreshold); } } diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index 41bed361..f76cde2d 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -1,16 +1,21 @@ pragma solidity 0.6.4; +pragma experimental ABIEncoderV2; + import "./System.sol"; import "./lib/BytesToTypes.sol"; +import "./lib/BytesLib.sol"; +import "./lib/TypesToBytes.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; import "./interface/IApplication.sol"; import "./interface/IBSCValidatorSet.sol"; import "./interface/IParamSubscriber.sol"; import "./interface/ICrossChain.sol"; +import "./interface/ISystemReward.sol"; import "./lib/CmnPkg.sol"; import "./lib/RLPEncode.sol"; -contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication{ +contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplication { using RLPEncode for *; uint256 public constant MISDEMEANOR_THRESHOLD = 50; @@ -28,6 +33,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication uint256 public misdemeanorThreshold; uint256 public felonyThreshold; + // BEP-126 Fast Finality + uint256 public constant FINALITY_DISTANCE = 11; + uint256 public constant FINALITY_SLASH_REWARD_RATIO = 20; + + uint256 public finalityDistance; + uint256 public finalitySlashRewardRatio; + event validatorSlashed(address indexed validator); event indicatorCleaned(); event paramChange(string key, bytes value); @@ -42,6 +54,17 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bool exist; } + // Proof that a validator misbehaved in fast finality + struct FinalityEvidence { + uint256 numA; + bytes32 headerA; + bytes sigA; + uint256 numB; + bytes32 headerB; + bytes sigB; + address valAddr; + } + modifier oncePerBlock() { require(block.number > previousHeight, "can not slash twice in one block"); _; @@ -52,22 +75,23 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication {% if mock %} require(true, "gasprice is not zero"); {% else %} - require(tx.gasprice == 0 , "gasprice is not zero"); + require(tx.gasprice == 0, "gasprice is not zero"); {% endif %} _; } - {% if mock %} +{% if mock %} function getSlashValidators() external view returns (address[] memory) { return validators; - }{% endif %} - function init() external onlyNotInit{ + } +{% endif %} + function init() external onlyNotInit { misdemeanorThreshold = MISDEMEANOR_THRESHOLD; felonyThreshold = FELONY_THRESHOLD; alreadyInit = true; } /*********************** Implement cross chain app ********************************/ - function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns(bytes memory) { + function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns (bytes memory) { require(false, "receive unexpected syn package"); } @@ -87,7 +111,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } /*********************** External func ********************************/ - function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ + function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice { if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { return; } @@ -111,52 +135,51 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit validatorSlashed(validator); } - // To prevent validator misbehaving and leaving, do not clean slash record to zero, but decrease by felonyThreshold/DECREASE_RATE . // Clean is an effective implement to reorganize "validators" and "indicators". - function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit{ - if(validators.length == 0){ + function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit { + if (validators.length == 0) { return; } uint i = 0; - uint j = validators.length-1; - for (;i <= j;) { + uint j = validators.length - 1; + for (; i <= j;) { bool findLeft = false; bool findRight = false; - for(;i felonyThreshold/DECREASE_RATE){ - leftIndicator.count = leftIndicator.count - felonyThreshold/DECREASE_RATE; + if (leftIndicator.count > felonyThreshold / DECREASE_RATE) { + leftIndicator.count = leftIndicator.count - felonyThreshold / DECREASE_RATE; indicators[validators[i]] = leftIndicator; - }else{ + } else { findLeft = true; break; } } - for(;i<=j;j--){ + for (; i <= j; j--) { Indicator memory rightIndicator = indicators[validators[j]]; - if(rightIndicator.count > felonyThreshold/DECREASE_RATE){ - rightIndicator.count = rightIndicator.count - felonyThreshold/DECREASE_RATE; + if (rightIndicator.count > felonyThreshold / DECREASE_RATE) { + rightIndicator.count = rightIndicator.count - felonyThreshold / DECREASE_RATE; indicators[validators[j]] = rightIndicator; findRight = true; break; - }else{ + } else { delete indicators[validators[j]]; validators.pop(); } // avoid underflow - if(j==0){ + if (j == 0) { break; } } // swap element in array - if (findLeft && findRight){ + if (findLeft && findRight) { delete indicators[validators[i]]; validators[i] = validators[j]; validators.pop(); } // avoid underflow - if(j==0){ + if (j == 0) { break; } // move to next @@ -166,30 +189,117 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit indicatorCleaned(); } + function submitFinalityViolationEvidence(FinalityEvidence calldata _evidence) external onlyInit onlyRelayer { + if (finalityDistance == 0 || finalitySlashRewardRatio == 0) { + finalityDistance = FINALITY_DISTANCE; + finalitySlashRewardRatio = FINALITY_SLASH_REWARD_RATIO; + } + + require( + (_evidence.numA < _evidence.numB && _evidence.numA + finalityDistance >= _evidence.numB) || + (_evidence.numB < _evidence.numA && _evidence.numB + finalityDistance >= _evidence.numA), + "too long distance between blocks" + ); + require( + _evidence.numA < block.number && _evidence.numA + 256 > block.number && + _evidence.numB < block.number && _evidence.numB + 256 > block.number, + "block number out of range" + ); + + bytes32 _headerA = blockhash(_evidence.numA); + bytes32 _headerB = blockhash(_evidence.numB); + if (_headerA != _evidence.headerA && _headerB != _evidence.headerB) { + revert(string(abi.encodePacked("neither header is in local fork"))); + } else if (_headerA == _evidence.headerA && _headerB == _evidence.headerB) { + revert(string(abi.encodePacked("both headers are in local fork"))); + } + + // BLS verification + (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); + bytes memory voteAddress; + bool exist; + for (uint i = 0; i < vals.length; i++) { + if (vals[i] == _evidence.valAddr) { + exist = true; + voteAddress = voteAddrs[i]; + break; + } + } + require(exist, "validator not exist"); +{% if mock %}{% else %} + bytes memory input; + bytes memory output; + + // to avoid too deep stack + { + bytes memory bytesNumA; + bytes memory bytesNumB; + bytes memory bytesHeaderA; + bytes memory bytesHeaderB; + TypesToBytes.uintToBytes(32, _evidence.numA, bytesNumA); + TypesToBytes.bytes32ToBytes(32, _evidence.headerA, bytesHeaderA); + TypesToBytes.uintToBytes(32, _evidence.numB, bytesNumB); + TypesToBytes.bytes32ToBytes(32, _evidence.headerB, bytesHeaderB); + + input = BytesLib.concat(bytesNumA, bytesHeaderA); + input = BytesLib.concat(input, _evidence.sigA); + input = BytesLib.concat(input, bytesNumB); + input = BytesLib.concat(input, bytesHeaderB); + input = BytesLib.concat(input, _evidence.sigB); + input = BytesLib.concat(input, voteAddress); + } + + // call the precompiled contract to verify the BLS signature + // the precompiled contract's address is 0x64 + assembly { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { + revert(0, 0) + } + } +{% endif %} + uint256 amount = (address(SYSTEM_REWARD_ADDR).balance * finalitySlashRewardRatio) / 100; + ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, amount); + IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); + emit validatorSlashed(_evidence.valAddr); + + } + function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ - if (Memory.compareStrings(key,"misdemeanorThreshold")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { + if (Memory.compareStrings(key, "misdemeanorThreshold")) { require(value.length == 32, "length of misdemeanorThreshold mismatch"); uint256 newMisdemeanorThreshold = BytesToTypes.bytesToUint256(32, value); require(newMisdemeanorThreshold >= 1 && newMisdemeanorThreshold < felonyThreshold, "the misdemeanorThreshold out of range"); misdemeanorThreshold = newMisdemeanorThreshold; - } else if (Memory.compareStrings(key,"felonyThreshold")) { + } else if (Memory.compareStrings(key, "felonyThreshold")) { require(value.length == 32, "length of felonyThreshold mismatch"); uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); felonyThreshold = newFelonyThreshold; + } else if (Memory.compareStrings(key, "finalityDistance")) { + require(value.length == 32, "length of finalityDistance mismatch"); + uint256 newFinalityDistance = BytesToTypes.bytesToUint256(32, value); + require(newFinalityDistance >= 1 && newFinalityDistance <= 21, "the finality distance out of range"); + finalityDistance = newFinalityDistance; + } else if (Memory.compareStrings(key, "finalitySlashRewardRatio")) { + require(value.length == 32, "length of finalitySlashRewardRatio mismatch"); + uint256 newFinalitySlashRewardRatio = BytesToTypes.bytesToUint256(32, value); + require(newFinalitySlashRewardRatio >= 10 && newFinalitySlashRewardRatio < 100, "the finality slash reward ratio out of range"); + finalitySlashRewardRatio = newFinalitySlashRewardRatio; } else { require(false, "unknown param"); } - emit paramChange(key,value); + emit paramChange(key, value); } /*********************** query api ********************************/ - function getSlashIndicator(address validator) external view returns (uint256,uint256) { + function getSlashIndicator(address validator) external view returns (uint256, uint256) { Indicator memory indicator = indicators[validator]; return (indicator.height, indicator.count); } @@ -203,7 +313,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication return elements.encodeList(); } - function getSlashThresholds() override(ISlashIndicator) external view returns (uint256, uint256) { + function getSlashThresholds() external view override(ISlashIndicator) returns (uint256, uint256) { return (misdemeanorThreshold, felonyThreshold); } } diff --git a/contracts/System.sol b/contracts/System.sol index 7d64ddc2..951910ff 100644 --- a/contracts/System.sol +++ b/contracts/System.sol @@ -24,7 +24,7 @@ contract System { address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002; address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003; address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004; - address public constant INCENTIVIZE_ADDR=0x0000000000000000000000000000000000001005; + address public constant INCENTIVIZE_ADDR = 0x0000000000000000000000000000000000001005; address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006; address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; diff --git a/contracts/System.template b/contracts/System.template index 4ceba2da..cec65ee3 100644 --- a/contracts/System.template +++ b/contracts/System.template @@ -19,11 +19,11 @@ contract System { uint8 constant public SLASH_CHANNELID = 0x0b; uint16 constant public bscChainID = 0x{{bscChainId}}; {% if mock %} - address public VALIDATOR_CONTRACT_ADDR; - address public SLASH_CONTRACT_ADDR; - address public SYSTEM_REWARD_ADDR; - address public LIGHT_CLIENT_ADDR; - address public TOKEN_HUB_ADDR; + address public VALIDATOR_CONTRACT_ADDR; + address public SLASH_CONTRACT_ADDR; + address public SYSTEM_REWARD_ADDR; + address public LIGHT_CLIENT_ADDR; + address public TOKEN_HUB_ADDR; address public INCENTIVIZE_ADDR; address public RELAYERHUB_CONTRACT_ADDR; address public GOV_HUB_ADDR; @@ -48,7 +48,7 @@ contract System { address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002; address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003; address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004; - address public constant INCENTIVIZE_ADDR=0x0000000000000000000000000000000000001005; + address public constant INCENTIVIZE_ADDR = 0x0000000000000000000000000000000000001005; address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006; address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; diff --git a/contracts/SystemReward.sol b/contracts/SystemReward.sol index ffaa2a60..ed0c8df7 100644 --- a/contracts/SystemReward.sol +++ b/contracts/SystemReward.sol @@ -1,8 +1,11 @@ pragma solidity 0.6.4; + import "./System.sol"; +import "./lib/Memory.sol"; +import "./interface/IParamSubscriber.sol"; import "./interface/ISystemReward.sol"; -contract SystemReward is System, ISystemReward{ +contract SystemReward is System, IParamSubscriber, ISystemReward { uint256 public constant MAX_REWARDS = 1e18; uint public numOperator; @@ -19,30 +22,29 @@ contract SystemReward is System, ISystemReward{ _; } - - modifier onlyOperator() { - require(operators[msg.sender],"only operator is allowed to call the method"); - _; - } - event rewardTo(address indexed to, uint256 amount); event rewardEmpty(); event receiveDeposit(address indexed from, uint256 amount); + event updateOperator(address indexed operator); + event paramChange(string key, bytes value); - receive() external payable{ - if (msg.value>0) { + receive() external payable { + if (msg.value > 0) { emit receiveDeposit(msg.sender, msg.value); } } - - function claimRewards(address payable to, uint256 amount) external override(ISystemReward) doInit onlyOperator returns(uint256) { + function claimRewards(address payable to, uint256 amount) external override(ISystemReward) doInit returns (uint256) { + if (!operators[msg.sender]) { + return 0; + } + uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount>0) { + if (actualAmount > 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { @@ -54,4 +56,20 @@ contract SystemReward is System, ISystemReward{ function isOperator(address addr) external view returns (bool) { return operators[addr]; } -} \ No newline at end of file + + function updateParam(string calldata key, bytes calldata value) onlyGov external override { + if (Memory.compareStrings(key, "updateOperator")) { + bytes memory valueLocal = value; + require(valueLocal.length == 20, "length of value for updateOperator should be 20"); + address operatorAddr; + assembly { + operatorAddr := mload(add(valueLocal, 20)) + } + operators[operatorAddr] = true; + emit updateOperator(operatorAddr); + } else { + require(false, "unknown param"); + } + emit paramChange(key, value); + } +} diff --git a/contracts/SystemReward.template b/contracts/SystemReward.template index 8784188e..7c846bf4 100644 --- a/contracts/SystemReward.template +++ b/contracts/SystemReward.template @@ -1,8 +1,11 @@ pragma solidity 0.6.4; + import "./System.sol"; +import "./lib/Memory.sol"; +import "./interface/IParamSubscriber.sol"; import "./interface/ISystemReward.sol"; -contract SystemReward is System, ISystemReward{ +contract SystemReward is System, IParamSubscriber, ISystemReward { uint256 public constant MAX_REWARDS = 1e18; uint public numOperator; @@ -18,28 +21,23 @@ contract SystemReward is System, ISystemReward{ } _; } - - - modifier onlyOperator() { - require(operators[msg.sender],"only operator is allowed to call the method"); - _; - } - {% if mock %} +{% if mock %} event newOperator(address indexed operator); event deleteOperator(address indexed operator); - {% endif %} +{% endif %} event rewardTo(address indexed to, uint256 amount); event rewardEmpty(); event receiveDeposit(address indexed from, uint256 amount); + event updateOperator(address indexed operator); + event paramChange(string key, bytes value); - receive() external payable{ - if (msg.value>0) { + receive() external payable { + if (msg.value > 0) { emit receiveDeposit(msg.sender, msg.value); } } - - {% if mock %} +{% if mock %} modifier onlyOperatorExist(address _operator) { require(operators[_operator], "the operator do not exist"); _; @@ -61,13 +59,17 @@ contract SystemReward is System, ISystemReward{ numOperator --; emit deleteOperator(operator); } - {% endif %} - function claimRewards(address payable to, uint256 amount) external override(ISystemReward) doInit onlyOperator returns(uint256) { +{% endif %} + function claimRewards(address payable to, uint256 amount) external override(ISystemReward) doInit returns (uint256) { + if (!operators[msg.sender]) { + return 0; + } + uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount>0) { + if (actualAmount > 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { @@ -79,4 +81,20 @@ contract SystemReward is System, ISystemReward{ function isOperator(address addr) external view returns (bool) { return operators[addr]; } -} \ No newline at end of file + + function updateParam(string calldata key, bytes calldata value) onlyGov external override { + if (Memory.compareStrings(key, "updateOperator")) { + bytes memory valueLocal = value; + require(valueLocal.length == 20, "length of value for updateOperator should be 20"); + address operatorAddr; + assembly { + operatorAddr := mload(add(valueLocal, 20)) + } + operators[operatorAddr] = true; + emit updateOperator(operatorAddr); + } else { + require(false, "unknown param"); + } + emit paramChange(key, value); + } +} diff --git a/contracts/TendermintLightClient.sol b/contracts/TendermintLightClient.sol index 418dbe32..537925ed 100644 --- a/contracts/TendermintLightClient.sol +++ b/contracts/TendermintLightClient.sol @@ -7,13 +7,13 @@ import "./interface/ISystemReward.sol"; import "./interface/IParamSubscriber.sol"; import "./System.sol"; -contract TendermintLightClient is ILightClient, System, IParamSubscriber{ +contract TendermintLightClient is ILightClient, System, IParamSubscriber { struct ConsensusState { - uint64 preValidatorSetChangeHeight; + uint64 preValidatorSetChangeHeight; bytes32 appHash; bytes32 curValidatorSetHash; - bytes nextValidatorSet; + bytes nextValidatorSet; } mapping(uint64 => ConsensusState) public lightClientConsensusStates; @@ -23,7 +23,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ bytes32 public chainID; bytes constant public INIT_CONSENSUS_STATE_BYTES = hex"42696e616e63652d436861696e2d4e696c650000000000000000000000000000000000000000000229eca254b3859bffefaf85f4c95da9fbd26527766b784272789c30ec56b380b6eb96442aaab207bc59978ba3dd477690f5c5872334fc39e627723daa97e441e88ba4515150ec3182bc82593df36f8abb25a619187fcfab7e552b94e64ed2deed000000e8d4a51000"; - uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = 1e16; + uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = 1e16; uint256 public rewardForValidatorSetChange; event initConsensusState(uint64 initHeight, bytes32 appHash); @@ -75,17 +75,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ //32 + 32 + 8 + 32 + 32 + cs.nextValidatorSet.length; uint256 length = 136 + cs.nextValidatorSet.length; - bytes memory input = new bytes(length+header.length); + bytes memory input = new bytes(length + header.length); uint256 ptr = Memory.dataPtr(input); require(encodeConsensusState(cs, preValidatorSetChangeHeight, ptr, length), "failed to serialize consensus state"); // write header to input uint256 src; - ptr = ptr+length; + ptr = ptr + length; (src, length) = Memory.fromBytes(header); Memory.copy(src, ptr, length); - length = input.length+32; + length = input.length + 32; // Maximum validator quantity is 99 bytes32[128] memory result; /* solium-disable-next-line */ @@ -103,11 +103,11 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ length := mload(add(result, 0)) } bool validatorChanged = false; - if ((length&(0x01<<248))!=0x00) { + if ((length & (0x01 << 248)) != 0x00) { validatorChanged = true; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, rewardForValidatorSetChange); } - length = length&0xffffffffffffffff; + length = length & 0xffffffffffffffff; /* solium-disable-next-line */ assembly { @@ -145,7 +145,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ function getChainID() external view returns (string memory) { bytes memory chainIDBytes = new bytes(32); assembly { - mstore(add(chainIDBytes,32), sload(chainID_slot)) + mstore(add(chainIDBytes, 32), sload(chainID_slot)) } uint8 chainIDLength = 0; @@ -175,36 +175,36 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ uint256 length; (src, length) = Memory.fromBytes(cs.nextValidatorSet); Memory.copy(src, outputPtr, length); - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; bytes32 hash = cs.curValidatorSetHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; hash = cs.appHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; /* solium-disable-next-line */ assembly { mstore(outputPtr, height) } - outputPtr = outputPtr-8; + outputPtr = outputPtr - 8; /* solium-disable-next-line */ assembly { mstore(outputPtr, sload(chainID_slot)) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; // size doesn't contain length - size = size-32; + size = size - 32; /* solium-disable-next-line */ assembly { mstore(outputPtr, size) @@ -216,22 +216,22 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ // | chainID | height | appHash | curValidatorSetHash | [{validator pubkey, voting power}] | // | 32 bytes | 8 bytes | 32 bytes | 32 bytes | [{32 bytes, 8 bytes}] | /* solium-disable-next-line */ - function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns(ConsensusState memory, uint64) { - ptr = ptr+8; + function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns (ConsensusState memory, uint64) { + ptr = ptr + 8; uint64 height; /* solium-disable-next-line */ assembly { height := mload(ptr) } - ptr = ptr+32; + ptr = ptr + 32; bytes32 appHash; /* solium-disable-next-line */ assembly { appHash := mload(ptr) } - ptr = ptr+32; + ptr = ptr + 32; bytes32 curValidatorSetHash; /* solium-disable-next-line */ assembly { @@ -245,17 +245,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ if (!leaveOutValidatorSet) { uint256 dest; uint256 length; - cs.nextValidatorSet = new bytes(size-104); - (dest,length) = Memory.fromBytes(cs.nextValidatorSet); + cs.nextValidatorSet = new bytes(size - 104); + (dest, length) = Memory.fromBytes(cs.nextValidatorSet); - Memory.copy(ptr+32, dest, length); + Memory.copy(ptr + 32, dest, length); } return (cs, height); } - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ - if (Memory.compareStrings(key,"rewardForValidatorSetChange")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { + if (Memory.compareStrings(key, "rewardForValidatorSetChange")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newRewardForValidatorSetChange = BytesToTypes.bytesToUint256(32, value); require(newRewardForValidatorSetChange > 0 && newRewardForValidatorSetChange <= 1e18, "the newRewardForValidatorSetChange out of range"); @@ -265,4 +265,4 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ } emit paramChange(key, value); } -} \ No newline at end of file +} diff --git a/contracts/TendermintLightClient.template b/contracts/TendermintLightClient.template index 13511ed7..7976a617 100644 --- a/contracts/TendermintLightClient.template +++ b/contracts/TendermintLightClient.template @@ -7,13 +7,13 @@ import "./interface/ISystemReward.sol"; import "./interface/IParamSubscriber.sol"; import "./System.sol"; -contract TendermintLightClient is ILightClient, System, IParamSubscriber{ +contract TendermintLightClient is ILightClient, System, IParamSubscriber { struct ConsensusState { - uint64 preValidatorSetChangeHeight; + uint64 preValidatorSetChangeHeight; bytes32 appHash; bytes32 curValidatorSetHash; - bytes nextValidatorSet; + bytes nextValidatorSet; } mapping(uint64 => ConsensusState) public lightClientConsensusStates; @@ -23,7 +23,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ bytes32 public chainID; bytes constant public INIT_CONSENSUS_STATE_BYTES = hex"{{initConsensusStateBytes}}"; - uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = {{rewardForValidatorSetChange}}; + uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = {{rewardForValidatorSetChange}}; uint256 public rewardForValidatorSetChange; event initConsensusState(uint64 initHeight, bytes32 appHash); @@ -75,17 +75,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ //32 + 32 + 8 + 32 + 32 + cs.nextValidatorSet.length; uint256 length = 136 + cs.nextValidatorSet.length; - bytes memory input = new bytes(length+header.length); + bytes memory input = new bytes(length + header.length); uint256 ptr = Memory.dataPtr(input); require(encodeConsensusState(cs, preValidatorSetChangeHeight, ptr, length), "failed to serialize consensus state"); // write header to input uint256 src; - ptr = ptr+length; + ptr = ptr + length; (src, length) = Memory.fromBytes(header); Memory.copy(src, ptr, length); - length = input.length+32; + length = input.length + 32; // Maximum validator quantity is 99 bytes32[128] memory result; /* solium-disable-next-line */ @@ -103,11 +103,11 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ length := mload(add(result, 0)) } bool validatorChanged = false; - if ((length&(0x01<<248))!=0x00) { + if ((length & (0x01 << 248)) != 0x00) { validatorChanged = true; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, rewardForValidatorSetChange); } - length = length&0xffffffffffffffff; + length = length & 0xffffffffffffffff; /* solium-disable-next-line */ assembly { @@ -145,7 +145,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ function getChainID() external view returns (string memory) { bytes memory chainIDBytes = new bytes(32); assembly { - mstore(add(chainIDBytes,32), sload(chainID_slot)) + mstore(add(chainIDBytes, 32), sload(chainID_slot)) } uint8 chainIDLength = 0; @@ -175,36 +175,36 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ uint256 length; (src, length) = Memory.fromBytes(cs.nextValidatorSet); Memory.copy(src, outputPtr, length); - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; bytes32 hash = cs.curValidatorSetHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; hash = cs.appHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; /* solium-disable-next-line */ assembly { mstore(outputPtr, height) } - outputPtr = outputPtr-8; + outputPtr = outputPtr - 8; /* solium-disable-next-line */ assembly { mstore(outputPtr, sload(chainID_slot)) } - outputPtr = outputPtr-32; + outputPtr = outputPtr - 32; // size doesn't contain length - size = size-32; + size = size - 32; /* solium-disable-next-line */ assembly { mstore(outputPtr, size) @@ -216,22 +216,22 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ // | chainID | height | appHash | curValidatorSetHash | [{validator pubkey, voting power}] | // | 32 bytes | 8 bytes | 32 bytes | 32 bytes | [{32 bytes, 8 bytes}] | /* solium-disable-next-line */ - function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns(ConsensusState memory, uint64) { - ptr = ptr+8; + function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns (ConsensusState memory, uint64) { + ptr = ptr + 8; uint64 height; /* solium-disable-next-line */ assembly { height := mload(ptr) } - ptr = ptr+32; + ptr = ptr + 32; bytes32 appHash; /* solium-disable-next-line */ assembly { appHash := mload(ptr) } - ptr = ptr+32; + ptr = ptr + 32; bytes32 curValidatorSetHash; /* solium-disable-next-line */ assembly { @@ -245,17 +245,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ if (!leaveOutValidatorSet) { uint256 dest; uint256 length; - cs.nextValidatorSet = new bytes(size-104); - (dest,length) = Memory.fromBytes(cs.nextValidatorSet); + cs.nextValidatorSet = new bytes(size - 104); + (dest, length) = Memory.fromBytes(cs.nextValidatorSet); - Memory.copy(ptr+32, dest, length); + Memory.copy(ptr + 32, dest, length); } return (cs, height); } - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ - if (Memory.compareStrings(key,"rewardForValidatorSetChange")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { + if (Memory.compareStrings(key, "rewardForValidatorSetChange")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newRewardForValidatorSetChange = BytesToTypes.bytesToUint256(32, value); require(newRewardForValidatorSetChange > 0 && newRewardForValidatorSetChange <= 1e18, "the newRewardForValidatorSetChange out of range"); @@ -265,4 +265,4 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber{ } emit paramChange(key, value); } -} \ No newline at end of file +} diff --git a/contracts/TokenHub.sol b/contracts/TokenHub.sol index 72a93e76..849e7889 100644 --- a/contracts/TokenHub.sol +++ b/contracts/TokenHub.sol @@ -28,7 +28,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256[] amounts; address[] recipients; address[] refundAddrs; - uint64 expireTime; + uint64 expireTime; } // BC to BSC @@ -46,7 +46,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256 amount; address recipient; address refundAddr; - uint64 expireTime; + uint64 expireTime; } // BSC to BC @@ -70,11 +70,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 constant public MAXIMUM_BEP20_SYMBOL_LEN = 8; uint8 constant public BEP2_TOKEN_DECIMALS = 8; bytes32 constant public BEP2_TOKEN_SYMBOL_FOR_BNB = 0x424E420000000000000000000000000000000000000000000000000000000000; // "BNB" - uint256 constant public MAX_GAS_FOR_CALLING_BEP20=50000; - uint256 constant public MAX_GAS_FOR_TRANSFER_BNB=10000; + uint256 constant public MAX_GAS_FOR_CALLING_BEP20 = 50000; + uint256 constant public MAX_GAS_FOR_TRANSFER_BNB = 10000; - uint256 constant public INIT_MINIMUM_RELAY_FEE =2e15; - uint256 constant public REWARD_UPPER_LIMIT =1e18; + uint256 constant public INIT_MINIMUM_RELAY_FEE = 2e15; + uint256 constant public REWARD_UPPER_LIMIT = 1e18; uint256 constant public TEN_DECIMALS = 1e10; uint256 public relayFee; @@ -97,32 +97,32 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function init() onlyNotInit external { relayFee = INIT_MINIMUM_RELAY_FEE; bep20ContractDecimals[address(0x0)] = 18; // BNB decimals is 18 - alreadyInit=true; + alreadyInit = true; } - receive() external payable{ - if (msg.value>0) { + receive() external payable { + if (msg.value > 0) { emit receiveDeposit(msg.sender, msg.value); } } - function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns(uint256) { + function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns (uint256) { uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > REWARD_UPPER_LIMIT) { return 0; } - if (actualAmount>0) { + if (actualAmount > 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } return actualAmount; } - function getMiniRelayFee() external view override returns(uint256) { + function getMiniRelayFee() external view override returns (uint256) { return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory) { + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns (bytes memory) { if (channelId == TRANSFER_IN_CHANNELID) { return handleTransferInSynPackage(msgBytes); } else { @@ -153,15 +153,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx=0; + uint256 idx = 0; while (iter.hasNext()) { - if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); - else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); - else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); - else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); - else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); + if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); + else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); + else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); + else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); + else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); else if (idx == 5) { - transInSynPkg.expireTime = uint64(iter.next().toUint()); + transInSynPkg.expireTime = uint64(iter.next().toUint()); success = true; } else break; @@ -179,17 +179,17 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return elements.encodeList(); } - function handleTransferInSynPackage(bytes memory msgBytes) internal returns(bytes memory) { + function handleTransferInSynPackage(bytes memory msgBytes) internal returns (bytes memory) { (TransferInSynPackage memory transInSynPkg, bool success) = decodeTransferInSynPackage(msgBytes); require(success, "unrecognized transferIn package"); uint32 resCode = doTransferIn(transInSynPkg); if (resCode != TRANSFER_IN_SUCCESS) { uint256 bep2Amount = convertToBep2Amount(transInSynPkg.amount, bep20ContractDecimals[transInSynPkg.contractAddr]); TransferInRefundPackage memory transInAckPkg = TransferInRefundPackage({ - bep2TokenSymbol: transInSynPkg.bep2TokenSymbol, - refundAmount: bep2Amount, - refundAddr: transInSynPkg.refundAddr, - status: resCode + bep2TokenSymbol : transInSynPkg.bep2TokenSymbol, + refundAmount : bep2Amount, + refundAddr : transInSynPkg.refundAddr, + status : resCode }); return encodeTransferInRefundPackage(transInAckPkg); } else { @@ -198,14 +198,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function doTransferIn(TransferInSynPackage memory transInSynPkg) internal returns (uint32) { - if (transInSynPkg.contractAddr==address(0x0)) { + if (transInSynPkg.contractAddr == address(0x0)) { if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } if (address(this).balance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - (bool success, ) = transInSynPkg.recipient.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: transInSynPkg.amount}(""); + (bool success,) = transInSynPkg.recipient.call{gas : MAX_GAS_FOR_TRANSFER_BNB, value : transInSynPkg.amount}(""); if (!success) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } @@ -215,14 +215,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } - if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr]!= transInSynPkg.bep2TokenSymbol) { + if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr] != transInSynPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP20}(address(this)); + uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas : MAX_GAS_FOR_CALLING_BEP20}(address(this)); if (actualBalance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); + bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas : MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); if (success) { emit transferInSuccess(transInSynPkg.contractAddr, transInSynPkg.recipient, transInSynPkg.amount); return TRANSFER_IN_SUCCESS; @@ -232,38 +232,38 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } } - function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns(TransferOutAckPackage memory, bool) { + function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns (TransferOutAckPackage memory, bool) { TransferOutAckPackage memory transOutAckPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx=0; + uint256 idx = 0; while (iter.hasNext()) { - if (idx == 0) { - transOutAckPkg.contractAddr = iter.next().toAddress(); - } - else if (idx == 1) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAmounts = new uint256[](list.length); - for (uint256 index=0; index=block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); bytes32 bep2TokenSymbol; uint256 convertedAmount; uint256 rewardForRelayer; - if (contractAddr==address(0x0)) { - require(msg.value>=amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); - require(amount%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); - rewardForRelayer=msg.value.sub(amount); + if (contractAddr == address(0x0)) { + require(msg.value >= amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); + require(amount % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); + rewardForRelayer = msg.value.sub(amount); convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 - bep2TokenSymbol=BEP2_TOKEN_SYMBOL_FOR_BNB; + bep2TokenSymbol = BEP2_TOKEN_SYMBOL_FOR_BNB; } else { bep2TokenSymbol = contractAddrToBEP2Symbol[contractAddr]; - require(bep2TokenSymbol!=bytes32(0x00), "the contract has not been bound to any bep2 token"); - require(msg.value>=relayFee, "received BNB amount should be no less than the minimum relayFee"); - rewardForRelayer=msg.value; - uint256 bep20TokenDecimals=bep20ContractDecimals[contractAddr]; - require(bep20TokenDecimals<=BEP2_TOKEN_DECIMALS || (bep20TokenDecimals>BEP2_TOKEN_DECIMALS && amount.mod(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS))==0), "invalid transfer amount: precision loss in amount conversion"); - convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals);// convert to bep2 amount + require(bep2TokenSymbol != bytes32(0x00), "the contract has not been bound to any bep2 token"); + require(msg.value >= relayFee, "received BNB amount should be no less than the minimum relayFee"); + rewardForRelayer = msg.value; + uint256 bep20TokenDecimals = bep20ContractDecimals[contractAddr]; + require(bep20TokenDecimals <= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals > BEP2_TOKEN_DECIMALS && amount.mod(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)) == 0), "invalid transfer amount: precision loss in amount conversion"); + convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals); // convert to bep2 amount if (isMiniBEP2Token(bep2TokenSymbol)) { - require(convertedAmount >= 1e8 , "For miniToken, the transfer amount must not be less than 1"); + require(convertedAmount >= 1e8, "For miniToken, the transfer amount must not be less than 1"); } - require(bep20TokenDecimals>=BEP2_TOKEN_DECIMALS || (bep20TokenDecimalsamount), "amount is too large, uint256 overflow"); - require(convertedAmount<=MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); + require(bep20TokenDecimals >= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals < BEP2_TOKEN_DECIMALS && convertedAmount > amount), "amount is too large, uint256 overflow"); + require(convertedAmount <= MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); require(IBEP20(contractAddr).transferFrom(msg.sender, address(this), amount)); } TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol: bep2TokenSymbol, - contractAddr: contractAddr, - amounts: new uint256[](1), - recipients: new address[](1), - refundAddrs: new address[](1), - expireTime: expireTime + bep2TokenSymbol : bep2TokenSymbol, + contractAddr : contractAddr, + amounts : new uint256[](1), + recipients : new address[](1), + refundAddrs : new address[](1), + expireTime : expireTime }); - transOutSynPkg.amounts[0]=convertedAmount; - transOutSynPkg.recipients[0]=recipient; - transOutSynPkg.refundAddrs[0]=msg.sender; + transOutSynPkg.amounts[0] = convertedAmount; + transOutSynPkg.recipients[0] = recipient; + transOutSynPkg.refundAddrs[0] = msg.sender; ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(contractAddr, msg.sender, amount, rewardForRelayer); return true; @@ -427,34 +427,34 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external override onlyInit payable returns (bool) { require(recipientAddrs.length == amounts.length, "Length of recipientAddrs doesn't equal to length of amounts"); require(recipientAddrs.length == refundAddrs.length, "Length of recipientAddrs doesn't equal to length of refundAddrs"); - require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); uint256 batchLength = amounts.length; uint256 totalAmount = 0; uint256 rewardForRelayer; uint256[] memory convertedAmounts = new uint256[](batchLength); for (uint i = 0; i < batchLength; i++) { - require(amounts[i]%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); + require(amounts[i] % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); totalAmount = totalAmount.add(amounts[i]); convertedAmounts[i] = amounts[i].div(TEN_DECIMALS); } - require(msg.value>=totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); + require(msg.value >= totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); rewardForRelayer = msg.value.sub(totalAmount); TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol: BEP2_TOKEN_SYMBOL_FOR_BNB, - contractAddr: address(0x00), - amounts: convertedAmounts, - recipients: recipientAddrs, - refundAddrs: refundAddrs, - expireTime: expireTime + bep2TokenSymbol : BEP2_TOKEN_SYMBOL_FOR_BNB, + contractAddr : address(0x00), + amounts : convertedAmounts, + recipients : recipientAddrs, + refundAddrs : refundAddrs, + expireTime : expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(address(0x0), msg.sender, totalAmount, rewardForRelayer); return true; } - function updateParam(string calldata key, bytes calldata value) override external onlyGov{ + function updateParam(string calldata key, bytes calldata value) override external onlyGov { require(value.length == 32, "expected value length is 32"); string memory localKey = key; bytes memory localValue = value; @@ -462,12 +462,12 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR assembly { bytes32Key := mload(add(localKey, 32)) } - if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) { // relayFee + if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) {// relayFee uint256 newRelayFee; assembly { newRelayFee := mload(add(localValue, 32)) } - require(newRelayFee <= 1e18 && newRelayFee%(TEN_DECIMALS)==0, "the relayFee out of range"); + require(newRelayFee <= 1e18 && newRelayFee % (TEN_DECIMALS) == 0, "the relayFee out of range"); relayFee = newRelayFee; } else { require(false, "unknown param"); @@ -475,11 +475,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR emit paramChange(key, value); } - function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns(address) { + function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns (address) { return bep2SymbolToContractAddr[bep2Symbol]; } - function getBep2SymbolByContractAddr(address contractAddr) external view override returns(bytes32) { + function getBep2SymbolByContractAddr(address contractAddr) external view override returns (bytes32) { return contractAddrToBEP2Symbol[contractAddr]; } @@ -494,43 +494,43 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR delete contractAddrToBEP2Symbol[contractAddr]; } - function isMiniBEP2Token(bytes32 symbol) internal pure returns(bool) { - bytes memory symbolBytes = new bytes(32); - assembly { - mstore(add(symbolBytes, 32), symbol) - } - uint8 symbolLength = 0; - for (uint8 j = 0; j < 32; j++) { - if (symbolBytes[j] != 0) { - symbolLength++; - } else { - break; - } - } - if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { - return false; - } - if (symbolBytes[symbolLength-5] != 0x2d) { // '-' - return false; - } - if (symbolBytes[symbolLength-1] != 'M') { // ABC-XXXM - return false; - } - return true; + function isMiniBEP2Token(bytes32 symbol) internal pure returns (bool) { + bytes memory symbolBytes = new bytes(32); + assembly { + mstore(add(symbolBytes, 32), symbol) + } + uint8 symbolLength = 0; + for (uint8 j = 0; j < 32; j++) { + if (symbolBytes[j] != 0) { + symbolLength++; + } else { + break; + } + } + if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { + return false; + } + if (symbolBytes[symbolLength - 5] != 0x2d) {// '-' + return false; + } + if (symbolBytes[symbolLength - 1] != 'M') {// ABC-XXXM + return false; + } + return true; } function convertToBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.div(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); + return amount.div(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); } - return amount.mul(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); + return amount.mul(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); } function convertFromBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.mul(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); + return amount.mul(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); } - return amount.div(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); + return amount.div(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); } function getBoundContract(string memory bep2Symbol) public view returns (address) { @@ -545,7 +545,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2SymbolBytes32 = contractAddrToBEP2Symbol[contractAddr]; bytes memory bep2SymbolBytes = new bytes(32); assembly { - mstore(add(bep2SymbolBytes,32), bep2SymbolBytes32) + mstore(add(bep2SymbolBytes, 32), bep2SymbolBytes32) } uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { @@ -557,7 +557,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } bytes memory bep2Symbol = new bytes(bep2SymbolLength); for (uint8 j = 0; j < bep2SymbolLength; j++) { - bep2Symbol[j] = bep2SymbolBytes[j]; + bep2Symbol[j] = bep2SymbolBytes[j]; } return string(bep2Symbol); } diff --git a/contracts/TokenHub.template b/contracts/TokenHub.template index a2979006..4a93b03a 100644 --- a/contracts/TokenHub.template +++ b/contracts/TokenHub.template @@ -28,7 +28,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256[] amounts; address[] recipients; address[] refundAddrs; - uint64 expireTime; + uint64 expireTime; } // BC to BSC @@ -46,7 +46,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256 amount; address recipient; address refundAddr; - uint64 expireTime; + uint64 expireTime; } // BSC to BC @@ -70,11 +70,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 constant public MAXIMUM_BEP20_SYMBOL_LEN = 8; uint8 constant public BEP2_TOKEN_DECIMALS = 8; bytes32 constant public BEP2_TOKEN_SYMBOL_FOR_BNB = 0x424E420000000000000000000000000000000000000000000000000000000000; // "BNB" - uint256 constant public MAX_GAS_FOR_CALLING_BEP20={{maxGasForCallingBEP20}}; - uint256 constant public MAX_GAS_FOR_TRANSFER_BNB={{maxGasForTransferringBNB}}; + uint256 constant public MAX_GAS_FOR_CALLING_BEP20 = {{maxGasForCallingBEP20}}; + uint256 constant public MAX_GAS_FOR_TRANSFER_BNB = {{maxGasForTransferringBNB}}; - uint256 constant public INIT_MINIMUM_RELAY_FEE ={{initRelayFee}}; - uint256 constant public REWARD_UPPER_LIMIT ={{rewardUpperLimit}}; + uint256 constant public INIT_MINIMUM_RELAY_FEE = {{initRelayFee}}; + uint256 constant public REWARD_UPPER_LIMIT = {{rewardUpperLimit}}; uint256 constant public TEN_DECIMALS = 1e10; uint256 public relayFee; @@ -97,32 +97,32 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function init() onlyNotInit external { relayFee = INIT_MINIMUM_RELAY_FEE; bep20ContractDecimals[address(0x0)] = 18; // BNB decimals is 18 - alreadyInit=true; + alreadyInit = true; } - receive() external payable{ - if (msg.value>0) { + receive() external payable { + if (msg.value > 0) { emit receiveDeposit(msg.sender, msg.value); } } - function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns(uint256) { + function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns (uint256) { uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > REWARD_UPPER_LIMIT) { return 0; } - if (actualAmount>0) { + if (actualAmount > 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } return actualAmount; } - function getMiniRelayFee() external view override returns(uint256) { + function getMiniRelayFee() external view override returns (uint256) { return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory) { + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns (bytes memory) { if (channelId == TRANSFER_IN_CHANNELID) { return handleTransferInSynPackage(msgBytes); } else { @@ -153,15 +153,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx=0; + uint256 idx = 0; while (iter.hasNext()) { - if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); - else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); - else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); - else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); - else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); + if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); + else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); + else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); + else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); + else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); else if (idx == 5) { - transInSynPkg.expireTime = uint64(iter.next().toUint()); + transInSynPkg.expireTime = uint64(iter.next().toUint()); success = true; } else break; @@ -179,17 +179,17 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return elements.encodeList(); } - function handleTransferInSynPackage(bytes memory msgBytes) internal returns(bytes memory) { + function handleTransferInSynPackage(bytes memory msgBytes) internal returns (bytes memory) { (TransferInSynPackage memory transInSynPkg, bool success) = decodeTransferInSynPackage(msgBytes); require(success, "unrecognized transferIn package"); uint32 resCode = doTransferIn(transInSynPkg); if (resCode != TRANSFER_IN_SUCCESS) { uint256 bep2Amount = convertToBep2Amount(transInSynPkg.amount, bep20ContractDecimals[transInSynPkg.contractAddr]); TransferInRefundPackage memory transInAckPkg = TransferInRefundPackage({ - bep2TokenSymbol: transInSynPkg.bep2TokenSymbol, - refundAmount: bep2Amount, - refundAddr: transInSynPkg.refundAddr, - status: resCode + bep2TokenSymbol : transInSynPkg.bep2TokenSymbol, + refundAmount : bep2Amount, + refundAddr : transInSynPkg.refundAddr, + status : resCode }); return encodeTransferInRefundPackage(transInAckPkg); } else { @@ -198,14 +198,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function doTransferIn(TransferInSynPackage memory transInSynPkg) internal returns (uint32) { - if (transInSynPkg.contractAddr==address(0x0)) { + if (transInSynPkg.contractAddr == address(0x0)) { if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } if (address(this).balance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - (bool success, ) = transInSynPkg.recipient.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: transInSynPkg.amount}(""); + (bool success,) = transInSynPkg.recipient.call{gas : MAX_GAS_FOR_TRANSFER_BNB, value : transInSynPkg.amount}(""); if (!success) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } @@ -215,14 +215,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } - if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr]!= transInSynPkg.bep2TokenSymbol) { + if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr] != transInSynPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP20}(address(this)); + uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas : MAX_GAS_FOR_CALLING_BEP20}(address(this)); if (actualBalance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); + bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas : MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); if (success) { emit transferInSuccess(transInSynPkg.contractAddr, transInSynPkg.recipient, transInSynPkg.amount); return TRANSFER_IN_SUCCESS; @@ -232,38 +232,38 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } } - function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns(TransferOutAckPackage memory, bool) { + function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns (TransferOutAckPackage memory, bool) { TransferOutAckPackage memory transOutAckPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx=0; + uint256 idx = 0; while (iter.hasNext()) { - if (idx == 0) { - transOutAckPkg.contractAddr = iter.next().toAddress(); - } - else if (idx == 1) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAmounts = new uint256[](list.length); - for (uint256 index=0; index=block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); bytes32 bep2TokenSymbol; uint256 convertedAmount; uint256 rewardForRelayer; - if (contractAddr==address(0x0)) { - require(msg.value>=amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); - require(amount%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); - rewardForRelayer=msg.value.sub(amount); + if (contractAddr == address(0x0)) { + require(msg.value >= amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); + require(amount % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); + rewardForRelayer = msg.value.sub(amount); convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 - bep2TokenSymbol=BEP2_TOKEN_SYMBOL_FOR_BNB; + bep2TokenSymbol = BEP2_TOKEN_SYMBOL_FOR_BNB; } else { bep2TokenSymbol = contractAddrToBEP2Symbol[contractAddr]; - require(bep2TokenSymbol!=bytes32(0x00), "the contract has not been bound to any bep2 token"); - require(msg.value>=relayFee, "received BNB amount should be no less than the minimum relayFee"); - rewardForRelayer=msg.value; - uint256 bep20TokenDecimals=bep20ContractDecimals[contractAddr]; - require(bep20TokenDecimals<=BEP2_TOKEN_DECIMALS || (bep20TokenDecimals>BEP2_TOKEN_DECIMALS && amount.mod(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS))==0), "invalid transfer amount: precision loss in amount conversion"); - convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals);// convert to bep2 amount + require(bep2TokenSymbol != bytes32(0x00), "the contract has not been bound to any bep2 token"); + require(msg.value >= relayFee, "received BNB amount should be no less than the minimum relayFee"); + rewardForRelayer = msg.value; + uint256 bep20TokenDecimals = bep20ContractDecimals[contractAddr]; + require(bep20TokenDecimals <= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals > BEP2_TOKEN_DECIMALS && amount.mod(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)) == 0), "invalid transfer amount: precision loss in amount conversion"); + convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals); // convert to bep2 amount if (isMiniBEP2Token(bep2TokenSymbol)) { - require(convertedAmount >= 1e8 , "For miniToken, the transfer amount must not be less than 1"); + require(convertedAmount >= 1e8, "For miniToken, the transfer amount must not be less than 1"); } - require(bep20TokenDecimals>=BEP2_TOKEN_DECIMALS || (bep20TokenDecimalsamount), "amount is too large, uint256 overflow"); - require(convertedAmount<=MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); + require(bep20TokenDecimals >= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals < BEP2_TOKEN_DECIMALS && convertedAmount > amount), "amount is too large, uint256 overflow"); + require(convertedAmount <= MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); require(IBEP20(contractAddr).transferFrom(msg.sender, address(this), amount)); } TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol: bep2TokenSymbol, - contractAddr: contractAddr, - amounts: new uint256[](1), - recipients: new address[](1), - refundAddrs: new address[](1), - expireTime: expireTime + bep2TokenSymbol : bep2TokenSymbol, + contractAddr : contractAddr, + amounts : new uint256[](1), + recipients : new address[](1), + refundAddrs : new address[](1), + expireTime : expireTime }); - transOutSynPkg.amounts[0]=convertedAmount; - transOutSynPkg.recipients[0]=recipient; - transOutSynPkg.refundAddrs[0]=msg.sender; + transOutSynPkg.amounts[0] = convertedAmount; + transOutSynPkg.recipients[0] = recipient; + transOutSynPkg.refundAddrs[0] = msg.sender; ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(contractAddr, msg.sender, amount, rewardForRelayer); return true; @@ -427,34 +427,34 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external override onlyInit payable returns (bool) { require(recipientAddrs.length == amounts.length, "Length of recipientAddrs doesn't equal to length of amounts"); require(recipientAddrs.length == refundAddrs.length, "Length of recipientAddrs doesn't equal to length of refundAddrs"); - require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); uint256 batchLength = amounts.length; uint256 totalAmount = 0; uint256 rewardForRelayer; uint256[] memory convertedAmounts = new uint256[](batchLength); for (uint i = 0; i < batchLength; i++) { - require(amounts[i]%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); + require(amounts[i] % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); totalAmount = totalAmount.add(amounts[i]); convertedAmounts[i] = amounts[i].div(TEN_DECIMALS); } - require(msg.value>=totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); + require(msg.value >= totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); rewardForRelayer = msg.value.sub(totalAmount); TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol: BEP2_TOKEN_SYMBOL_FOR_BNB, - contractAddr: address(0x00), - amounts: convertedAmounts, - recipients: recipientAddrs, - refundAddrs: refundAddrs, - expireTime: expireTime + bep2TokenSymbol : BEP2_TOKEN_SYMBOL_FOR_BNB, + contractAddr : address(0x00), + amounts : convertedAmounts, + recipients : recipientAddrs, + refundAddrs : refundAddrs, + expireTime : expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(address(0x0), msg.sender, totalAmount, rewardForRelayer); return true; } - function updateParam(string calldata key, bytes calldata value) override external onlyGov{ + function updateParam(string calldata key, bytes calldata value) override external onlyGov { require(value.length == 32, "expected value length is 32"); string memory localKey = key; bytes memory localValue = value; @@ -462,12 +462,12 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR assembly { bytes32Key := mload(add(localKey, 32)) } - if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) { // relayFee + if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) {// relayFee uint256 newRelayFee; assembly { newRelayFee := mload(add(localValue, 32)) } - require(newRelayFee <= 1e18 && newRelayFee%(TEN_DECIMALS)==0, "the relayFee out of range"); + require(newRelayFee <= 1e18 && newRelayFee % (TEN_DECIMALS) == 0, "the relayFee out of range"); relayFee = newRelayFee; } else { require(false, "unknown param"); @@ -475,11 +475,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR emit paramChange(key, value); } - function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns(address) { + function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns (address) { return bep2SymbolToContractAddr[bep2Symbol]; } - function getBep2SymbolByContractAddr(address contractAddr) external view override returns(bytes32) { + function getBep2SymbolByContractAddr(address contractAddr) external view override returns (bytes32) { return contractAddrToBEP2Symbol[contractAddr]; } @@ -494,43 +494,43 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR delete contractAddrToBEP2Symbol[contractAddr]; } - function isMiniBEP2Token(bytes32 symbol) internal pure returns(bool) { - bytes memory symbolBytes = new bytes(32); - assembly { - mstore(add(symbolBytes, 32), symbol) - } - uint8 symbolLength = 0; - for (uint8 j = 0; j < 32; j++) { - if (symbolBytes[j] != 0) { - symbolLength++; - } else { - break; - } - } - if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { - return false; - } - if (symbolBytes[symbolLength-5] != 0x2d) { // '-' - return false; - } - if (symbolBytes[symbolLength-1] != 'M') { // ABC-XXXM - return false; - } - return true; + function isMiniBEP2Token(bytes32 symbol) internal pure returns (bool) { + bytes memory symbolBytes = new bytes(32); + assembly { + mstore(add(symbolBytes, 32), symbol) + } + uint8 symbolLength = 0; + for (uint8 j = 0; j < 32; j++) { + if (symbolBytes[j] != 0) { + symbolLength++; + } else { + break; + } + } + if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { + return false; + } + if (symbolBytes[symbolLength - 5] != 0x2d) {// '-' + return false; + } + if (symbolBytes[symbolLength - 1] != 'M') {// ABC-XXXM + return false; + } + return true; } function convertToBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.div(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); + return amount.div(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); } - return amount.mul(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); + return amount.mul(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); } function convertFromBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.mul(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); + return amount.mul(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); } - return amount.div(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); + return amount.div(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); } function getBoundContract(string memory bep2Symbol) public view returns (address) { @@ -545,7 +545,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2SymbolBytes32 = contractAddrToBEP2Symbol[contractAddr]; bytes memory bep2SymbolBytes = new bytes(32); assembly { - mstore(add(bep2SymbolBytes,32), bep2SymbolBytes32) + mstore(add(bep2SymbolBytes, 32), bep2SymbolBytes32) } uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { @@ -557,7 +557,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } bytes memory bep2Symbol = new bytes(bep2SymbolLength); for (uint8 j = 0; j < bep2SymbolLength; j++) { - bep2Symbol[j] = bep2SymbolBytes[j]; + bep2Symbol[j] = bep2SymbolBytes[j]; } return string(bep2Symbol); } diff --git a/contracts/interface/IBSCValidatorSet.sol b/contracts/interface/IBSCValidatorSet.sol index 513c9289..51f3e9fe 100644 --- a/contracts/interface/IBSCValidatorSet.sol +++ b/contracts/interface/IBSCValidatorSet.sol @@ -1,7 +1,10 @@ pragma solidity 0.6.4; +pragma experimental ABIEncoderV2; interface IBSCValidatorSet { function misdemeanor(address validator) external; - function felony(address validator)external; + function felony(address validator) external; function isCurrentValidator(address validator) external view returns (bool); + function getLivingValidators() external view returns(address[] memory, bytes[] memory); + function getMiningValidators() external view returns(address[] memory, bytes[] memory); } diff --git a/test/BSCValidatorSet.js b/test/BSCValidatorSet.js index 8769ecdf..06062a0f 100644 --- a/test/BSCValidatorSet.js +++ b/test/BSCValidatorSet.js @@ -3,12 +3,12 @@ const SystemReward = artifacts.require("SystemReward"); const LightClient = artifacts.require("MockLightClient"); const RelayerIncentivize = artifacts.require("RelayerIncentivize"); const TokenManager = artifacts.require("TokenManager"); -const crypto = require('crypto'); +const crypto = require("crypto"); const MockTokenHub = artifacts.require("mock/MockTokenHub"); -const Web3 = require('web3'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); -const RLP = require('rlp'); -const truffleAssert = require('truffle-assertions'); +const Web3 = require("web3"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const RLP = require("rlp"); +const truffleAssert = require("truffle-assertions"); const CrossChain = artifacts.require("CrossChain"); const GovHub = artifacts.require("GovHub"); const RelayerHub = artifacts.require("RelayerHub"); @@ -19,91 +19,186 @@ const SlashIndicator = artifacts.require("SlashIndicator"); const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; -const packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( - "0x00" + - "000000000000000000000000000000000000000000000000002386F26FC10000" -)); +const packageBytesPrefix = Buffer.from( + web3.utils.hexToBytes("0x00" + "000000000000000000000000000000000000000000000000002386F26FC10000") +); -contract('BSCValidatorSet', (accounts) => { - it('query basic info', async () => { +contract("BSCValidatorSet", (accounts) => { + it("query basic info", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let totalInComing = await validatorSetInstance.totalInComing.call(); - assert.equal(totalInComing,0, "totalInComing should be 0"); + assert.equal(totalInComing, 0, "totalInComing should be 0"); - let consensusAddr = await validatorSetInstance.getValidators.call()[0]; - assert.equal(consensusAddr,accounts[9].address, "consensusAddr should be accounts[9]"); + let consensusAddr = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddr[0], accounts[0], "consensusAddr should be accounts[0]"); }); - it('deposit success and fail', async () => { + it("deposit success and fail", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); - let validator = accounts[0]; + let validator = accounts[0]; let systemAccount = accounts[0]; - let tx = await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); + let tx = await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); - truffleAssert.eventEmitted(tx, "validatorDeposit",(ev) => { + truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { return ev.amount.toNumber() === 1e8 && ev.validator === validator; }); let tmpAccount = web3.eth.accounts.create(); - tx = await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: 1e8 }); + tx = await validatorSetInstance.deposit(tmpAccount.address, { + from: systemAccount, + value: 1e8, + }); - truffleAssert.eventEmitted(tx, "deprecatedDeposit",(ev) => { + truffleAssert.eventEmitted(tx, "deprecatedDeposit", (ev) => { return ev.amount.toNumber() === 1e8 && ev.validator === tmpAccount.address; }); - try{ - await validatorSetInstance.deposit(validator, {from: accounts[2], value: 1e8 }); + try { + await validatorSetInstance.deposit(validator, { from: accounts[2], value: 1e8 }); assert.fail(); - }catch (error) { + } catch (error) { assert.ok(error.toString().includes("the message sender must be the block producer")); } - try{ - await validatorSetInstance.deposit(validator, {from: systemAccount, value: 0 }); + try { + await validatorSetInstance.deposit(validator, { from: systemAccount, value: 0 }); assert.fail(); - }catch (error) { + } catch (error) { assert.ok(error.toString().includes("deposit value is zero")); } - try{ - await validatorSetInstance.send(1e8, {from: systemAccount}); - assert.fail(); - }catch (error) { - } - let totalInComing = await validatorSetInstance.totalInComing.call(); - assert.equal(totalInComing.toNumber(),1e8, "totalInComing should be 1e8"); + assert.equal(totalInComing.toNumber(), 1e8, "totalInComing should be 1e8"); let balance_wei = await web3.eth.getBalance(validatorSetInstance.address); assert.equal(balance_wei, 2e8, "balance not equal"); }); +}); +contract("BSCValidatorSet", (accounts) => { + it("decode old version cross chain package", async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + let relayerAccount = accounts[8]; + let newValidator = web3.eth.accounts.create(); + let packageBytes = validatorUpdateRlpEncode([newValidator.address], [newValidator.address], [newValidator.address]); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + let consensusAddr = await validatorSetInstance.getValidators.call(); + truffleAssert.eventEmitted(tx, "validatorSetUpdated"); + assert.equal(consensusAddr[0], newValidator.address, "consensusAddr should be new validator"); + }); + + it("decode new version cross chain package", async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + let relayerAccount = accounts[8]; + + let newValidator = web3.eth.accounts.create(); + let voteAddrHex = "0x61626364"; // random bytes + let packageBytes = newValidatorUpdateRlpEncode( + [newValidator.address], + [newValidator.address], + [newValidator.address], + [web3.utils.hexToBytes(voteAddrHex)] + ); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + let consensusAddr = (await validatorSetInstance.getMiningValidators.call())["0"][0]; + let voteAddr = (await validatorSetInstance.getMiningValidators.call())["1"][0]; + + truffleAssert.eventEmitted(tx, "validatorSetUpdated"); + assert.equal(consensusAddr, newValidator.address, "consensusAddr should be new validator"); + assert.equal(voteAddr, voteAddrHex); + }); }); -contract('BSCValidatorSet', (accounts) => { - it('test distribute algorithm', async () => { +contract("BSCValidatorSet", (accounts) => { + it("distribute finality reward success", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let validator = accounts[0]; + await systemRewardInstance.send(web3.utils.toBN(1e10), { from: accounts[1] }); + + let accountOne = accounts[0]; + let relayerAccount = accounts[8]; + + let newValidators = []; + for (let i = 0; i < 10; i++) { + newValidators.push(web3.eth.accounts.create().address); + } + let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + + let valAddrs = await validatorSetInstance.getValidators.call(); + for (let i = 0; i < 10; i++) { + valAddrs.push(web3.eth.accounts.create().address); + } + let weights = new Array(valAddrs.length).fill(1); + + await systemRewardInstance.addOperator(validatorSetInstance.address); + let tx = await validatorSetInstance.distributeFinalityReward(valAddrs, weights, { + from: accountOne, + }); + + for (let i = 0; i < 10; i++) { + truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { + return ev.validator === valAddrs[i] && ev.amount.toNumber() === 5e7; + }); + } + for (let i = 0; i < 10; i++) { + truffleAssert.eventEmitted(tx, "deprecatedDeposit", (ev) => { + return ev.validator === valAddrs[i + 10] && ev.amount.toNumber() === 5e7; + }); + } + }); + + it("distribute finality reward fail", async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + + let valAddrs = await validatorSetInstance.getValidators.call(); + let weights = new Array(valAddrs.length).fill(1); + + try { + await validatorSetInstance.distributeFinalityReward(valAddrs, weights, { from: accounts[2] }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("the message sender must be the block producer")); + } + }); +}); + +contract("BSCValidatorSet", (accounts) => { + it("test distribute algorithm", async () => { + const validatorSetInstance = await BSCValidatorSet.deployed(); + const systemRewardInstance = await SystemReward.deployed(); + + let validator = accounts[0]; let systemAccount = accounts[0]; let tmpAccount = web3.eth.accounts.create(); // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); - - for(let i =0;i <5; i++){ - await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); - await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: 1e8 }); + for (let i = 0; i < 5; i++) { + await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); + await validatorSetInstance.deposit(tmpAccount.address, { from: systemAccount, value: 1e8 }); } - for(let i =0;i <5; i++){ - await validatorSetInstance.deposit(validator, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: web3.utils.toBN(1e18) }); + for (let i = 0; i < 5; i++) { + await validatorSetInstance.deposit(validator, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(tmpAccount.address, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); } let newValidator = web3.eth.accounts.create(); @@ -114,19 +209,28 @@ contract('BSCValidatorSet', (accounts) => { let totalInComing = await validatorSetInstance.totalInComing.call(); let relayerBalance = await web3.eth.getBalance(relayerAccount); - assert.equal(totalInComing.toString(), web3.utils.toBN(5e18).add(web3.utils.toBN(5e8)).toString(), "totalInComing is not correct"); - assert.equal(totalBalance.toString(), web3.utils.toBN(1e19).add(web3.utils.toBN(1e9)).toString(), "totalbalance is not correct"); + assert.equal( + totalInComing.toString(), + web3.utils.toBN(5e18).add(web3.utils.toBN(5e8)).toString(), + "totalInComing is not correct" + ); + assert.equal( + totalBalance.toString(), + web3.utils.toBN(1e19).add(web3.utils.toBN(1e9)).toString(), + "totalBalance is not correct" + ); // do update - let packageBytes = validatorUpdateRlpEncode([newValidator.address], - [newValidator.address],[newValidator.address]); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode([newValidator.address], [newValidator.address], [newValidator.address]); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(5e18).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(5e18).add(web3.utils.toBN(1e9)).toString(); }); @@ -137,16 +241,18 @@ contract('BSCValidatorSet', (accounts) => { totalInComing = await validatorSetInstance.totalInComing.call(); let afterRelayerBalance = await web3.eth.getBalance(relayerAccount); - assert.equal(web3.utils.toBN(relayerBalance).sub(web3.utils.toBN(afterRelayerBalance)).toString(), used_wei.toString(), "totalInComing is not correct"); + assert.equal( + web3.utils.toBN(relayerBalance).sub(web3.utils.toBN(afterRelayerBalance)).toString(), + used_wei.toString(), + "totalInComing is not correct" + ); assert.equal(totalInComing.toNumber(), 0, "totalInComing is not correct"); - assert.equal(totalBalance, 0, "totalbalance is not correct"); - + assert.equal(totalBalance, 0, "totalBalance is not correct"); }); - }); -contract('BSCValidatorSet', (accounts) => { - it('test distribute algorithm with 41 validators', async () => { +contract("BSCValidatorSet", (accounts) => { + it("test distribute algorithm with 41 validators", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -154,40 +260,48 @@ contract('BSCValidatorSet', (accounts) => { let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); let newValidators = []; - for(let i =0;i <41; i++) { - newValidators.push(web3.eth.accounts.create().address) + for (let i = 0; i < 41; i++) { + newValidators.push(web3.eth.accounts.create().address); } - let packageBytes = validatorUpdateRlpEncode(newValidators, - newValidators,newValidators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); // do deposit - for(let i =0;i <41; i++){ - await validatorSetInstance.deposit(newValidators[i], {from: systemAccount, value: 1e18 }); + let receipt; + for (let i = 0; i < 41; i++) { + receipt = await validatorSetInstance.deposit(newValidators[i], { + from: systemAccount, + value: 1e18, + }); + truffleAssert.eventEmitted(receipt, "validatorDeposit", (ev) => { + return ev.validator === newValidators[i]; + }); } // do update let updateValidators = []; - for(let i =0;i <41; i++) { - updateValidators.push(web3.eth.accounts.create().address) + for (let i = 0; i < 41; i++) { + updateValidators.push(web3.eth.accounts.create().address); } - packageBytes = validatorUpdateRlpEncode(updateValidators, - updateValidators,updateValidators); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - console.log("The total gasUsd is", tx.receipt.gasUsed) + packageBytes = validatorUpdateRlpEncode(updateValidators, updateValidators, updateValidators); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + console.log("The total gasUsed is", tx.receipt.gasUsed); }); - }); -contract('BSCValidatorSet', (accounts) => { - it('complicate validatorSet change and test valdiatorset map', async () => { +contract("BSCValidatorSet", (accounts) => { + it("complicate validatorSet change and test validatorSet map", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let validatorA = accounts[0]; + let validatorA = accounts[0]; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; @@ -195,97 +309,121 @@ contract('BSCValidatorSet', (accounts) => { let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); await validatorSetInstance.getValidators.call(); - let arrs = [[validatorB,validatorA,validatorC,validatorD], - [validatorB,validatorC,validatorE], - [validatorB,validatorC,validatorE], - [validatorE,validatorC,validatorB], - [validatorE,validatorC,validatorB,validatorA,validatorD], - [validatorE,validatorC,validatorB,validatorA]]; - for(let j=0;j { - it('failed to update', async () => { +contract("BSCValidatorSet", (accounts) => { + it("failed to update", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); const crossChain = await CrossChain.deployed(); - let validatorA = accounts[0]; + let validatorA = accounts[0]; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; let validatorE = web3.eth.accounts.create().address; let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); - - let arrs = [[validatorB,validatorA,validatorC,validatorD], - [validatorB,validatorB,validatorE], - [validatorC,validatorC,validatorB], - []]; + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + + let arrs = [ + [validatorB, validatorA, validatorC, validatorD], + [validatorB, validatorB, validatorE], + [validatorC, validatorC, validatorB], + [], + ]; let packageBytes = validatorUpdateRlpEncode(arrs[0], arrs[0], arrs[0]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); - for(let j=1;j { + let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { return ev.message === "duplicate consensus address of validatorSet"; }); } - let arr =arrs[3]; + let arr = arrs[3]; - packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); truffleAssert.eventNotEmitted(tx, "failReasonWithStr"); // block the light client const lightClientInstance = await LightClient.deployed(); await lightClientInstance.setBlockNotSynced(true); let validArray = arrs[0]; - try{ - packageBytes = validatorUpdateRlpEncode(validArray, validArray,validArray); - await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), crypto.randomBytes(32),100, 0, STAKE_CHANNEL_ID, {from: relayerAccount}); + try { + packageBytes = validatorUpdateRlpEncode(validArray, validArray, validArray); + await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + crypto.randomBytes(32), + 100, + 0, + STAKE_CHANNEL_ID, + { from: relayerAccount } + ); assert.fail(); - }catch(error){ + } catch (error) { assert.ok(error.toString().includes("light client not sync the block yet")); } await lightClientInstance.setBlockNotSynced(false); - try{ - packageBytes = validatorUpdateRlpEncode(validArray, validArray,validArray); - await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), crypto.randomBytes(32),100, 0, STAKE_CHANNEL_ID, {from: accounts[4]}); + try { + packageBytes = validatorUpdateRlpEncode(validArray, validArray, validArray); + await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + crypto.randomBytes(32), + 100, + 0, + STAKE_CHANNEL_ID, + { from: accounts[4] } + ); assert.fail(); - }catch(error){ + } catch (error) { assert.ok(error.toString().includes("the msg sender is not a relayer")); } - }); }); -contract('BSCValidatorSet', (accounts) => { - it('complicate distribute', async () => { +contract("BSCValidatorSet", (accounts) => { + it("complicate distribute", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -299,27 +437,52 @@ contract('BSCValidatorSet', (accounts) => { let systemAccount = accounts[0]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); await validatorSetInstance.getValidators.call(); - let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; + let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); - await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorA, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorB, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorC, { + from: systemAccount, + value: web3.utils.toBN(1e17), + }); + await validatorSetInstance.deposit(validatorD, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(deprecated, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e5), + }); - packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); let validatorCBalance = await web3.eth.getBalance(validatorC); @@ -327,33 +490,33 @@ contract('BSCValidatorSet', (accounts) => { let validatorEBalance = await web3.eth.getBalance(validatorE); let deprecatedBalance = await web3.eth.getBalance(deprecated); - assert.equal(validatorABalance,web3.utils.toBN(1e16)); - assert.equal(validatorBBalance,web3.utils.toBN(1e16)); - assert.equal(validatorCBalance,0); - assert.equal(validatorDBalance,0); - assert.equal(validatorEBalance,0); - assert.equal(deprecatedBalance,0); + assert.equal(validatorABalance, web3.utils.toBN(1e16)); + assert.equal(validatorBBalance, web3.utils.toBN(1e16)); + assert.equal(validatorCBalance, 0); + assert.equal(validatorDBalance, 0); + assert.equal(validatorEBalance, 0); + assert.equal(deprecatedBalance, 0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).toString(); }); }); }); - -contract('BSCValidatorSet', (accounts) => { - it('complicate distribute when one validar fee addr is contract', async () => { +contract("BSCValidatorSet", (accounts) => { + it("complicate distribute when one validator fee addr is contract", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); + const crossChainInstance = await CrossChain.deployed(); - let validatorA = validatorSetInstance.address; + let validatorA = crossChainInstance.address; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; @@ -363,27 +526,52 @@ contract('BSCValidatorSet', (accounts) => { let systemAccount = accounts[0]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); await validatorSetInstance.getValidators.call(); - let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; + let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); - await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorA, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorB, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorC, { + from: systemAccount, + value: web3.utils.toBN(1e17), + }); + await validatorSetInstance.deposit(validatorD, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(deprecated, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e5), + }); - packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); @@ -392,36 +580,39 @@ contract('BSCValidatorSet', (accounts) => { let validatorEBalance = await web3.eth.getBalance(validatorE); let deprecatedBalance = await web3.eth.getBalance(deprecated); - assert.equal(validatorABalance,0); - assert.equal(validatorBBalance,web3.utils.toBN(1e16)); - assert.equal(validatorCBalance,0); - assert.equal(validatorDBalance,0); - assert.equal(validatorEBalance,0); - assert.equal(deprecatedBalance,0); + assert.equal(validatorABalance, 0); + assert.equal(validatorBBalance, web3.utils.toBN(1e16)); + assert.equal(validatorCBalance, 0); + assert.equal(validatorDBalance, 0); + assert.equal(validatorEBalance, 0); + assert.equal(deprecatedBalance, 0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "directTransferFail",(ev) => { + truffleAssert.eventEmitted(tx, "directTransferFail", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { - return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).add(web3.utils.toBN(1e16)).toString(); + truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { + return ( + ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).add(web3.utils.toBN(1e16)).toString() + ); }); }); }); -contract('BSCValidatorSet', (accounts) => { - it('complicate distribute when cross chain transfer failed', async () => { +contract("BSCValidatorSet", (accounts) => { + it("complicate distribute when cross chain transfer failed", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); + const crossChainInstance = await CrossChain.deployed(); const tokenHub = await MockTokenHub.deployed(); - let validatorA = validatorSetInstance.address; + let validatorA = crossChainInstance.address; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; @@ -429,30 +620,55 @@ contract('BSCValidatorSet', (accounts) => { let deprecated = web3.eth.accounts.create().address; let relayerAccount = accounts[8]; let systemAccount = accounts[0]; - await tokenHub.setPanicBatchTransferOut(true); + await tokenHub.setPanicBatchTransferOut(true); // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); await validatorSetInstance.getValidators.call(); - let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; + let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); - await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); - await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); - await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorA, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorB, { + from: systemAccount, + value: web3.utils.toBN(1e16), + }); + await validatorSetInstance.deposit(validatorC, { + from: systemAccount, + value: web3.utils.toBN(1e17), + }); + await validatorSetInstance.deposit(validatorD, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); + await validatorSetInstance.deposit(deprecated, { + from: systemAccount, + value: web3.utils.toBN(1e18), + }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); + await validatorSetInstance.deposit(validatorE, { + from: systemAccount, + value: web3.utils.toBN(1e5), + }); - packageBytes = validatorUpdateRlpEncode(arr, arr,arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + packageBytes = validatorUpdateRlpEncode(arr, arr, arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); @@ -469,23 +685,23 @@ contract('BSCValidatorSet', (accounts) => { assert.equal(deprecatedBalance, 0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransferFailed",(ev) => { + truffleAssert.eventEmitted(tx, "batchTransferFailed", (ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "directTransferFail",(ev) => { + truffleAssert.eventEmitted(tx, "directTransferFail", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e16)).toString(); }); }); }); -contract('BSCValidatorSet', (accounts) => { - it('validator jail', async () => { +contract("BSCValidatorSet", (accounts) => { + it("validator jail", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let newValidator1 = web3.eth.accounts.create(); @@ -494,166 +710,251 @@ contract('BSCValidatorSet', (accounts) => { let relayerAccount = accounts[8]; // do update - let packageBytes = validatorUpdateRlpEncode([newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address], [newValidator1.address, newValidator2.address, newValidator3.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - - let consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length, 3); - assert.equal(consensusAddres[0], newValidator1.address); - assert.equal(consensusAddres[1], newValidator2.address); - assert.equal(consensusAddres[2], newValidator3.address); + let packageBytes = validatorUpdateRlpEncode( + [newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); - packageBytes = jailRlpEncode([newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address], [newValidator1.address, newValidator2.address, newValidator3.address]); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let consensusAddrs = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddrs.length, 3); + assert.equal(consensusAddrs[0], newValidator1.address); + assert.equal(consensusAddrs[1], newValidator2.address); + assert.equal(consensusAddrs[2], newValidator3.address); + + packageBytes = jailRlpEncode( + [newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address] + ); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { return ev.message === "length of jail validators must be one"; }); packageBytes = jailRlpEncode([newValidator1.address], [newValidator1.address], [newValidator1.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); - consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length, 2); - assert.equal(consensusAddres[0], newValidator2.address); - assert.equal(consensusAddres[1], newValidator3.address); + consensusAddrs = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddrs.length, 2); + assert.equal(consensusAddrs[0], newValidator2.address); + assert.equal(consensusAddrs[1], newValidator3.address); // ok to re jail packageBytes = jailRlpEncode([newValidator1.address], [newValidator1.address], [newValidator1.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); packageBytes = jailRlpEncode([newValidator2.address], [newValidator2.address], [newValidator2.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); - consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length, 1); - assert.equal(consensusAddres[0], newValidator3.address); + consensusAddrs = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddrs.length, 1); + assert.equal(consensusAddrs[0], newValidator3.address); // can not jail if it is the last one validator packageBytes = jailRlpEncode([newValidator3.address], [newValidator3.address], [newValidator3.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - - consensusAddres = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddres.length, 1); - assert.equal(consensusAddres[0], newValidator3.address); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + consensusAddrs = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddrs.length, 1); + assert.equal(consensusAddrs[0], newValidator3.address); }); }); -contract('BSCValidatorSet', (accounts) => { - it('test distribute algorithm with more than 41 validators', async () => { +contract("BSCValidatorSet", (accounts) => { + it("test distribute algorithm with more than 41 validators", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let relayerAccount = accounts[8]; let newValidators = []; for (let i = 0; i < 42; i++) { - newValidators.push(web3.eth.accounts.create().address) + newValidators.push(web3.eth.accounts.create().address); } - let packageBytes = validatorUpdateRlpEncode(newValidators, - newValidators, newValidators); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); - + let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { return ev.message === "the number of validators exceed the limit"; }); }); }); -contract('BSCValidatorSet', (accounts) => { - it('burn', async () => { +contract("BSCValidatorSet", (accounts) => { + it("burn", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let systemAccount = accounts[0]; - let validator = accounts[0]; + let validator = accounts[0]; - let relayerAccount = accounts[8]; const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); + await relayerInstance.register({ from: relayer, value: 1e20 }); let initialBurnRatio = await validatorSetInstance.burnRatio.call(); assert.equal(web3.utils.toBN(initialBurnRatio).eq(web3.utils.toBN(0)), true, "wrong burnRatio"); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + LightClient.address, + MockTokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + crossChain.address + ); let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000BB8";// 3000; + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000BB8"; // 3000; let govPackageBytes = serializeGovPack("burnRatio", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); let burnRatio = await validatorSetInstance.burnRatio.call(); assert.equal(web3.utils.toBN(burnRatio).eq(web3.utils.toBN(3000)), true, "wrong burnRatio"); - let tx = await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); + let tx = await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); - truffleAssert.eventEmitted(tx, "validatorDeposit",(ev) => { + truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { return ev.amount.toNumber() === 7e7 && ev.validator === validator; }); - truffleAssert.eventEmitted(tx, "feeBurned",(ev) => { + truffleAssert.eventEmitted(tx, "feeBurned", (ev) => { return ev.amount.toNumber() === 3e7; }); }); }); -contract('BSCValidatorSet', (accounts) => { - it('test set maxNumOfWorkingCandidates greater than maxNumOfCandidates', async () => { +contract("BSCValidatorSet", (accounts) => { + it("test set maxNumOfWorkingCandidates greater than maxNumOfCandidates", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); + await relayerInstance.register({ from: relayer, value: 1e20 }); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + LightClient.address, + MockTokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + crossChain.address + ); // should fail - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; - govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000002"; // 2; + let govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + let except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(0)), true, "wrong maxNumOfWorkingCandidates"); }); }); -contract('BSCValidatorSet', (accounts) => { - it('test set maxNumOfCandidates less than maxNumOfWorkingCandidates', async () => { +contract("BSCValidatorSet", (accounts) => { + it("test set maxNumOfCandidates less than maxNumOfWorkingCandidates", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); + await relayerInstance.register({ from: relayer, value: 1e20 }); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + LightClient.address, + MockTokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + crossChain.address + ); // set maxNumOfCandidates to 20 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; - govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - - except = await validatorSetInstance.maxNumOfCandidates.call(); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000014"; // 20; + let govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + let except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); // set maxNumOfWorkingCandidates to 10 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x000000000000000000000000000000000000000000000000000000000000000A";// 10; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x000000000000000000000000000000000000000000000000000000000000000A"; // 10; govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(10)), true, "wrong maxNumOfWorkingCandidates"); // set maxNumOfCandidates to 5 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x0000000000000000000000000000000000000000000000000000000000000005";// 5; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000000000000000000005"; // 5; govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(5)), true, "wrong maxNumOfCandidates"); except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); @@ -661,30 +962,49 @@ contract('BSCValidatorSet', (accounts) => { }); }); -contract('BSCValidatorSet', (accounts) => { - it('test getMiningValidators with 41 validators', async () => { +contract("BSCValidatorSet", (accounts) => { + it("test getMiningValidators with 41 validators", async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); + await relayerInstance.register({ from: relayer, value: 1e20 }); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + LightClient.address, + MockTokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + crossChain.address + ); let relayerAccount = accounts[8]; let newValidators = []; for (let i = 0; i < 41; i++) { - newValidators.push(web3.eth.accounts.create().address) + newValidators.push(web3.eth.accounts.create().address); } - let packageBytes = validatorUpdateRlpEncode(newValidators, - newValidators, newValidators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); // set numOfCabinets to 21 let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000015";// 21; + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000015"; // 21; let govPackageBytes = serializeGovPack("numOfCabinets", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); let except = await validatorSetInstance.numOfCabinets.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(21)), true, "wrong numOfCabinets"); @@ -693,92 +1013,121 @@ contract('BSCValidatorSet', (accounts) => { let maxNumOfWorkingCandidates = 2; let numOfCabinets = 21; let validators = await validatorSetInstance.getValidators.call(); - let miningValidators = await validatorSetInstance.getMiningValidators.call(); - assert.deepEqual(validators.slice(0,numOfCabinets), miningValidators, "wrong validators"); + let miningValidators = (await validatorSetInstance.getMiningValidators.call())["0"]; + assert.deepEqual(validators.slice(0, numOfCabinets), miningValidators, "wrong validators"); // set maxNumOfCandidates to 20 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000000000000000000014"; // 20; govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); // set maxNumOfWorkingCandidates to 2 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) - govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000000000000000000002"; // 2; govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(2)), true, "wrong maxNumOfWorkingCandidates"); - if ((validators.length - numOfCabinets) < maxNumOfWorkingCandidates){ + if (validators.length - numOfCabinets < maxNumOfWorkingCandidates) { maxNumOfWorkingCandidates = validators.length - numOfCabinets; - } - - miningValidators = await validatorSetInstance.getMiningValidators.call(); - let exceptValues = validators.slice(0,numOfCabinets); - let outValidator = miningValidators.filter((addr)=>{ + } + + miningValidators = (await validatorSetInstance.getMiningValidators.call())["0"]; + let exceptValues = validators.slice(0, numOfCabinets); + let outValidator = miningValidators.filter((addr) => { return !exceptValues.includes(addr); }); // TODO, this is not always true, but as the epoch number is fixed during UT, the result is fixed. - assert(outValidator.length > 0, "no validator choose from candidates"); - assert(outValidator.length <= maxNumOfWorkingCandidates, "too many working candidates" ) - + assert(outValidator.length > 0, "no validator choose from candidates"); + assert(outValidator.length <= maxNumOfWorkingCandidates, "too many working candidates"); }); }); -function jailRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) { +function jailRlpEncode(consensusAddrList, feeAddrList, bscFeeAddrList) { let pkg = []; pkg.push(0x01); let n = consensusAddrList.length; let vals = []; - for(let i = 0;i { - it('Gov others success', async () => { - const govHubInstance = await GovHub.deployed(); - const bSCValidatorSetInstance =await BSCValidatorSet.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x0000000000000000000000000000000000000000000000000000000000010000", bSCValidatorSetInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "expireTimeSecondGap"; - }); - - let reward = await bSCValidatorSetInstance.expireTimeSecondGap.call(); - assert.equal(reward.toNumber(), 65536, "value not equal"); - }); - - it('Gov others failed', async () => { - const govHubInstance = await GovHub.deployed(); - const bSCValidatorSetInstance =await BSCValidatorSet.deployed(); - const systemRewardInstance = await SystemReward.deployed(); - const relayerAccount = accounts[8]; - - // unknown key - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("unknown key", "0x0000000000000000000000000000000000000000000000000000000000010000", bSCValidatorSetInstance.address), - {from: relayerAccount}); - - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "unknown param"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange") - - // exceed range key - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x000000000000010000000000000000000000000000000000000000000000000", bSCValidatorSetInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the expireTimeSecondGap is out of range"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange") +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); + +contract("GovHub others", (accounts) => { + it("Gov validatorSet", async () => { + const govHubInstance = await GovHub.deployed(); + const bSCValidatorSetInstance = await BSCValidatorSet.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x0000000000000000000000000000000000000000000000000000000000010000", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "expireTimeSecondGap"; + }); - // length mismatch - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x10000", bSCValidatorSetInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "length of expireTimeSecondGap mismatch"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange") + let reward = await bSCValidatorSetInstance.expireTimeSecondGap.call(); + assert.equal(reward.toNumber(), 65536, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "finalityRewardRatio", + "0x0000000000000000000000000000000000000000000000000000000000000032", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "finalityRewardRatio"; + }); - // address do not exist - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x1110000000000000000000000000000000001004"), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the target is not a contract"; - }); + let rewardRatio = await bSCValidatorSetInstance.finalityRewardRatio.call(); + assert.equal(rewardRatio.toNumber(), 50, "value not equal"); + }); + + it("Gov tokenhub", async () => { + const govHubInstance = await GovHub.deployed(); + const tokenHub = await TokenHub.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("relayFee", "0x00000000000000000000000000000000000000000000000000038d7ea4c68000", tokenHub.address), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "relayFee"; + }); + + let minimumRelayFee = await tokenHub.relayFee.call(); + assert.equal(minimumRelayFee.toNumber(), 1000000000000000, "value not equal"); + }); + + it("Gov tendermintLightClient", async () => { + const govHubInstance = await GovHub.deployed(); + const tendermintLightClient = await TendermintLightClient.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "rewardForValidatorSetChange", + "0x0000000000000000000000000000000000000000000000000000000000010000", + TendermintLightClient.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "rewardForValidatorSetChange"; + }); - // method do no exist - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x0000000000000000000000000000000000000000000000000000000000000000", systemRewardInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithBytes",(ev) => { - return ev.message === null; - }); + let rewardForValidatorSetChange = await tendermintLightClient.rewardForValidatorSetChange.call(); + assert.equal(rewardForValidatorSetChange.toNumber(), 65536, "value not equal"); + }); + + it("Gov RelayerHub", async () => { + const govHubInstance = await GovHub.deployed(); + const relayerHub = await RelayerHub.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "requiredDeposit", + "0x0000000000000000000000000000000000000000000000000000000000010000", + relayerHub.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the requiredDeposit out of range"; }); - it('Gov tokenhub', async () => { - const govHubInstance = await GovHub.deployed(); - const tokenHub =await TokenHub.deployed(); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "requiredDeposit", + "0x0010000000000000000000000000000000000000000000000000000000000000", + relayerHub.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the requiredDeposit out of range"; + }); - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("relayFee", "0x00000000000000000000000000000000000000000000000000038d7ea4c68000", tokenHub.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "relayFee"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "requiredDeposit", + "0x0000000000000000000000000000000000000000000000000000000000000000", + relayerHub.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the requiredDeposit out of range"; + }); - let minimumRelayFee = await tokenHub.relayFee.call(); - assert.equal(minimumRelayFee.toNumber(), 1000000000000000, "value not equal"); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "requiredDeposit", + "0x0000000000000000000000000000000000000000000000056bc75e2d63000000", + relayerHub.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "requiredDeposit"; }); - it('Gov tendermintLightClient', async () => { - const govHubInstance = await GovHub.deployed(); - const tendermintLightClient =await TendermintLightClient.deployed(); + let requiredDeposit = await relayerHub.requiredDeposit.call(); + assert.equal(requiredDeposit.toString(), "99999999999998951424", "value not equal"); - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("rewardForValidatorSetChange", "0x0000000000000000000000000000000000000000000000000000000000010000", TendermintLightClient.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "rewardForValidatorSetChange"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("dues", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + { from: relayerAccount } + ); - let rewardForValidatorSetChange = await tendermintLightClient.rewardForValidatorSetChange.call(); - assert.equal(rewardForValidatorSetChange.toNumber(), 65536, "value not equal"); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the dues out of range"; }); - it('Gov RelayerHub', async () => { - const govHubInstance = await GovHub.deployed(); - const relayerHub =await RelayerHub.deployed(); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("dues", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + { from: relayerAccount } + ); - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000000000000000010000", relayerHub.address), - {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the dues out of range"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the requiredDeposit out of range"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("dues", "0x0000000000000000000000000000000000000000000000016bc75e2d63000000", relayerHub.address), + { from: relayerAccount } + ); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "dues"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the requiredDeposit out of range"; - }); + let dues = await relayerHub.dues.call(); + assert.equal(dues.toString(), "26213023705160744960", "value not equal"); + }); + + it("Gov relayerIncentivize", async () => { + const govHubInstance = await GovHub.deployed(); + const relayerIncentivize = await RelayerIncentivize.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "headerRelayerRewardRateMolecule", + "0x000000000000000000000000000000000000000000000000000000000000000f", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { + return ev.key === "headerRelayerRewardRateMolecule"; + }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - {from: relayerAccount}); + let headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); + assert.equal(headerRelayerRewardRateMolecule.toNumber(), 1, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "headerRelayerRewardRateMolecule", + "0x0000000000000000000000000000000000000000000000000000000000000002", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "headerRelayerRewardRateMolecule"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the requiredDeposit out of range"; - }); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000056bc75e2d63000000", relayerHub.address), - {from: relayerAccount}); + headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); + assert.equal(headerRelayerRewardRateMolecule.toNumber(), 2, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "headerRelayerRewardRateDenominator", + "0x0000000000000000000000000000000000000000000000000000000000000001", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { + return ev.key === "headerRelayerRewardRateDenominator"; + }); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "requiredDeposit"; - }); - - let requiredDeposit = await relayerHub.requiredDeposit.call(); - assert.equal(requiredDeposit.toString(), "99999999999998951424", "value not equal"); + let headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); + assert.equal(headerRelayerRewardRateDenominator.toNumber(), 5, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "headerRelayerRewardRateDenominator", + "0x0000000000000000000000000000000000000000000000000000000000000004", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "headerRelayerRewardRateDenominator"; + }); + headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); + assert.equal(headerRelayerRewardRateDenominator.toNumber(), 4, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "callerCompensationMolecule", + "0x0000000000000000000000000000000000000000000000000000000000000064", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { + return ev.key === "callerCompensationMolecule"; + }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - {from: relayerAccount}); + let callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); + assert.equal(callerCompensationMolecule.toNumber(), 1, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "callerCompensationMolecule", + "0x0000000000000000000000000000000000000000000000000000000000000010", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "callerCompensationMolecule"; + }); + + callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); + assert.equal(callerCompensationMolecule.toNumber(), 16, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "callerCompensationDenominator", + "0x000000000000000000000000000000000000000000000000000000000000000f", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { + return ev.key === "callerCompensationDenominator"; + }); + + let callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); + assert.equal(callerCompensationDenominator.toNumber(), 80, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "callerCompensationDenominator", + "0x0000000000000000000000000000000000000000000000000000000000000020", + RelayerIncentivize.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "callerCompensationDenominator"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the dues out of range"; - }); + callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); + assert.equal(callerCompensationDenominator.toNumber(), 32, "value not equal"); + }); + + it("Gov cross chain contract", async () => { + const govHubInstance = await GovHub.deployed(); + const crossChainInstance = await CrossChain.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "addOrUpdateChannel", + web3.utils.bytesToHex( + Buffer.concat([ + Buffer.from(web3.utils.hexToBytes("0x57")), + Buffer.from(web3.utils.hexToBytes("0x00")), + Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address)), + ]) + ), + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "addOrUpdateChannel"; + }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - {from: relayerAccount}); + await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "addOrUpdateChannel", + web3.utils.bytesToHex( + Buffer.concat([ + Buffer.from(web3.utils.hexToBytes("0x58")), + Buffer.from(web3.utils.hexToBytes("0x00")), + Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address)), + ]) + ), + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "addOrUpdateChannel"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the dues out of range"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "enableOrDisableChannel", + web3.utils.bytesToHex( + Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00"))]) + ), + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "enableOrDisableChannel"; + }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0000000000000000000000000000000000000000000000016bc75e2d63000000", relayerHub.address), - {from: relayerAccount}); + let isChannelEnable = await crossChainInstance.registeredContractChannelMap.call( + RelayerIncentivize.address, + "0x57" + ); + assert.equal(isChannelEnable, false, "channel should be disabled"); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); + assert.equal(isChannelEnable, true, "channel should be enabled"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "enableOrDisableChannel", + web3.utils.bytesToHex( + Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x01"))]) + ), + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "enableOrDisableChannel"; + }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "enableOrDisableChannel", + web3.utils.bytesToHex( + Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00"))]) + ), + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "enableOrDisableChannel"; + }); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); + assert.equal(isChannelEnable, true, "channel should be enabled"); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); + assert.equal(isChannelEnable, false, "channel should be disabled"); + + let appAddr = await crossChainInstance.channelHandlerContractMap.call(0x57); + assert.equal(appAddr, RelayerIncentivize.address, "value not equal"); + let fromSys = await crossChainInstance.isRelayRewardFromSystemReward.call(0x57); + assert.equal(fromSys, true, "should from system reward"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "batchSizeForOracle", + "0x0000000000000000000000000000000000000000000000000000000000000064", + crossChainInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "batchSizeForOracle"; + }); + let batchSizeForOracle = await crossChainInstance.batchSizeForOracle.call(); + assert.equal(batchSizeForOracle, 100, "value not equal"); + }); + + it("Gov SlashIndicator", async () => { + const govHubInstance = await GovHub.deployed(); + const slashIndicator = await SlashIndicator.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "felonyThreshold", + "0x0000000000000000000000000000000000000000000000000000000000000100", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "felonyThreshold"; + }); + let felonyThreshold = await slashIndicator.felonyThreshold.call(); + assert.equal(felonyThreshold.toNumber(), 256, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "felonyThreshold", + "0x0000000000000000000000000000000000000000000000000000000000010000", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the felonyThreshold out of range"; + }); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "dues"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "felonyThreshold", + "0x0000000000000000000000000000000000000000000000000000000000000010", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the felonyThreshold out of range"; + }); - let dues = await relayerHub.dues.call(); - assert.equal(dues.toString(), "26213023705160744960", "value not equal"); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "misdemeanorThreshold", + "0x00000000000000000000000000000000000000000000000000000000000000f0", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "misdemeanorThreshold"; + }); + let misdemeanorThreshold = await slashIndicator.misdemeanorThreshold.call(); + assert.equal(misdemeanorThreshold.toNumber(), 240, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "misdemeanorThreshold", + "0x0000000000000000000000000000000000000000000000000000000000000000", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the misdemeanorThreshold out of range"; + }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "misdemeanorThreshold", + "0x0000000000000000000000000000000000000000000000000000000000010001", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the misdemeanorThreshold out of range"; }); - it('Gov relayerIncentivize', async () => { - const govHubInstance = await GovHub.deployed(); - const relayerIncentivize =await RelayerIncentivize.deployed(); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "finalityDistance", + "0x000000000000000000000000000000000000000000000000000000000000000f", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "finalityDistance"; + }); + let finalityDistance = await slashIndicator.finalityDistance.call(); + assert.equal(finalityDistance.toNumber(), 15, "value not equal"); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "finalitySlashRewardRatio", + "0x0000000000000000000000000000000000000000000000000000000000000032", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "finalitySlashRewardRatio"; + }); + let finalitySlashRewardRatio = await slashIndicator.finalitySlashRewardRatio.call(); + assert.equal(finalitySlashRewardRatio.toNumber(), 50, "value not equal"); + }); + + it("Gov SystemReward", async () => { + const govHubInstance = await GovHub.deployed(); + const systemReward = await SystemReward.deployed(); + const validatorSet = await BSCValidatorSet.deployed(); + const slash = await SlashIndicator.deployed(); + const lightClient = await MockLightClient.deployed(); + const tokenHub = await TokenHub.deployed(); + const relayer = await RelayerIncentivize.deployed(); + const relayerHub = await RelayerHub.deployed(); + const govHub = await GovHub.deployed(); + const tokenManager = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + + await systemReward.updateContractAddr( + validatorSet.address, + slash.address, + systemReward.address, + lightClient.address, + tokenHub.address, + relayer.address, + relayerHub.address, + govHub.address, + tokenManager.address, + crossChain.address + ); + + const relayerAccount = accounts[8]; + let newOperator = web3.eth.accounts.create(); + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("updateOperator", accounts[4], systemReward.address), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "updateOperator"; + }); - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateMolecule", "0x000000000000000000000000000000000000000000000000000000000000000f", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { - return ev.key === "headerRelayerRewardRateMolecule"; - }); + await systemReward.send(1e8, { from: accounts[3] }); + tx = await systemReward.claimRewards(newOperator.address, 1e7, { from: accounts[4] }); + truffleAssert.eventEmitted(tx, "rewardTo", (ev) => { + return ev.amount.toNumber() === 1e7 && ev.to === newOperator.address; + }); - let headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); - assert.equal(headerRelayerRewardRateMolecule.toNumber(), 1, "value not equal"); + let balance_wei = await web3.eth.getBalance(newOperator.address); + assert.equal(balance_wei, 1e7, "balance not equal"); + }); + + it("Gov others failed", async () => { + const govHubInstance = await GovHub.deployed(); + const bSCValidatorSetInstance = await BSCValidatorSet.deployed(); + const migrationInstance = await Migration.deployed(); + const relayerAccount = accounts[8]; + + // unknown key + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "unknown key", + "0x0000000000000000000000000000000000000000000000000000000000010000", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "unknown param"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // exceed range key + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x000000000000010000000000000000000000000000000000000000000000000", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the expireTimeSecondGap is out of range"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // length mismatch + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("expireTimeSecondGap", "0x10000", bSCValidatorSetInstance.address), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "length of expireTimeSecondGap mismatch"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // address do not exist + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x1110000000000000000000000000000000001004" + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the target is not a contract"; + }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateMolecule", "0x0000000000000000000000000000000000000000000000000000000000000002", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "headerRelayerRewardRateMolecule"; - }); - - headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); - assert.equal(headerRelayerRewardRateMolecule.toNumber(), 2, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateDenominator", "0x0000000000000000000000000000000000000000000000000000000000000001", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { - return ev.key === "headerRelayerRewardRateDenominator"; - }); - - let headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); - assert.equal(headerRelayerRewardRateDenominator.toNumber(), 5, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateDenominator", "0x0000000000000000000000000000000000000000000000000000000000000004", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "headerRelayerRewardRateDenominator"; - }); - - headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); - assert.equal(headerRelayerRewardRateDenominator.toNumber(), 4, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationMolecule", "0x0000000000000000000000000000000000000000000000000000000000000064", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { - return ev.key === "callerCompensationMolecule"; - }); - - let callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); - assert.equal(callerCompensationMolecule.toNumber(), 1, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationMolecule", "0x0000000000000000000000000000000000000000000000000000000000000010", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "callerCompensationMolecule"; - }); - - callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); - assert.equal(callerCompensationMolecule.toNumber(), 16, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationDenominator", "0x000000000000000000000000000000000000000000000000000000000000000f", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { - return ev.key === "callerCompensationDenominator"; - }); - - let callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); - assert.equal(callerCompensationDenominator.toNumber(), 80, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationDenominator", "0x0000000000000000000000000000000000000000000000000000000000000020", RelayerIncentivize.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "callerCompensationDenominator"; - }); - - callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); - assert.equal(callerCompensationDenominator.toNumber(), 32, "value not equal"); - }); - - it('Gov cross chain contract', async () => { - const govHubInstance = await GovHub.deployed(); - const crossChainInstance =await CrossChain.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("addOrUpdateChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00")), Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address))])), crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'addOrUpdateChannel'; - }); - - await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("addOrUpdateChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00")), Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address))])), crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'addOrUpdateChannel'; - }); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00"))])), crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'enableOrDisableChannel'; - }); - - let isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); - assert.equal(isChannelEnable, false, "channel should be disabled"); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); - assert.equal(isChannelEnable, true, "channel should be enabled"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x01"))])), crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'enableOrDisableChannel'; - }); - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00"))])), crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'enableOrDisableChannel'; - }); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); - assert.equal(isChannelEnable, true, "channel should be enabled"); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); - assert.equal(isChannelEnable, false, "channel should be disabled"); - - let appAddr = await crossChainInstance.channelHandlerContractMap.call(0x57); - assert.equal(appAddr, RelayerIncentivize.address, "value not equal"); - let fromSys = await crossChainInstance.isRelayRewardFromSystemReward.call(0x57); - assert.equal(fromSys, true, "should from system reward"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("batchSizeForOracle", "0x0000000000000000000000000000000000000000000000000000000000000064", crossChainInstance.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === 'batchSizeForOracle'; - }); - let batchSizeForOracle = await crossChainInstance.batchSizeForOracle.call(); - assert.equal(batchSizeForOracle, 100, "value not equal"); - }); - - - it('Gov SlashIndicator', async () => { - const govHubInstance = await GovHub.deployed(); - const slashIndicator =await SlashIndicator.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000000100", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "felonyThreshold"; - }); - let felonyThreshold = await slashIndicator.felonyThreshold.call(); - assert.equal(felonyThreshold.toNumber(), 256, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000010000", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the felonyThreshold out of range"; - }); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000000010", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the felonyThreshold out of range"; - }); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x00000000000000000000000000000000000000000000000000000000000000f0", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "paramChange",(ev) => { - return ev.key === "misdemeanorThreshold"; - }); - let misdemeanorThreshold = await slashIndicator.misdemeanorThreshold.call(); - assert.equal(misdemeanorThreshold.toNumber(), 240, "value not equal"); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x0000000000000000000000000000000000000000000000000000000000000000", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the misdemeanorThreshold out of range"; - }); - - tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x0000000000000000000000000000000000000000000000000000000000010001", slashIndicator.address), - {from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { - return ev.message === "the misdemeanorThreshold out of range"; - }); + // method do no exist + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x0000000000000000000000000000000000000000000000000000000000000000", + migrationInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithBytes", (ev) => { + return ev.message === null; }); + }); }); -function serialize(key,value, target,extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if(extra != null){ - pkg.push(extra); - } - return RLP.encode(pkg); +function serialize(key, value, target, extra) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if (extra != null) { + pkg.push(extra); + } + return RLP.encode(pkg); } diff --git a/test/RelayerHub.js b/test/RelayerHub.js index a8509d4c..d8cb88af 100644 --- a/test/RelayerHub.js +++ b/test/RelayerHub.js @@ -1,71 +1,79 @@ const RelayerHub = artifacts.require("RelayerHub"); const SystemReward = artifacts.require("SystemReward"); -const Web3 = require('web3'); -const truffleAssert = require('truffle-assertions'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const Web3 = require("web3"); +const truffleAssert = require("truffle-assertions"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); -contract('RelayerHub', (accounts) => { - it('register and unregister success', async () => { +contract("RelayerHub", (accounts) => { + it("register and unregister success", async () => { const relayerInstance = await RelayerHub.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let tx =await relayerInstance.register({from: accounts[3],value: 1e20}); + let tx = await relayerInstance.register({ from: accounts[3], value: 1e20 }); truffleAssert.eventEmitted(tx, "relayerRegister"); let res = await relayerInstance.isRelayer.call(accounts[3]); - assert.equal(res,true); + assert.equal(res, true); let balanceBefore = await web3.eth.getBalance(accounts[3]); let systemRewardBefore = await web3.eth.getBalance(systemRewardInstance.address); - tx =await relayerInstance.unregister({from: accounts[3]}); + tx = await relayerInstance.unregister({ from: accounts[3] }); truffleAssert.eventEmitted(tx, "relayerUnRegister"); res = await relayerInstance.isRelayer.call(accounts[3]); - assert.equal(res,false); + assert.equal(res, false); let balanceAfter = await web3.eth.getBalance(accounts[3]); - assert.equal(res,false); + assert.equal(res, false); let deposit = await relayerInstance.requiredDeposit.call(); let dues = await relayerInstance.dues.call(); - assert.equal(web3.utils.toBN(balanceAfter).sub(web3.utils.toBN(balanceBefore)).add(web3.utils.toBN(2e10).mul(web3.utils.toBN(tx.receipt.gasUsed))).toString(), deposit.sub(dues).toString()); + assert.equal( + web3.utils + .toBN(balanceAfter) + .sub(web3.utils.toBN(balanceBefore)) + .add(web3.utils.toBN(2e10).mul(web3.utils.toBN(tx.receipt.gasUsed))) + .toString(), + deposit.sub(dues).toString() + ); let systemRewardAfter = await web3.eth.getBalance(systemRewardInstance.address); - assert.equal(web3.utils.toBN(systemRewardAfter).sub(web3.utils.toBN(systemRewardBefore)).toString(), web3.utils.toBN(1e17).toString()) + assert.equal( + web3.utils.toBN(systemRewardAfter).sub(web3.utils.toBN(systemRewardBefore)).toString(), + web3.utils.toBN(1e17).toString() + ); }); - it('fail to register', async () => { + it("fail to register", async () => { const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: accounts[3],value: 1e20}); - // reregister + await relayerInstance.register({ from: accounts[3], value: 1e20 }); + // re-register try { - await relayerInstance.register({from: accounts[3],value: 1e20}); + await relayerInstance.register({ from: accounts[3], value: 1e20 }); assert.fail(); } catch (error) { assert.ok(error.toString().includes("relayer already exist")); } - await relayerInstance.unregister({from: accounts[3]}); + await relayerInstance.unregister({ from: accounts[3] }); try { - await relayerInstance.unregister({from: accounts[3]}); + await relayerInstance.unregister({ from: accounts[3] }); assert.fail(); } catch (error) { assert.ok(error.toString().includes("relayer do not exist")); } try { - await relayerInstance.register({from: accounts[4],value: 2e20}); + await relayerInstance.register({ from: accounts[4], value: 2e20 }); assert.fail(); } catch (error) { assert.ok(error.toString().includes("deposit value is not exactly the same")); } try { - await relayerInstance.register({from: accounts[4],value: 1e10}); + await relayerInstance.register({ from: accounts[4], value: 1e10 }); assert.fail(); } catch (error) { assert.ok(error.toString().includes("deposit value is not exactly the same")); } - }); }); - diff --git a/test/Slash.js b/test/Slash.js index a1a6342b..9a4ed158 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -1,88 +1,89 @@ const SlashIndicator = artifacts.require("SlashIndicator"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); -const Web3 = require('web3'); -const crypto = require('crypto'); -const RLP = require('rlp'); +const Web3 = require("web3"); +const crypto = require("crypto"); +const RLP = require("rlp"); const SystemReward = artifacts.require("SystemReward"); -const truffleAssert = require('truffle-assertions'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const truffleAssert = require("truffle-assertions"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); const STAKE_CHANNEL_ID = 0x08; -contract('SlashIndicator', (accounts) => { - it('slash success', async () => { +contract("SlashIndicator", (accounts) => { + it("slash success", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); const accountOne = accounts[0]; - let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; let validatorAccount = validatorAccounts[0]; - for (let i =1; i<10; i++){ + for (let i = 1; i < 10; i++) { await slashInstance.slash(validatorAccount, { from: accountOne }); - let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); - let count =res[1].toNumber(); + let res = await slashInstance.getSlashIndicator.call(validatorAccount); + let count = res[1].toNumber(); assert.equal(count, i, "slash num is not correct"); } }); - it('slash from no system account', async () => { + it("slash from no system account", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); const nonSystemAccount = accounts[1]; - let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; let validatorAccount = validatorAccounts[0]; // first slash - try{ + try { await slashInstance.slash(validatorAccount, { from: nonSystemAccount }); assert.fail(); - }catch (error) { - assert.ok(error.toString().includes("the message sender must be the block producer"), "slash from no system account should not be ok"); + } catch (error) { + assert.ok( + error.toString().includes("the message sender must be the block producer"), + "slash from no system account should not be ok" + ); } }); }); -contract('SlashIndicator: isOperator works', (accounts) => { - it('isOperator works', async () => { +contract("SlashIndicator: isOperator works", (accounts) => { + it("isOperator works", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); const accountOne = accounts[0]; - let validatorAccounts = await validatorInstance.getMiningValidators.call(); + let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; let validatorAccount = validatorAccounts[0]; // slash afterward - for (let i =1; i<10; i++){ + for (let i = 1; i < 10; i++) { await slashInstance.slash(validatorAccount, { from: accountOne }); - let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); - let count =res[1].toNumber(); + let res = await slashInstance.getSlashIndicator.call(validatorAccount); + let count = res[1].toNumber(); assert.equal(count, i, "slash num is not correct for validator"); } }); }); +contract("SlashIndicator: catch emit event", (accounts) => { + it("catch emit event", async () => { + const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); -contract('SlashIndicator: catch emit event', (accounts) => { - it('catch emit event', async () => { - const slashInstance = await SlashIndicator.deployed(); - const validatorInstance = await BSCValidatorSet.deployed(); - - const accountOne = accounts[0]; - let validatorAccounts = await validatorInstance.getMiningValidators.call(); - let validatorAccount = validatorAccounts[0]; - for (let i =1; i<50; i++){ - let tx = await slashInstance.slash(validatorAccount, { from: accountOne }); - truffleAssert.eventEmitted(tx, "validatorSlashed",(ev) => { - return ev.validator === validatorAccount; - }); - } - }); + const accountOne = accounts[0]; + let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; + let validatorAccount = validatorAccounts[0]; + for (let i = 1; i < 50; i++) { + let tx = await slashInstance.slash(validatorAccount, { from: accountOne }); + truffleAssert.eventEmitted(tx, "validatorSlashed", (ev) => { + return ev.validator === validatorAccount; + }); + } + }); }); - -contract('SlashIndicator', (accounts) => { - it('trigger misdemeanor', async () => { +contract("SlashIndicator", (accounts) => { + it("trigger misdemeanor", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -92,71 +93,72 @@ contract('SlashIndicator', (accounts) => { let secondValidator = accounts[1]; let thirdValidator = accounts[2]; - await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e18 }); - await systemRewardInstance.addOperator(validatorSetInstance.address, {from: systemAccount}); + await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e18 }); + await systemRewardInstance.addOperator(validatorSetInstance.address, { from: systemAccount }); let amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); - for (let i =1; i<=50; i++){ + for (let i = 1; i <= 50; i++) { await slashInstance.slash(validator, { from: systemAccount }); } amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(), 0); - let packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], - [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); + let packageBytes = validatorUpdateRlpEncode( + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); - await validatorSetInstance.deposit(validator, {from: systemAccount, value: 2e18 }); + await validatorSetInstance.deposit(validator, { from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) - for (let i =1; i<=4; i++){ + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); + for (let i = 1; i <= 4; i++) { await slashInstance.slash(validator, { from: systemAccount }); } - let res= (await slashInstance.getSlashIndicator.call(validator)); - assert.equal(res[1].toNumber(),50); + let res = await slashInstance.getSlashIndicator.call(validator); + assert.equal(res[1].toNumber(), 50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(), 0); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); - - await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 1e18 }); + await validatorSetInstance.deposit(secondValidator, { from: systemAccount, value: 1e18 }); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) - for (let i =1; i<=50; i++){ + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); + for (let i = 1; i <= 50; i++) { await slashInstance.slash(secondValidator, { from: systemAccount }); } - res= (await slashInstance.getSlashIndicator.call(secondValidator)); - assert.equal(res[1].toNumber(),50); + res = await slashInstance.getSlashIndicator.call(secondValidator); + assert.equal(res[1].toNumber(), 50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toNumber(),0); + assert.equal(amount.toNumber(), 0); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); - for (let i =1; i<=50; i++){ + for (let i = 1; i <= 50; i++) { await slashInstance.slash(thirdValidator, { from: systemAccount }); } - res= (await slashInstance.getSlashIndicator.call(thirdValidator)); - assert.equal(res[1].toNumber(),50); + res = await slashInstance.getSlashIndicator.call(thirdValidator); + assert.equal(res[1].toNumber(), 50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toNumber(),0); - + assert.equal(amount.toNumber(), 0); }); }); -contract('felony SlashIndicator', (accounts) => { - it('trigger felony ', async () => { +contract("felony SlashIndicator", (accounts) => { + it("trigger felony ", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); @@ -165,83 +167,91 @@ contract('felony SlashIndicator', (accounts) => { let secondValidator = accounts[1]; let thirdValidator = accounts[2]; - let packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], - [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); + let packageBytes = validatorUpdateRlpEncode( + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); - await validatorSetInstance.deposit(validator, {from: systemAccount, value: 2e18 }); + await validatorSetInstance.deposit(validator, { from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case1: incoming of account1 is wrong") - for (let i =1; i<=150; i++){ + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case1: incoming of account1 is wrong"); + for (let i = 1; i <= 150; i++) { await slashInstance.slash(validator, { from: systemAccount }); } - let res= (await slashInstance.getSlashIndicator.call(validator)); - assert.equal(res[1].toNumber(),0, "case1: slash indicator of account1 is wrong"); + let res = await slashInstance.getSlashIndicator.call(validator); + assert.equal(res[1].toNumber(), 0, "case1: slash indicator of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(),0, "case1: incoming of account1 is wrong"); + assert.equal(amount.toNumber(), 0, "case1: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account2 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case1: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account3 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case1: incoming of account3 is wrong"); let consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length,2, "case1: length of validators should be 2"); - assert.equal(consensusAddress[0],secondValidator, "case1: index 0 of validators should be account2"); - assert.equal(consensusAddress[1],thirdValidator, "case1: index 1 of validators should be account3"); - - packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], - [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); - - await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 2e18 }); + assert.equal(consensusAddress.length, 2, "case1: length of validators should be 2"); + assert.equal(consensusAddress[0], secondValidator, "case1: index 0 of validators should be account2"); + assert.equal(consensusAddress[1], thirdValidator, "case1: index 1 of validators should be account3"); + + packageBytes = validatorUpdateRlpEncode( + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); + + await validatorSetInstance.deposit(secondValidator, { from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case2: incoming of account2 is wrong") - for (let i =1; i<=150; i++){ + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case2: incoming of account2 is wrong"); + for (let i = 1; i <= 150; i++) { await slashInstance.slash(secondValidator, { from: systemAccount }); } - res= (await slashInstance.getSlashIndicator.call(secondValidator)); - assert.equal(res[1].toNumber(),0, "case2: slash indicator of account2 is wrong"); + res = await slashInstance.getSlashIndicator.call(secondValidator); + assert.equal(res[1].toNumber(), 0, "case2: slash indicator of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toNumber(),0, "case2: incoming of account2 is wrong"); + assert.equal(amount.toNumber(), 0, "case2: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account1 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case2: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account3 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case2: incoming of account3 is wrong"); consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length,2, "case2: length of validators should be 2"); - assert.equal(consensusAddress[0],validator, "case2: index 0 of validators should be account1"); - assert.equal(consensusAddress[1],thirdValidator, "case2: index 1 of validators should be account3"); - - packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], - [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); - - await validatorSetInstance.deposit(thirdValidator, {from: systemAccount, value: 2e18 }); + assert.equal(consensusAddress.length, 2, "case2: length of validators should be 2"); + assert.equal(consensusAddress[0], validator, "case2: index 0 of validators should be account1"); + assert.equal(consensusAddress[1], thirdValidator, "case2: index 1 of validators should be account3"); + + packageBytes = validatorUpdateRlpEncode( + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator], + [validator, secondValidator, thirdValidator] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); + + await validatorSetInstance.deposit(thirdValidator, { from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case3: incoming of account3 is wrong") - for (let i =1; i<=150; i++){ + assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case3: incoming of account3 is wrong"); + for (let i = 1; i <= 150; i++) { await slashInstance.slash(thirdValidator, { from: systemAccount }); } - res= (await slashInstance.getSlashIndicator.call(thirdValidator)); - assert.equal(res[1].toNumber(),0, "case3: slash indicator of account3 is wrong"); + res = await slashInstance.getSlashIndicator.call(thirdValidator); + assert.equal(res[1].toNumber(), 0, "case3: slash indicator of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toNumber(),0, "case3: incoming of account3 is wrong"); + assert.equal(amount.toNumber(), 0, "case3: incoming of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account1 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case3: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account2 is wrong"); + assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case3: incoming of account2 is wrong"); consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length,2, "case3: length of validators should be 2"); - assert.equal(consensusAddress[0],validator, "case3: index 0 of validators should be account1"); - assert.equal(consensusAddress[1],secondValidator, "case3: index 0 of validators should be account2"); - + assert.equal(consensusAddress.length, 2, "case3: length of validators should be 2"); + assert.equal(consensusAddress[0], validator, "case3: index 0 of validators should be account1"); + assert.equal(consensusAddress[1], secondValidator, "case3: index 0 of validators should be account2"); }); }); -contract('Clean SlashIndicator', (accounts) => { - it('test slash clean', async () => { +contract("Clean SlashIndicator", (accounts) => { + it("test slash clean", async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); let newValidator = web3.eth.accounts.create(); @@ -250,100 +260,217 @@ contract('Clean SlashIndicator', (accounts) => { // case 1: all clean. let validators = []; - for(let i =0;i <20; i++){ + for (let i = 0; i < 20; i++) { validators.push(web3.eth.accounts.create().address); } // Do init - let packageBytes = validatorUpdateRlpEncode(validators, - validators,validators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + let packageBytes = validatorUpdateRlpEncode(validators, validators, validators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); - for(let i =0;i <20;i++){ + for (let i = 0; i < 20; i++) { await slashInstance.slash(validators[i], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); - let res= (await slashInstance.getSlashValidators.call()); + let res = await slashInstance.getSlashValidators.call(); assert.equal(res.length, 0); - for(let i =0;i <20;i++){ + for (let i = 0; i < 20; i++) { let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count =res[1].toNumber(); + let count = res[1].toNumber(); let height = res[0].toNumber(); assert.equal(count, 0); assert.equal(height, 0); } // case 2: all stay. - for(let i =0;i <20;i++){ - for(let j=0;j<5;j++){ + for (let i = 0; i < 20; i++) { + for (let j = 0; j < 5; j++) { await slashInstance.slash(validators[i], { from: accountOne }); } } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - res= (await slashInstance.getSlashValidators.call()); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); + res = await slashInstance.getSlashValidators.call(); assert.equal(res.length, 20); - for(let i =0;i <20;i++){ + for (let i = 0; i < 20; i++) { let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count =res[1].toNumber(); + let count = res[1].toNumber(); assert.equal(count, 1); } // case 3: partial stay. - for(let i =0;i <10;i++){ - for(let j=0;j<5;j++){ - await slashInstance.slash(validators[2*i], { from: accountOne }); + for (let i = 0; i < 10; i++) { + for (let j = 0; j < 5; j++) { + await slashInstance.slash(validators[2 * i], { from: accountOne }); } - await slashInstance.slash(validators[2*i+1], { from: accountOne }); + await slashInstance.slash(validators[2 * i + 1], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - res= (await slashInstance.getSlashValidators.call()); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); + res = await slashInstance.getSlashValidators.call(); assert.equal(res.length, 10); - for(let i =0;i <20;i++){ + for (let i = 0; i < 20; i++) { let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count =res[1].toNumber(); - if(i%2==0){ + let count = res[1].toNumber(); + if (i % 2 == 0) { assert.equal(count, 2); - }else{ + } else { assert.equal(count, 0); } } // case 4: partial stay. - for(let i =0;i <10;i++){ - for(let j=0;j<5;j++){ - await slashInstance.slash(validators[2*i+1], { from: accountOne }); + for (let i = 0; i < 10; i++) { + for (let j = 0; j < 5; j++) { + await slashInstance.slash(validators[2 * i + 1], { from: accountOne }); } - await slashInstance.slash(validators[2*i], { from: accountOne }); + await slashInstance.slash(validators[2 * i], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - res= (await slashInstance.getSlashValidators.call()); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); + res = await slashInstance.getSlashValidators.call(); assert.equal(res.length, 10); - for(let i =0;i <20;i++){ + for (let i = 0; i < 20; i++) { let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count =res[1].toNumber(); - if(i%2==0){ + let count = res[1].toNumber(); + if (i % 2 == 0) { assert.equal(count, 0); - }else{ + } else { assert.equal(count, 1); } } - }); }); +contract("finality slash SlashIndicator", (accounts) => { + it("valid finality evidence", async () => { + const slashInstance = await SlashIndicator.deployed(); + const systemRewardInstance = await SystemReward.deployed(); + let relayerAccount = accounts[8]; + + await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.addOperator(slashInstance.address); + + let currentNumber = await web3.eth.getBlockNumber(); + let blockNumberA = currentNumber - 5; + let blockHashA = await web3.eth.getBlock(blockNumberA).then((x) => { + return x.hash; + }); + + let evidence = { + numA: blockNumberA, + headerA: blockHashA, + sigA: Buffer.from("sigA"), + numB: currentNumber - 10, + headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigB: Buffer.from("sigB"), + valAddr: accounts[0], + }; + + let tx = await slashInstance.submitFinalityViolationEvidence(evidence, { + from: relayerAccount, + }); + truffleAssert.eventEmitted(tx, "validatorSlashed", (ev) => { + return ev.validator === accounts[0]; + }); + }); + + it("invalid finality evidence", async () => { + const slashInstance = await SlashIndicator.deployed(); + let relayerAccount = accounts[8]; + + let currentNumber = await web3.eth.getBlockNumber(); + let blockNumberA = currentNumber - 5; + let blockHashA = await web3.eth.getBlock(blockNumberA).then((x) => { + return x.hash; + }); + let evidence1 = { + numA: blockNumberA, + headerA: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigA: Buffer.from("sigA"), + numB: currentNumber - 10, + headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigB: Buffer.from("sigB"), + valAddr: accounts[0], + }; + let evidence2 = { + numA: blockNumberA, + headerA: blockHashA, + sigA: Buffer.from("sigA"), + numB: blockNumberA - 15, + headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigB: Buffer.from("sigB"), + valAddr: accounts[0], + }; + let evidence3 = { + numA: blockNumberA, + headerA: blockHashA, + sigA: Buffer.from("sigA"), + numB: currentNumber - 10, + headerB: await web3.eth.getBlock(currentNumber - 10).then((x) => { + return x.hash; + }), + sigB: Buffer.from("sigB"), + valAddr: accounts[0], + }; + let evidence4 = { + numA: currentNumber - 257, + headerA: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigA: Buffer.from("sigA"), + numB: currentNumber - 258, + headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", + sigB: Buffer.from("sigB"), + valAddr: accounts[0], + }; + + try { + await slashInstance.submitFinalityViolationEvidence(evidence1, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("neither header is in local fork"), + "two headers from other fork should not be ok" + ); + } + try { + await slashInstance.submitFinalityViolationEvidence(evidence2, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("too long distance between blocks"), + "two blocks' number larger than 11 should not be ok" + ); + } + try { + await slashInstance.submitFinalityViolationEvidence(evidence3, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("both headers are in local fork"), + "two headers from one fork should not be ok" + ); + } + try { + await slashInstance.submitFinalityViolationEvidence(evidence4, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("block number out of range"), + "256 block before current height should not be ok" + ); + } + }); +}); -function validatorUpdateRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) { +function validatorUpdateRlpEncode(consensusAddrList, feeAddrList, bscFeeAddrList) { let pkg = []; pkg.push(0x00); let n = consensusAddrList.length; let vals = []; - for(let i = 0;i { - it('receive token success', async () => { +contract("SystemReward", (accounts) => { + it("receive token success", async () => { const systemRewardInstance = await SystemReward.deployed(); - let tx = await systemRewardInstance.send(1e8, {from: accounts[3]}); + let tx = await systemRewardInstance.send(1e8, { from: accounts[3] }); let balance_wei = await web3.eth.getBalance(systemRewardInstance.address); assert.equal(balance_wei, 1e8, "balance not equal"); - truffleAssert.eventEmitted(tx, "receiveDeposit",(ev) => { + truffleAssert.eventEmitted(tx, "receiveDeposit", (ev) => { return ev.amount.toNumber() === 1e8 && ev.from === accounts[3]; }); }); - it('isOperator works', async () => { + it("isOperator works", async () => { const systemRewardInstance = await SystemReward.deployed(); let res = await systemRewardInstance.isOperator.call(accounts[0]); assert.ok(res, "accounts[0] should be operator"); @@ -28,15 +28,16 @@ contract('SystemReward', (accounts) => { assert.ok(!res, "accounts[4] should not be operator"); }); - - it('claim reward success', async () => { + it("claim reward success", async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); - await systemRewardInstance.send(1e8, {from: accounts[3]}); - let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, {from: accounts[0]}) + await systemRewardInstance.send(1e8, { from: accounts[3] }); + let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, { + from: accounts[0], + }); - truffleAssert.eventEmitted(tx, "rewardTo",(ev) => { + truffleAssert.eventEmitted(tx, "rewardTo", (ev) => { return ev.amount.toNumber() === 1e7 && ev.to === newAccount.address; }); @@ -44,26 +45,25 @@ contract('SystemReward', (accounts) => { assert.equal(balance_wei, 1e7, "balance not equal"); }); - it('claim reward failed', async () => { + it("claim reward failed", async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); - await systemRewardInstance.send(1e8, {from: accounts[3]}); - try{ - await systemRewardInstance.claimRewards(newAccount.address, 1e7, {from: accounts[3]}) - assert.fail(); - }catch (error) { - assert.ok(error.toString().includes("only operator is allowed to call the method")); - } + await systemRewardInstance.send(1e8, { from: accounts[3] }); + let amount = await systemRewardInstance.claimRewards.call(newAccount.address, 1e7, { + from: accounts[3], + }); + assert.equal(amount, 0, "the claim amount should be zero"); }); }); -contract('SystemReward', (accounts) => { - - it('claim empty reward', async () => { +contract("SystemReward", (accounts) => { + it("claim empty reward", async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); - let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, {from: accounts[0]}) + let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, { + from: accounts[0], + }); truffleAssert.eventEmitted(tx, "rewardEmpty"); let balance_wei = await web3.eth.getBalance(newAccount.address); assert.equal(balance_wei, 0, "balance not equal"); diff --git a/test/TestRelayerIncentivize.js b/test/TestRelayerIncentivize.js index 426d787d..efc80661 100644 --- a/test/TestRelayerIncentivize.js +++ b/test/TestRelayerIncentivize.js @@ -5,360 +5,468 @@ const MockLightClient = artifacts.require("mock/MockLightClient"); const TokenHub = artifacts.require("TokenHub"); const TokenManager = artifacts.require("TokenManager"); const CrossChain = artifacts.require("CrossChain"); -const ABCToken = artifacts.require("ABCToken"); -const DEFToken = artifacts.require("DEFToken"); -const XYZToken = artifacts.require("test/XYZToken"); -const MiniToken = artifacts.require("test/MiniToken"); -const MaliciousToken = artifacts.require("test/MaliciousToken"); const RelayerHub = artifacts.require("RelayerHub"); const GovHub = artifacts.require("GovHub"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); const SlashIndicator = artifacts.require("SlashIndicator"); -const Web3 = require('web3'); -const RLP = require('rlp'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const Web3 = require("web3"); +const RLP = require("rlp"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); const GOV_CHANNEL_ID = 0x09; const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; -function serialize(key,value, target,extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if(extra != null){ - pkg.push(extra); - } - return RLP.encode(pkg); +function serialize(key, value, target, extra) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if (extra != null) { + pkg.push(extra); + } + return RLP.encode(pkg); } function toBytes32String(input) { - let initialInputHexStr = web3.utils.toBN(input).toString(16); - const initialInputHexStrLength = initialInputHexStr.length; - - let inputHexStr = initialInputHexStr; - for (var i = 0; i < 64 - initialInputHexStrLength; i++) { - inputHexStr = '0' + inputHexStr; - } - return inputHexStr; + let initialInputHexStr = web3.utils.toBN(input).toString(16); + const initialInputHexStrLength = initialInputHexStr.length; + + let inputHexStr = initialInputHexStr; + for (let i = 0; i < 64 - initialInputHexStrLength; i++) { + inputHexStr = "0" + inputHexStr; + } + return inputHexStr; } function buildSyncPackagePrefix(syncRelayFee) { - return Buffer.from(web3.utils.hexToBytes( - "0x00" + toBytes32String(syncRelayFee) - )); + return Buffer.from(web3.utils.hexToBytes("0x00" + toBytes32String(syncRelayFee))); } -contract('RelayerIncentivize', (accounts) => { - it('init incentivize', async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const systemReward = await SystemReward.deployed(); - let uselessAddr = web3.eth.accounts.create().address; - - const systemRewardContract = await relayerIncentivize.SYSTEM_REWARD_ADDR.call(); - assert.equal(systemRewardContract, systemReward.address, "wrong system reward contract address"); - }); - it('header relayer incentivize', async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - - const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); - const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); - const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); - const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); - const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); - const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); - const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); - const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const roundSize = await relayerIncentivize.ROUND_SIZE.call(); - assert.equal(roundSize.toNumber(), 30, "wrong round size"); - const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); - assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); - - for(let i=0; i<1; i++){ - await relayerIncentivize.addReward(accounts[1], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<2; i++){ - await relayerIncentivize.addReward(accounts[2], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<3; i++){ - await relayerIncentivize.addReward(accounts[3], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<4; i++){ - await relayerIncentivize.addReward(accounts[4], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<5; i++){ - await relayerIncentivize.addReward(accounts[5], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<6; i++){ - await relayerIncentivize.addReward(accounts[6], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<7; i++){ - await relayerIncentivize.addReward(accounts[7], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - for(let i=0; i<2; i++){ - await relayerIncentivize.addReward(accounts[8], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 1, "wrong round sequence"); - - await relayerIncentivize.claimRelayerReward(accounts[1], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[2], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[3], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[4], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[5], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[6], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[7], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[8], {from: accounts[0]}); - - const newAccount1Balance = await web3.eth.getBalance(accounts[1]); - const newAccount2Balance = await web3.eth.getBalance(accounts[2]); - const newAccount3Balance = await web3.eth.getBalance(accounts[3]); - const newAccount4Balance = await web3.eth.getBalance(accounts[4]); - const newAccount5Balance = await web3.eth.getBalance(accounts[5]); - const newAccount6Balance = await web3.eth.getBalance(accounts[6]); - const newAccount7Balance = await web3.eth.getBalance(accounts[7]); - const newAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const rewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)); - const rewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)); - const rewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)); - const rewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)); - const rewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)); - const rewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)); - const rewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)); - const rewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)); - - assert.equal(rewardAccount1.lt(rewardAccount2), true, "wrong reward"); - assert.equal(rewardAccount2.lt(rewardAccount3), true, "wrong reward"); - assert.equal(rewardAccount3.eq(rewardAccount4), true, "wrong reward"); - assert.equal(rewardAccount4.eq(rewardAccount5), true, "wrong reward"); - assert.equal(rewardAccount5.eq(rewardAccount6), true, "wrong reward"); - assert.equal(rewardAccount6.eq(rewardAccount7), true, "wrong reward"); - assert.equal(rewardAccount8.eq(rewardAccount2), true, "wrong reward"); - - }); - it('transfer relayer Incentivize', async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - - const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); - const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); - const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); - const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); - const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); - const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); - const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); - const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const gasPriceStr = await web3.eth.getGasPrice(); - const gasPrice = web3.utils.toBN(gasPriceStr); - - let account1TxFee = web3.utils.toBN(0); - let account2TxFee = web3.utils.toBN(0); - let account3TxFee = web3.utils.toBN(0); - let account4TxFee = web3.utils.toBN(0); - let account5TxFee = web3.utils.toBN(0); - let account6TxFee = web3.utils.toBN(0); - let account7TxFee = web3.utils.toBN(0); - let account8TxFee = web3.utils.toBN(0); - - const tokenHub = accounts[9]; - - for(let i=0; i<1; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[1], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account1TxFee = account1TxFee.add(txFee) - } - for(let i=0; i<2; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[2], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account2TxFee = account2TxFee.add(txFee) - } - for(let i=0; i<3; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[3], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account3TxFee = account3TxFee.add(txFee) - } - for(let i=0; i<4; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[4], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account4TxFee = account4TxFee.add(txFee) - } - for(let i=0; i<5; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[5], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account5TxFee = account5TxFee.add(txFee) - } - for(let i=0; i<6; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[6], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account6TxFee = account6TxFee.add(txFee) - } - for(let i=0; i<7; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[7], web3.utils.toBN(1e16), false,{from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account7TxFee = account7TxFee.add(txFee) - } - for(let i=0; i<2; i++){ - let tx = await relayerIncentivize.addReward(accounts[0], accounts[8], web3.utils.toBN(1e16), false, {from: tokenHub}); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account8TxFee = account8TxFee.add(txFee) - } - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 2, "wrong round sequence"); - - await relayerIncentivize.claimRelayerReward(accounts[1], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[2], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[3], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[4], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[5], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[6], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[7], {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(accounts[8], {from: accounts[0]}); - - const newAccount1Balance = await web3.eth.getBalance(accounts[1]); - const newAccount2Balance = await web3.eth.getBalance(accounts[2]); - const newAccount3Balance = await web3.eth.getBalance(accounts[3]); - const newAccount4Balance = await web3.eth.getBalance(accounts[4]); - const newAccount5Balance = await web3.eth.getBalance(accounts[5]); - const newAccount6Balance = await web3.eth.getBalance(accounts[6]); - const newAccount7Balance = await web3.eth.getBalance(accounts[7]); - const newAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const pureRewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)).sub(account1TxFee); - const pureRewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)).sub(account2TxFee); - const pureRewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)).sub(account3TxFee); - const pureRewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)).sub(account4TxFee); - const pureRewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)).sub(account5TxFee); - const pureRewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)).sub(account6TxFee); - const pureRewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)).sub(account7TxFee); - const pureRewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)).sub(account8TxFee); - - assert.equal(pureRewardAccount1.lt(pureRewardAccount2), true, "wrong reward"); - assert.equal(pureRewardAccount2.lt(pureRewardAccount3), true, "wrong reward"); - assert.equal(pureRewardAccount3.gt(pureRewardAccount4), true, "wrong reward"); - assert.equal(pureRewardAccount4.gt(pureRewardAccount5), true, "wrong reward"); - assert.equal(pureRewardAccount5.gt(pureRewardAccount6), true, "wrong reward"); - assert.equal(pureRewardAccount6.gt(pureRewardAccount7), true, "wrong reward"); - assert.equal(pureRewardAccount8.gt(pureRewardAccount2), true, "wrong reward"); // get extra 1/80 of total reward - assert.equal(pureRewardAccount8.lt(pureRewardAccount3), true, "wrong reward"); // get extra 1/80 of total reward - }); - it('non-payable address', async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const tendermintLightClient = await TendermintLightClient.deployed(); - - const tokenHub = accounts[9]; - const relayer = accounts[0]; - - for(let i=0; i<15; i++){ - await relayerIncentivize.addReward(tendermintLightClient.address, relayer, web3.utils.toBN(1e16), false, {from: tokenHub}); - } - - for(let i=0; i<14; i++){ - await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), false, {from: tokenHub}); - } - - const systemReward = await SystemReward.deployed(); - const originSystemRewardBalance = await web3.eth.getBalance(systemReward.address); +contract("RelayerIncentivize", (accounts) => { + it("init incentivize", async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const systemReward = await SystemReward.deployed(); + + const systemRewardContract = await relayerIncentivize.SYSTEM_REWARD_ADDR.call(); + assert.equal(systemRewardContract, systemReward.address, "wrong system reward contract address"); + }); + it("header relayer incentivize", async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + + const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); + const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); + const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); + const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); + const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); + const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); + const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); + const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const roundSize = await relayerIncentivize.ROUND_SIZE.call(); + assert.equal(roundSize.toNumber(), 30, "wrong round size"); + const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); + assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); + + for (let i = 0; i < 1; i++) { + await relayerIncentivize.addReward(accounts[1], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 2; i++) { + await relayerIncentivize.addReward(accounts[2], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 3; i++) { + await relayerIncentivize.addReward(accounts[3], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 4; i++) { + await relayerIncentivize.addReward(accounts[4], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 5; i++) { + await relayerIncentivize.addReward(accounts[5], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 6; i++) { + await relayerIncentivize.addReward(accounts[6], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 7; i++) { + await relayerIncentivize.addReward(accounts[7], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } + for (let i = 0; i < 2; i++) { + await relayerIncentivize.addReward(accounts[8], accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } - await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), true, {from: tokenHub}); + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 1, "wrong round sequence"); + + await relayerIncentivize.claimRelayerReward(accounts[1], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[2], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[3], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[4], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[5], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[6], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[7], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[8], { from: accounts[0] }); + + const newAccount1Balance = await web3.eth.getBalance(accounts[1]); + const newAccount2Balance = await web3.eth.getBalance(accounts[2]); + const newAccount3Balance = await web3.eth.getBalance(accounts[3]); + const newAccount4Balance = await web3.eth.getBalance(accounts[4]); + const newAccount5Balance = await web3.eth.getBalance(accounts[5]); + const newAccount6Balance = await web3.eth.getBalance(accounts[6]); + const newAccount7Balance = await web3.eth.getBalance(accounts[7]); + const newAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const rewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)); + const rewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)); + const rewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)); + const rewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)); + const rewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)); + const rewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)); + const rewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)); + const rewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)); + + assert.equal(rewardAccount1.lt(rewardAccount2), true, "wrong reward"); + assert.equal(rewardAccount2.lt(rewardAccount3), true, "wrong reward"); + assert.equal(rewardAccount3.eq(rewardAccount4), true, "wrong reward"); + assert.equal(rewardAccount4.eq(rewardAccount5), true, "wrong reward"); + assert.equal(rewardAccount5.eq(rewardAccount6), true, "wrong reward"); + assert.equal(rewardAccount6.eq(rewardAccount7), true, "wrong reward"); + assert.equal(rewardAccount8.eq(rewardAccount2), true, "wrong reward"); + }); + it("transfer relayer Incentivize", async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + + const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); + const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); + const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); + const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); + const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); + const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); + const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); + const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const gasPriceStr = await web3.eth.getGasPrice(); + const gasPrice = web3.utils.toBN(gasPriceStr); + + let account1TxFee = web3.utils.toBN(0); + let account2TxFee = web3.utils.toBN(0); + let account3TxFee = web3.utils.toBN(0); + let account4TxFee = web3.utils.toBN(0); + let account5TxFee = web3.utils.toBN(0); + let account6TxFee = web3.utils.toBN(0); + let account7TxFee = web3.utils.toBN(0); + let account8TxFee = web3.utils.toBN(0); + + const tokenHub = accounts[9]; + + for (let i = 0; i < 1; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[1], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account1TxFee = account1TxFee.add(txFee); + } + for (let i = 0; i < 2; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[2], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account2TxFee = account2TxFee.add(txFee); + } + for (let i = 0; i < 3; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[3], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account3TxFee = account3TxFee.add(txFee); + } + for (let i = 0; i < 4; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[4], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account4TxFee = account4TxFee.add(txFee); + } + for (let i = 0; i < 5; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[5], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account5TxFee = account5TxFee.add(txFee); + } + for (let i = 0; i < 6; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[6], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account6TxFee = account6TxFee.add(txFee); + } + for (let i = 0; i < 7; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[7], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account7TxFee = account7TxFee.add(txFee); + } + for (let i = 0; i < 2; i++) { + let tx = await relayerIncentivize.addReward(accounts[0], accounts[8], web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account8TxFee = account8TxFee.add(txFee); + } + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 2, "wrong round sequence"); + + await relayerIncentivize.claimRelayerReward(accounts[1], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[2], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[3], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[4], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[5], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[6], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[7], { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(accounts[8], { from: accounts[0] }); + + const newAccount1Balance = await web3.eth.getBalance(accounts[1]); + const newAccount2Balance = await web3.eth.getBalance(accounts[2]); + const newAccount3Balance = await web3.eth.getBalance(accounts[3]); + const newAccount4Balance = await web3.eth.getBalance(accounts[4]); + const newAccount5Balance = await web3.eth.getBalance(accounts[5]); + const newAccount6Balance = await web3.eth.getBalance(accounts[6]); + const newAccount7Balance = await web3.eth.getBalance(accounts[7]); + const newAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const pureRewardAccount1 = web3.utils + .toBN(newAccount1Balance) + .sub(web3.utils.toBN(initialAccount1Balance)) + .sub(account1TxFee); + const pureRewardAccount2 = web3.utils + .toBN(newAccount2Balance) + .sub(web3.utils.toBN(initialAccount2Balance)) + .sub(account2TxFee); + const pureRewardAccount3 = web3.utils + .toBN(newAccount3Balance) + .sub(web3.utils.toBN(initialAccount3Balance)) + .sub(account3TxFee); + const pureRewardAccount4 = web3.utils + .toBN(newAccount4Balance) + .sub(web3.utils.toBN(initialAccount4Balance)) + .sub(account4TxFee); + const pureRewardAccount5 = web3.utils + .toBN(newAccount5Balance) + .sub(web3.utils.toBN(initialAccount5Balance)) + .sub(account5TxFee); + const pureRewardAccount6 = web3.utils + .toBN(newAccount6Balance) + .sub(web3.utils.toBN(initialAccount6Balance)) + .sub(account6TxFee); + const pureRewardAccount7 = web3.utils + .toBN(newAccount7Balance) + .sub(web3.utils.toBN(initialAccount7Balance)) + .sub(account7TxFee); + const pureRewardAccount8 = web3.utils + .toBN(newAccount8Balance) + .sub(web3.utils.toBN(initialAccount8Balance)) + .sub(account8TxFee); + + assert.equal(pureRewardAccount1.lt(pureRewardAccount2), true, "wrong reward"); + assert.equal(pureRewardAccount2.lt(pureRewardAccount3), true, "wrong reward"); + assert.equal(pureRewardAccount3.gt(pureRewardAccount4), true, "wrong reward"); + assert.equal(pureRewardAccount4.gt(pureRewardAccount5), true, "wrong reward"); + assert.equal(pureRewardAccount5.gt(pureRewardAccount6), true, "wrong reward"); + assert.equal(pureRewardAccount6.gt(pureRewardAccount7), true, "wrong reward"); + assert.equal(pureRewardAccount8.gt(pureRewardAccount2), true, "wrong reward"); // get extra 1/80 of total reward + assert.equal(pureRewardAccount8.lt(pureRewardAccount3), true, "wrong reward"); // get extra 1/80 of total reward + }); + it("non-payable address", async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const tendermintLightClient = await TendermintLightClient.deployed(); + + const tokenHub = accounts[9]; + const relayer = accounts[0]; + + for (let i = 0; i < 15; i++) { + await relayerIncentivize.addReward(tendermintLightClient.address, relayer, web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + } - await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); - await relayerIncentivize.claimRelayerReward(tendermintLightClient.address, {from: accounts[0]}); + for (let i = 0; i < 14; i++) { + await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), false, { + from: tokenHub, + }); + } - const newSystemRewardBalance = await web3.eth.getBalance(systemReward.address); - assert.equal(web3.utils.toBN(newSystemRewardBalance).sub(web3.utils.toBN(originSystemRewardBalance)).eq(web3.utils.toBN(146812500000000000)), true, "wrong amount to systemReward contract"); + const systemReward = await SystemReward.deployed(); + const originSystemRewardBalance = await web3.eth.getBalance(systemReward.address); - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 3, "wrong round sequence"); + await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), true, { + from: tokenHub, }); - it('dynamic extra incentive', async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const crossChain = await CrossChain.deployed(); - const govHub = await GovHub.deployed(); - const relayer = accounts[2]; - - const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); - - const initialAccount1Balance = await web3.eth.getBalance(relayer); - - const roundSize = await relayerIncentivize.ROUND_SIZE.call(); - assert.equal(roundSize.toNumber(), 30, "wrong round size"); - const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); - assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); - - for(let i=0; i<30; i++){ - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } - - await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); - - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 4, "wrong round sequence"); - - const newRelayerBalance1 = await web3.eth.getBalance(relayer); - const relayerReward1 = web3.utils.toBN(newRelayerBalance1).sub(web3.utils.toBN(initialAccount1Balance)); - - - for(let i=0; i<30; i++){ - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(2e16), false, {from: accounts[0]}); - } - - await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); - - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 5, "wrong round sequence"); - - const newRelayerBalance2 = await web3.eth.getBalance(relayer); - - const relayerReward2 = web3.utils.toBN(newRelayerBalance2).sub(web3.utils.toBN(newRelayerBalance1)); - assert.equal(relayerReward2.gt(relayerReward1), true, "relayerReward2 should be larger than relayerReward1"); + await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); + await relayerIncentivize.claimRelayerReward(tendermintLightClient.address, { from: accounts[0] }); + + const newSystemRewardBalance = await web3.eth.getBalance(systemReward.address); + assert.equal( + web3.utils + .toBN(newSystemRewardBalance) + .sub(web3.utils.toBN(originSystemRewardBalance)) + .eq(web3.utils.toBN(146812500000000000)), + true, + "wrong amount to systemReward contract" + ); + + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 3, "wrong round sequence"); + }); + it("dynamic extra incentive", async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + const relayer = accounts[2]; + + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({ from: relayer, value: 1e20 }); + + const initialAccount1Balance = await web3.eth.getBalance(relayer); + + const roundSize = await relayerIncentivize.ROUND_SIZE.call(); + assert.equal(roundSize.toNumber(), 30, "wrong round size"); + const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); + assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); + + for (let i = 0; i < 30; i++) { + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } - let dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); - assert.equal(web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(0)), true, "wrong dynamicExtraIncentiveAmount"); + await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, CrossChain.address); + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 4, "wrong round sequence"); - await web3.eth.sendTransaction({to:SystemReward.address, from:accounts[3], value: web3.utils.toWei("10", "ether")}); + const newRelayerBalance1 = await web3.eth.getBalance(relayer); - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x000000000000000000000000000000000000000000000000002386F26FC10000";// 1e16; - let govPackageBytes = serialize("dynamicExtraIncentiveAmount", govValue, RelayerIncentivize.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + const relayerReward1 = web3.utils.toBN(newRelayerBalance1).sub(web3.utils.toBN(initialAccount1Balance)); - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, accounts[8]); + for (let i = 0; i < 30; i++) { + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(2e16), false, { + from: accounts[0], + }); + } - dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); - assert.equal(web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(1e16)), true, "wrong dynamicExtraIncentiveAmount"); + await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); + + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 5, "wrong round sequence"); + + const newRelayerBalance2 = await web3.eth.getBalance(relayer); + + const relayerReward2 = web3.utils.toBN(newRelayerBalance2).sub(web3.utils.toBN(newRelayerBalance1)); + assert.equal(relayerReward2.gt(relayerReward1), true, "relayerReward2 should be larger than relayerReward1"); + + let dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); + assert.equal( + web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(0)), + true, + "wrong dynamicExtraIncentiveAmount" + ); + + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + MockLightClient.address, + TokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + CrossChain.address + ); + + await web3.eth.sendTransaction({ + to: SystemReward.address, + from: accounts[3], + value: web3.utils.toWei("10", "ether"), + }); - for(let i=0; i<29; i++){ - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x000000000000000000000000000000000000000000000000002386F26FC10000"; // 1e16; + let govPackageBytes = serialize("dynamicExtraIncentiveAmount", govValue, RelayerIncentivize.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + MockLightClient.address, + TokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + accounts[8] + ); + + dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); + assert.equal( + web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(1e16)), + true, + "wrong dynamicExtraIncentiveAmount" + ); + + for (let i = 0; i < 29; i++) { + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 6, "wrong round sequence"); + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 6, "wrong round sequence"); - await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); - const relayerBalanceBeforeReward3 = await web3.eth.getBalance(relayer); + const relayerBalanceBeforeReward3 = await web3.eth.getBalance(relayer); - for(let i=0; i<30; i++){ - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); - } + for (let i = 0; i < 30; i++) { + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { + from: accounts[0], + }); + } - await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 7, "wrong round sequence"); + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 7, "wrong round sequence"); - const newRelayerBalance3 = await web3.eth.getBalance(relayer); + const newRelayerBalance3 = await web3.eth.getBalance(relayer); - const relayerReward3 = web3.utils.toBN(newRelayerBalance3).sub(web3.utils.toBN(relayerBalanceBeforeReward3)); - assert.equal(relayerReward3.eq(relayerReward2), true, "relayerReward3 should equal to relayerReward2"); - }); + const relayerReward3 = web3.utils.toBN(newRelayerBalance3).sub(web3.utils.toBN(relayerBalanceBeforeReward3)); + assert.equal(relayerReward3.eq(relayerReward2), true, "relayerReward3 should equal to relayerReward2"); + }); }); diff --git a/test/TestTendermintLightClient.js b/test/TestTendermintLightClient.js index 04648b34..e18cd605 100644 --- a/test/TestTendermintLightClient.js +++ b/test/TestTendermintLightClient.js @@ -1,25 +1,18 @@ -const SystemReward = artifacts.require("SystemReward"); -const RelayerIncentivize = artifacts.require("RelayerIncentivize"); const TendermintLightClient = artifacts.require("TendermintLightClient"); -const MockRelayerHub = artifacts.require("mock/MockRelayerHub"); -const crypto = require('crypto'); -const Web3 = require('web3'); -const truffleAssert = require('truffle-assertions'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const Web3 = require("web3"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); -contract('TendermintLightClient', (accounts) => { - it('Init consensus state', async () => { - const lightClient = await TendermintLightClient.deployed(); +contract("TendermintLightClient", (accounts) => { + it("Init consensus state", async () => { + const lightClient = await TendermintLightClient.deployed(); - let uselessAddr = web3.eth.accounts.create().address; + let initialHeight = await lightClient.initialHeight.call(); + assert.equal(initialHeight.toNumber(), 2, "mismatched initial consensus height"); + const chainID = await lightClient.getChainID.call(); + assert.equal(chainID, "Binance-Chain-Nile", "mismatched chainID"); - let initialHeight = await lightClient.initialHeight.call(); - assert.equal(initialHeight.toNumber(), 2, "mismatched initial consensus height"); - const chainID = await lightClient.getChainID.call(); - assert.equal(chainID, "Binance-Chain-Nile", "mismatched chainID"); - - const isHeaderSynced = await lightClient.isHeaderSynced.call(2); - assert.equal(isHeaderSynced, true, "height already synced"); - }); + const isHeaderSynced = await lightClient.isHeaderSynced.call(2); + assert.equal(isHeaderSynced, true, "height already synced"); + }); }); diff --git a/test/TestTokenHub.js b/test/TestTokenHub.js index 8fe454e6..ea134106 100644 --- a/test/TestTokenHub.js +++ b/test/TestTokenHub.js @@ -1,6 +1,6 @@ -const BN = require('bn.js'); +const BN = require("bn.js"); const sleep = require("await-sleep"); -const RLP = require('rlp'); +const RLP = require("rlp"); const SystemReward = artifacts.require("SystemReward"); const RelayerIncentivize = artifacts.require("RelayerIncentivize"); @@ -19,10 +19,9 @@ const GovHub = artifacts.require("GovHub"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); const SlashIndicator = artifacts.require("SlashIndicator"); -const crypto = require('crypto'); -const Web3 = require('web3'); -const truffleAssert = require('truffle-assertions'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const Web3 = require("web3"); +const truffleAssert = require("truffle-assertions"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); const BIND_CHANNEL_ID = 0x01; const TRANSFER_IN_CHANNELID = 0x02; @@ -35,1273 +34,1687 @@ const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; function toBytes32String(input) { - let initialInputHexStr = web3.utils.toBN(input).toString(16); - const initialInputHexStrLength = initialInputHexStr.length; - - let inputHexStr = initialInputHexStr; - for (var i = 0; i < 64 - initialInputHexStrLength; i++) { - inputHexStr = '0' + inputHexStr; - } - return inputHexStr; + let initialInputHexStr = web3.utils.toBN(input).toString(16); + const initialInputHexStrLength = initialInputHexStr.length; + + let inputHexStr = initialInputHexStr; + for (let i = 0; i < 64 - initialInputHexStrLength; i++) { + inputHexStr = "0" + inputHexStr; + } + return inputHexStr; } function stringToBytes32(symbol) { - var initialSymbolHexStr = ''; - for (var i=0; i=33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - mirrorSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - - const mirrorSender = web3.utils.bytesToHex(mirrorSynPackage[0]); - const bep20Addr = web3.utils.bytesToHex(mirrorSynPackage[1]); - const bep20Name = web3.utils.bytesToHex(mirrorSynPackage[2]); - const bep20Symbol = web3.utils.bytesToHex(mirrorSynPackage[3]); - const bep20Supply = web3.utils.bytesToHex(mirrorSynPackage[4]); - const bep20Decimals = web3.utils.bytesToHex(mirrorSynPackage[5]); - const mirrorFee = web3.utils.bytesToHex(mirrorSynPackage[6]); - const expireTime = web3.utils.bytesToHex(mirrorSynPackage[7]); - - return {mirrorSender, bep20Addr, bep20Name, bep20Symbol, bep20Supply, bep20Decimals, mirrorFee, expireTime}; + let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); + assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + let mirrorSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + + const mirrorSender = web3.utils.bytesToHex(mirrorSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(mirrorSynPackage[1]); + const bep20Name = web3.utils.bytesToHex(mirrorSynPackage[2]); + const bep20Symbol = web3.utils.bytesToHex(mirrorSynPackage[3]); + const bep20Supply = web3.utils.bytesToHex(mirrorSynPackage[4]); + const bep20Decimals = web3.utils.bytesToHex(mirrorSynPackage[5]); + const mirrorFee = web3.utils.bytesToHex(mirrorSynPackage[6]); + const expireTime = web3.utils.bytesToHex(mirrorSynPackage[7]); + + return { mirrorSender, bep20Addr, bep20Name, bep20Symbol, bep20Supply, bep20Decimals, mirrorFee, expireTime }; } function buildMirrorAckPackage(mirrorSender, bep20Addr, bep20Decimals, bep2Symbol, refundAmount, errorCode) { - const packageBytesPrefix = buildAckPackagePrefix(); - const packageBytes = RLP.encode([ - mirrorSender, - bep20Addr, - bep20Decimals, - stringToBytes32(bep2Symbol), - refundAmount, - errorCode]); - return Buffer.concat([packageBytesPrefix, packageBytes]); + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([ + mirrorSender, + bep20Addr, + bep20Decimals, + stringToBytes32(bep2Symbol), + refundAmount, + errorCode, + ]); + return Buffer.concat([packageBytesPrefix, packageBytes]); } function decodeSyncSynPackage(packageBytes) { - eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); - assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - syncSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - const syncSender = web3.utils.bytesToHex(syncSynPackage[0]); - const bep20Addr = web3.utils.bytesToHex(syncSynPackage[1]); - const bep2Symbol = web3.utils.bytesToHex(syncSynPackage[2]); - const bep20Supply = web3.utils.bytesToHex(syncSynPackage[3]); - const syncFee = web3.utils.bytesToHex(syncSynPackage[4]); - const expireTime = web3.utils.bytesToHex(syncSynPackage[5]); - return {syncSender, bep20Addr, bep2Symbol, bep20Supply, syncFee, expireTime}; + let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); + assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + let syncSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + const syncSender = web3.utils.bytesToHex(syncSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(syncSynPackage[1]); + const bep2Symbol = web3.utils.bytesToHex(syncSynPackage[2]); + const bep20Supply = web3.utils.bytesToHex(syncSynPackage[3]); + const syncFee = web3.utils.bytesToHex(syncSynPackage[4]); + const expireTime = web3.utils.bytesToHex(syncSynPackage[5]); + return { syncSender, bep20Addr, bep2Symbol, bep20Supply, syncFee, expireTime }; } function buildSyncAckPackage(syncSender, bep20Addr, refundAmount, errorCode) { - const packageBytesPrefix = buildAckPackagePrefix(); - const packageBytes = RLP.encode([ - syncSender, - bep20Addr, - refundAmount, - errorCode - ]); - return Buffer.concat([packageBytesPrefix, packageBytes]); + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([syncSender, bep20Addr, refundAmount, errorCode]); + return Buffer.concat([packageBytesPrefix, packageBytes]); } function serialize(key, value, target, extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if(extra != null){ - pkg.push(extra); - } - return RLP.encode(pkg); + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if (extra != null) { + pkg.push(extra); + } + return RLP.encode(pkg); } function verifyPrefixAndExtractSyncPackage(payload, expectedRelayFee) { - eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); - assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - assert.ok(web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(expectedRelayFee)), "wrong relay fee"); - return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); + assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + assert.ok( + web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(expectedRelayFee)), + "wrong relay fee" + ); + return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); } function verifyPrefixAndExtractAckPackage(payload) { - eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); - assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x01", "wrong package type"); - assert.ok(web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(0)), "wrong relay fee"); - if (eventPayloadBytes.length>33) { - return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - } - return [] + let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); + assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x01", "wrong package type"); + assert.ok( + web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(0)), + "wrong relay fee" + ); + if (eventPayloadBytes.length > 33) { + return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + } + return []; } -contract('TokenHub', (accounts) => { - it('Init TokenHub', async () => { - const mockLightClient = await MockLightClient.deployed(); - await mockLightClient.setBlockNotSynced(false); +contract("TokenHub", (accounts) => { + it("Init TokenHub", async () => { + const mockLightClient = await MockLightClient.deployed(); + await mockLightClient.setBlockNotSynced(false); + + const tokenHub = await TokenHub.deployed(); + let balance_wei = await web3.eth.getBalance(tokenHub.address); + assert.equal(balance_wei, 50e18, "wrong balance"); + + const relayer = accounts[1]; + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({ from: relayer, value: 1e20 }); + let res = await relayerInstance.isRelayer.call(relayer); + assert.equal(res, true); + }); + it("Relay expired bind package", async () => { + const abcToken = await ABCToken.deployed(); + const tokenManager = await TokenManager.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, + }); - const tokenHub = await TokenHub.deployed(); - let balance_wei = await web3.eth.getBalance(tokenHub.address); - assert.equal(balance_wei, 50e18, "wrong balance"); + let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(bindRequenst.totalSupply.eq(new BN("52b7d2dcc80cd2e4000000", 16)), true, "wrong total supply"); // 1e26 + assert.equal(bindRequenst.peggyAmount.eq(new BN("51e410c0f93fe543000000", 16)), true, "wrong peggy amount"); // 99e24 + assert.equal(bindRequenst.contractAddr.toString(), abcToken.address.toString(), "wrong contract address"); + + let lockAmount = await tokenManager.queryRequiredLockAmountForBind("ABC-9C7"); + assert.equal(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)).eq(lockAmount), true, "wrong lock amount"); + try { + await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: relayer }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("only bep20 owner can approve this bind request")); + } - const relayer = accounts[1]; - const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({from: relayer, value: 1e20}); - let res = await relayerInstance.isRelayer.call(relayer); - assert.equal(res,true); - }); - it('Relay expired bind package', async () => { - const abcToken = await ABCToken.deployed(); - const tokenManager = await TokenManager.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - - let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - assert.equal(bindRequenst.totalSupply.eq(new BN('52b7d2dcc80cd2e4000000', 16)), true, "wrong total supply"); // 1e26 - assert.equal(bindRequenst.peggyAmount.eq(new BN('51e410c0f93fe543000000', 16)), true, "wrong peggy amount"); // 99e24 - assert.equal(bindRequenst.contractAddr.toString(), abcToken.address.toString(), "wrong contract address"); - - let lockAmount = await tokenManager.queryRequiredLockAmountForBind( "ABC-9C7"); - assert.equal(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)).eq(lockAmount), true, "wrong lock amount"); - try { - await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: relayer}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("only bep20 owner can approve this bind request")); - } - - try { - await tokenManager.approveBind("0x0000000000000000000000000000000000000000", "ABC-9C7", {from: relayer}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("contact address doesn't equal to the contract address in bind request")); - } - - try { - await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("allowance is not enough")); - } - - await abcToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)), {from: owner}); - await sleep(5 * 1000); - // approve expired bind request - let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - - bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); + try { + await tokenManager.approveBind("0x0000000000000000000000000000000000000000", "ABC-9C7", { from: relayer }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("contact address doesn't equal to the contract address in bind request")); + } + + try { + await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("allowance is not enough")); + } + + await abcToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)), { from: owner }); + await sleep(5 * 1000); + // approve expired bind request + let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal( + bindRequenst.bep2TokenSymbol.toString(), + "0x0000000000000000000000000000000000000000000000000000000000000000", + "wrong bep2TokenSymbol" + ); + }); + it("Reject bind", async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); //expire time + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, }); - it('Reject bind', async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - const owner = accounts[0]; - const relayer = accounts[1]; + try { + await tokenManager.rejectBind(abcToken.address, "ABC-9C7", { from: relayer, value: 1e16 }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("only bep20 owner can reject")); + } - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); //expire time - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + let tx = await tokenManager.rejectBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - try { - await tokenManager.rejectBind(abcToken.address, "ABC-9C7", {from: relayer, value: 1e16}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("only bep20 owner can reject")); - } + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x07", "bind status should be rejected"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - let tx = await tokenManager.rejectBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); + const bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal( + bindRequenst.bep2TokenSymbol.toString(), + "0x0000000000000000000000000000000000000000000000000000000000000000", + "wrong bep2TokenSymbol" + ); + }); + it("Expire bind", async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + const relayer = accounts[1]; - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x07", "bind status should be rejected"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - const bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, }); - it('Expire bind', async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - const owner = accounts[0]; - const relayer = accounts[1]; + try { + await tokenManager.expireBind("ABC-9C7", { from: accounts[2], value: 1e16 }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("bind request is not expired")); + } - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + await sleep(5 * 1000); - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + let tx = await tokenManager.expireBind("ABC-9C7", { from: accounts[2], value: 1e16 }); - try { - await tokenManager.expireBind("ABC-9C7", {from: accounts[2], value: 1e16}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("bind request is not expired")); - } + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - await sleep(5 * 1000); + let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal( + bindRequenst.bep2TokenSymbol.toString(), + "0x0000000000000000000000000000000000000000000000000000000000000000", + "wrong bep2TokenSymbol" + ); + }); + it("Mismatched token symbol", async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - tx = await tokenManager.expireBind("ABC-9C7", {from: accounts[2], value: 1e16}); + const owner = accounts[0]; + const relayer = accounts[1]; - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + const bindPackage = buildBindPackage(0, "DEF-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, }); - it('Mismatched token symbol', async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - const owner = accounts[0]; - const relayer = accounts[1]; + let tx = await tokenManager.approveBind(abcToken.address, "DEF-9C7", { from: owner, value: 1e16 }); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x02", "bind status should be symbol mismatch"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("DEF-9C7"), "wrong bep2TokenSymbol"); + + let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("DEF-9C7")); // symbol: ABC-9C7 + assert.equal( + bindRequenst.bep2TokenSymbol.toString(), + "0x0000000000000000000000000000000000000000000000000000000000000000", + "wrong bep2TokenSymbol" + ); + }); + it("Success bind", async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, + }); - const bindPackage = buildBindPackage(0, "DEF-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); + truffleAssert.eventEmitted(tx, "bindSuccess", (ev) => { + return ev.contractAddr.toLowerCase() === abcToken.address.toLowerCase() && ev.bep2Symbol === "ABC-9C7"; + }); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + + const tokenHub = await TokenHub.deployed(); + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); + assert.equal(bep2Symbol, "ABC-9C7", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); + assert.equal(contractAddr, abcToken.address, "wrong contract addr"); + + let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(tokenManagerBalance, "0", "tokenManager balance should be zero"); + }); + it("Relayer transfer from BC to BSC", async () => { + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + + const transferInPackage = buildTransferInPackage( + "ABC-9C7", + abcToken.address, + 155e17, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.toNumber(), 0, "wrong balance"); + + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, { + from: relayer, + }); - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + }); + it("Expired transfer from BC to BSC", async () => { + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + + const transferInPackage = buildTransferInPackage( + "ABC-9C7", + abcToken.address, + 155e17, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + await sleep(5 * 1000); + + let tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + let event; + truffleAssert.eventEmitted(tx, "crossChainPackage", (ev) => { + let matched = false; + if (ev.packageSequence.toString() === "0") { + event = ev; + matched = true; + } + return matched; + }); + let decoded = verifyPrefixAndExtractAckPackage(event.payload); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "response should be empty"); + assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(155e7).toString(16), "response should be empty"); + assert.equal( + web3.utils.bytesToHex(decoded[2]), + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", + "response should be empty" + ); + assert.equal(web3.utils.bytesToHex(decoded[3]), "0x01", "refund status should be timeout"); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + }); + it("Relayer BNB transfer from BC to BSC", async () => { + const tokenHub = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + let transferInPackage = buildTransferInPackage( + "BNB", + "0x0000000000000000000000000000000000000000", + 1e18, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + let initBalance = await web3.eth.getBalance(accounts[2]); + let tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + let nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; + assert.equal(nestedEvents.length, 2, "wrong event number"); + assert.equal(nestedEvents[1].args.amount.eq(web3.utils.toBN(1e16)), true, "wrong relayer amount"); + let newBalance = await web3.eth.getBalance(accounts[2]); + assert.equal( + web3.utils.toBN(newBalance).sub(web3.utils.toBN(initBalance)).eq(web3.utils.toBN(1e18)), + true, + "wrong balance" + ); + + //try a very large relayer fee: 2e18 + transferInPackage = buildTransferInPackageWithRelayFee( + "BNB", + "0x0000000000000000000000000000000000000000", + 1e18, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", + 2e18 + ); + transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; + assert.equal(nestedEvents.length, 1, "wrong event number"); + }); + it("BNB transfer to non-payable address", async () => { + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + const tendermintLightClient = await TendermintLightClient.deployed(); + const transferInPackage = buildTransferInPackage( + "BNB", + "0x0000000000000000000000000000000000000000", + 1e18, + tendermintLightClient.address, + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + const transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + const tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + let event; + truffleAssert.eventEmitted(tx, "crossChainPackage", (ev) => { + let matched = false; + if (ev.packageSequence.toString() === "1") { + event = ev; + matched = true; + } + return matched; + }); + let decoded = verifyPrefixAndExtractAckPackage(event.payload); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "response should be empty"); + assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(1e8).toString(16), "response should be empty"); + assert.equal( + web3.utils.bytesToHex(decoded[2]), + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", + "response should be empty" + ); + assert.equal(web3.utils.bytesToHex(decoded[3]), "0x04", "refund status should be non-payable recipient address"); + }); + it("Transfer from BSC to BC", async () => { + const crossChain = await CrossChain.deployed(); + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const defToken = await DEFToken.deployed(); + + const sender = accounts[2]; - tx = await tokenManager.approveBind(abcToken.address, "DEF-9C7", {from: owner, value: 1e16}); + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + let amount = web3.utils.toBN(1e18); + let relayFee = web3.utils.toBN(1e16); + + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("BEP20: transfer amount exceeds allowance")); + } - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x02", "bind status should be symbol mismatch"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("DEF-9C7"), "wrong bep2TokenSymbol"); + try { + const amount = web3.utils.toBN(1e8); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount")); + } - bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("DEF-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); - }); - it('Success bind', async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - - let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); - truffleAssert.eventEmitted(tx, "bindSuccess",(ev) => { - return ev.contractAddr.toLowerCase() === abcToken.address.toLowerCase() && ev.bep2Symbol === "ABC-9C7"; - }); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - - const tokenHub = await TokenHub.deployed(); - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); - assert.equal(bep2Symbol, "ABC-9C7", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); - assert.equal(contractAddr, abcToken.address, "wrong contract addr"); - - let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(tokenManagerBalance, "0", "tokenManager balance should be zero"); - }); - it('Relayer transfer from BC to BSC', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); + try { + relayFee = web3.utils.toBN(1e16).add(web3.utils.toBN(1)); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid received BNB amount: precision loss in amount conversion")); + } - const relayer = accounts[1]; + try { + relayFee = web3.utils.toBN(1e14); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); + } - const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + relayFee = web3.utils.toBN(1e16); + try { + await tokenHub.transferOut(defToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); + } - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.toNumber(), 0, "wrong balance"); + try { + amount = web3.utils.toBN(1e8); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); + } - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + amount = web3.utils.toBN(1e18); + await abcToken.approve(tokenHub.address, amount, { from: sender }); + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { from: sender }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); + } + let tx = await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { + return ( + ev.amount.eq(web3.utils.toBN(amount)) && + ev.bep20Addr.toString().toLowerCase() === abcToken.address.toLowerCase() + ); + }); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "wrong symbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), abcToken.address.toLowerCase(), "wrong contract address"); + assert.ok( + web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e8)), + "wrong transferOut amount" + ); + assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipient.toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[4][0]), sender.toLowerCase(), "wrong refund address"); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); + }); + it("Relay refund package", async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + const refundAddr = accounts[2]; + + const packageBytesPrefix = buildAckPackagePrefix(1e16); - balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + const packageBytes = RLP.encode([ + abcToken.address, //bep20 contract address + [1e18], //amount + [refundAddr], //refund address + 1, + ]); //status + + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + const amount = web3.utils.toBN(1e18); + let balance = await abcToken.balanceOf.call(refundAddr); + assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); + + let tx = await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + proof, + merkleHeight, + refundSequence, + TRANSFER_OUT_CHANNELID, + { from: relayer } + ); + let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; + assert.equal( + nestedEventValues[0].toString().toLowerCase(), + abcToken.address.toLowerCase(), + "wrong refund contract address" + ); + + balance = await abcToken.balanceOf.call(refundAddr); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + }); + it("Batch transfer out", async () => { + const tokenHub = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + + const sender = accounts[0]; + + const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + let amounts = [web3.utils.toBN(5e9), web3.utils.toBN(5e9)]; + const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + + let timestamp = Math.floor(Date.now() / 1000); + let expireTime = timestamp + 150; + + try { + await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { + from: sender, + value: web3.utils.toBN(2000002e10), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); + } + + amounts = [web3.utils.toBN(1e16), web3.utils.toBN(2e16)]; + let tx = await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { + from: sender, + value: web3.utils.toBN(5e16), }); - it('Expired transfer from BC to BSC', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - - const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - await sleep(5 * 1000); - - let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - let event; - truffleAssert.eventEmitted(tx, "crossChainPackage",(ev) => { - let matched = false; - if (ev.packageSequence.toString() === "0") { - event = ev; - matched = true; - } - return matched; - }); - let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "response should be empty"); - assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(155e7).toString(16), "response should be empty"); - assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); - assert.equal(web3.utils.bytesToHex(decoded[3]), "0x01", "refund status should be timeout"); - - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { + return ( + ev.amount.eq(web3.utils.toBN(3e16)) && + ev.bep20Addr.toString().toLowerCase() === "0x0000000000000000000000000000000000000000" + ); }); - it('Relayer BNB transfer from BC to BSC', async () => { - const tokenHub = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - let transferInPackage = buildTransferInPackage("BNB", "0x0000000000000000000000000000000000000000", 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - let initBalance = await web3.eth.getBalance(accounts[2]); - let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - let nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; - assert.equal(nestedEvents.length, 2, "wrong event number"); - assert.equal(nestedEvents[1].args.amount.eq(web3.utils.toBN(1e16)), true, "wrong relayer amount"); - let newBalance = await web3.eth.getBalance(accounts[2]); - assert.equal(web3.utils.toBN(newBalance).sub(web3.utils.toBN(initBalance)).eq(web3.utils.toBN(1e18)), true, "wrong balance"); - - //try a very large relayer fee: 2e18 - transferInPackage = buildTransferInPackageWithRelayFee("BNB", "0x0000000000000000000000000000000000000000", 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", 2e18); - transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; - assert.equal(nestedEvents.length, 1, "wrong event number"); + assert.equal(tx.receipt.status, true, "failed transaction"); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 2e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "wrong symbol"); + assert.equal( + web3.utils.bytesToHex(decoded[1]), + "0x0000000000000000000000000000000000000000", + "wrong contract address" + ); + assert.ok( + web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e6)), + "wrong transferOut amount" + ); + assert.ok( + web3.utils.toBN(web3.utils.bytesToHex(decoded[2][1])).eq(web3.utils.toBN(2e6)), + "wrong transferOut amount" + ); + assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipientAddrs[0].toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[3][1]), recipientAddrs[1].toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[4][0]), refundAddrs[0].toLowerCase(), "wrong refund address"); + assert.equal(web3.utils.bytesToHex(decoded[4][1]), refundAddrs[1].toLowerCase(), "wrong refund address"); + }); + it("Bind malicious BEP20 token", async () => { + const maliciousToken = await MaliciousToken.deployed(); + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "MALICIOU-A09", maliciousToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, }); - it('BNB transfer to non-payable address', async () => { - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - const tendermintLightClient = await TendermintLightClient.deployed(); - const transferInPackage = buildTransferInPackage("BNB", "0x0000000000000000000000000000000000000000", 1e18, tendermintLightClient.address, "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - const transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - const tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - let event; - truffleAssert.eventEmitted(tx, "crossChainPackage",(ev) => { - let matched = false; - if (ev.packageSequence.toString() === "1") { - event = ev; - matched = true; - } - return matched; - }); - let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "response should be empty"); - assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(1e8).toString(16), "response should be empty"); - assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); - assert.equal(web3.utils.bytesToHex(decoded[3]), "0x04", "refund status should be non-payable recipient address"); + assert.equal(tx.receipt.status, true, "failed transaction"); + + await maliciousToken.approve(tokenManager.address, web3.utils.toBN("1000000000000000000000000"), { + from: owner, }); - it('Transfer from BSC to BC', async () => { - const crossChain = await CrossChain.deployed(); - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const defToken = await DEFToken.deployed(); - - const sender = accounts[2]; - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - let amount = web3.utils.toBN(1e18); - let relayFee = web3.utils.toBN(1e16); - - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("BEP20: transfer amount exceeds allowance")); - } - - try { - const amount = web3.utils.toBN(1e8); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount")); - } - - try { - relayFee = web3.utils.toBN(1e16).add(web3.utils.toBN(1)); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid received BNB amount: precision loss in amount conversion")); - } - - try { - relayFee = web3.utils.toBN(1e14); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); - } - - relayFee = web3.utils.toBN(1e16); - try { - await tokenHub.transferOut(defToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); - } - - try { - amount = web3.utils.toBN(1e8); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); - } - - amount = web3.utils.toBN(1e18); - await abcToken.approve(tokenHub.address, amount, {from: sender}); - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); - } - let tx = await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { - return ev.amount.eq(web3.utils.toBN(amount)) && ev.bep20Addr.toString().toLowerCase() === abcToken.address.toLowerCase(); - }); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "wrong symbol"); - assert.equal(web3.utils.bytesToHex(decoded[1]), abcToken.address.toLowerCase(), "wrong contract address"); - assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e8)), "wrong transferOut amount"); - assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipient.toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[4][0]), sender.toLowerCase(), "wrong refund address"); - - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); + await tokenManager.approveBind(maliciousToken.address, "MALICIOU-A09", { from: owner, value: 1e16 }); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(maliciousToken.address); + assert.equal(bep2Symbol, "MALICIOU-A09", "wrong symbol"); + + const transferInPackage = buildTransferInPackage( + "MALICIOU-A09", + maliciousToken.address, + 155e17, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + let balance = await maliciousToken.balanceOf.call(accounts[2]); + assert.equal(balance.toNumber(), 0, "wrong balance"); + + tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + assert.equal(tx.receipt.status, true, "failed transaction"); + + let newTransferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + assert.equal(newTransferInSequence.toNumber(), transferInSequence.toNumber() + 1, "wrong transferIn sequence"); + + let packageBytesPrefix = Buffer.from( + web3.utils.hexToBytes("0x01" + "0000000000000000000000000000000000000000000000000000000000000000") + ); + + let packageBytes = RLP.encode([ + maliciousToken.address, //bep2TokenSymbol + ["0x000000000000000000000000000000000000000000000000000000174876E800"], //amount + ["0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"], //refund address + 1, + ]); //refund address + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + tx = await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + proof, + merkleHeight, + refundSequence, + TRANSFER_OUT_CHANNELID, + { from: relayer } + ); + assert.equal(tx.receipt.status, true, "failed transaction"); + + let newRefundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + assert.equal(newRefundSequence.toNumber(), refundSequence.toNumber() + 1, "wrong transferIn sequence"); + }); + it("Uint256 overflow in transferOut and batchTransferOutBNB", async () => { + const tokenHub = await TokenHub.deployed(); + + const sender = accounts[2]; + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + let recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + let amount = web3.utils.toBN("115792089237316195423570985008687907853269984665640564039457584007903129639936"); + + try { + await tokenHub.transferOut("0x0000000000000000000000000000000000000000", recipient, amount, expireTime, { + from: sender, + value: web3.utils.toBN("9999990000000000"), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("SafeMath: addition overflow")); + } + + const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + let amounts = [ + web3.utils.toBN("100000000000000000000000000000000000000000000000000000000000000000000000000000"), + web3.utils.toBN("15792089237316195423570985008687907853269984665640564039457584007910000000000"), + ]; + const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + + timestamp = Math.floor(Date.now() / 1000); + expireTime = timestamp + 150; + + try { + await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { + from: sender, + value: web3.utils.toBN("9999990000000000"), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("SafeMath: addition overflow")); + } + }); + it("fail ack for transfer out", async () => { + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + let initBalance3 = await abcToken.balanceOf.call(accounts[3]); + let initBalance4 = await abcToken.balanceOf.call(accounts[4]); + + let packageBytesPrefix = Buffer.from( + web3.utils.hexToBytes("0x02" + "0000000000000000000000000000000000000000000000000000000000000000") + ); + + let packageBytes = RLP.encode([ + stringToBytes32("ABC-9C7"), + abcToken.address, + [1e6, 2e6], + ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], + [accounts[3], accounts[4]], + Math.floor(Date.now() / 1000), + ]); + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + proof, + merkleHeight, + refundSequence, + TRANSFER_OUT_CHANNELID, + { from: relayer } + ); + + let newBalance3 = await abcToken.balanceOf.call(accounts[3]); + let newBalance4 = await abcToken.balanceOf.call(accounts[4]); + + assert.equal(newBalance3.sub(initBalance3).eq(web3.utils.toBN(1e16)), true, "wrong balance"); + assert.equal(newBalance4.sub(initBalance4).eq(web3.utils.toBN(2e16)), true, "wrong balance"); + }); + it("Unbind Token", async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(1, "ABC-9C7", abcToken.address, 0, 0, 0); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, }); - it('Relay refund package', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); + assert.equal(tx.receipt.status, true, "failed transaction"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); + assert.equal(bep2Symbol, "", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); + assert.equal(contractAddr, "0x0000000000000000000000000000000000000000", "wrong contract addr"); + + const transferInPackage = buildTransferInPackage( + "ABC-9C7", + abcToken.address, + 1e18, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + tx = await crossChain.handlePackage( + transferInPackage, + proof, + merkleHeight, + transferInSequence, + TRANSFER_IN_CHANNELID, + { from: relayer } + ); + assert.equal(tx.receipt.status, true, "failed transaction"); + + // refund should be successful + const refundAddr = accounts[2]; + let packageBytesPrefix = Buffer.from( + web3.utils.hexToBytes("0x01" + "0000000000000000000000000000000000000000000000000000000000000000") + ); + let packageBytes = RLP.encode([ + abcToken.address, //bep2TokenSymbol + ["0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000"], //amount + [refundAddr], //refund address + 1, + ]); //refund address + + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + let beforeRefundBalance = await abcToken.balanceOf.call(refundAddr); + + tx = await crossChain.handlePackage( + Buffer.concat([packageBytesPrefix, packageBytes]), + proof, + merkleHeight, + refundSequence, + TRANSFER_OUT_CHANNELID, + { from: relayer } + ); + assert.equal(tx.receipt.status, true, "failed transaction"); + let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; + assert.equal( + nestedEventValues[0].toString().toLowerCase(), + abcToken.address.toLowerCase(), + "wrong refund contract address" + ); + assert.equal(nestedEventValues[1].toString().toLowerCase(), refundAddr.toLowerCase(), "wrong refund address"); + + let afterRefundBalance = await abcToken.balanceOf.call(refundAddr); + assert.equal(afterRefundBalance.sub(beforeRefundBalance).eq(web3.utils.toBN(1e18)), true, "wrong balance"); + + // transferOut should be failed + const sender = accounts[2]; + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + const amount = web3.utils.toBN(1e11); + const relayFee = web3.utils.toBN(2e16); + await abcToken.approve(tokenHub.address, amount, { from: sender }); + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { + from: sender, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); + } + }); + it("bind and transfer miniToken", async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - const refundAddr = accounts[2]; + const owner = accounts[0]; + const relayer = accounts[1]; - const packageBytesPrefix = buildAckPackagePrefix(1e16); + const bindPackage = buildBindPackage(0, "XYZ-9C7M", miniToken.address, 1e4, 5e3, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - const packageBytes = RLP.encode([ - abcToken.address, //bep20 contract address - [1e18], //amount - [refundAddr], //refund address - 1]); //status + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { + from: relayer, + }); - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + await miniToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(5e3)), { from: owner }); + let tx = await tokenManager.approveBind(miniToken.address, "XYZ-9C7M", { from: owner, value: 1e16 }); - const amount = web3.utils.toBN(1e18); - let balance = await abcToken.balanceOf.call(refundAddr); - assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("XYZ-9C7M"), "wrong bep2TokenSymbol"); - tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); - let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; - assert.equal(nestedEventValues[0].toString().toLowerCase(), abcToken.address.toLowerCase(), "wrong refund contract address"); + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); + assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("XYZ-9C7M"); + assert.equal(contractAddr, miniToken.address, "wrong contract addr"); - balance = await abcToken.balanceOf.call(refundAddr); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); + let amount = web3.utils.toBN(1e18); + let recipient = accounts[3]; + await miniToken.approve(tokenHub.address, amount, { from: owner }); + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; + const relayFee = web3.utils.toBN(1e16); + tx = await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, { + from: owner, + value: relayFee, }); - it('Batch transfer out', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const sender = accounts[0]; - - const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - let amounts = [web3.utils.toBN(5e9), web3.utils.toBN(5e9)]; - const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - - let timestamp = Math.floor(Date.now() / 1000); - let expireTime = (timestamp + 150); - - try { - await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN(2000002e10)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); - } - - amounts = [web3.utils.toBN(1e16), web3.utils.toBN(2e16)]; - let tx = await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN(5e16)}); - truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { - return ev.amount.eq(web3.utils.toBN(3e16)) && ev.bep20Addr.toString().toLowerCase() === "0x0000000000000000000000000000000000000000"; - }); - assert.equal(tx.receipt.status, true, "failed transaction"); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 2e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "wrong symbol"); - assert.equal(web3.utils.bytesToHex(decoded[1]), "0x0000000000000000000000000000000000000000", "wrong contract address"); - assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e6)), "wrong transferOut amount"); - assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][1])).eq(web3.utils.toBN(2e6)), "wrong transferOut amount"); - assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipientAddrs[0].toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[3][1]), recipientAddrs[1].toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[4][0]), refundAddrs[0].toLowerCase(), "wrong refund address"); - assert.equal(web3.utils.bytesToHex(decoded[4][1]), refundAddrs[1].toLowerCase(), "wrong refund address"); + truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { + return ( + ev.amount.eq(web3.utils.toBN(amount)) && + ev.bep20Addr.toString().toLowerCase() === miniToken.address.toLowerCase() + ); }); - it('Bind malicious BEP20 token', async () => { - const maliciousToken = await MaliciousToken.deployed(); - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); + amount = web3.utils.toBN(5e17); + await miniToken.approve(tokenHub.address, amount, { from: owner }); + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; + try { + await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, { + from: owner, + value: relayFee, + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("For miniToken, the transfer amount must not be less than 1")); + } - const owner = accounts[0]; - const relayer = accounts[1]; + amount = web3.utils.toBN(1e18); + const transferInPackage = buildTransferInPackage( + "XYZ-9C7M", + miniToken.address, + amount, + accounts[2], + "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" + ); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + const initBalance = await miniToken.balanceOf.call(accounts[2]); + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, { + from: relayer, + }); + const newBalance = await miniToken.balanceOf.call(accounts[2]); + assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); + }); + it("enable mirror and sync channel", async () => { + const tokenManager = await TokenManager.deployed(); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + MockLightClient.address, + TokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + CrossChain.address + ); + + const relayer = accounts[1]; + + const tokenMgrAddrStr = TokenManager.address.toString().replace("0x", ""); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x04" + "01" + tokenMgrAddrStr; + let govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x05" + "01" + tokenMgrAddrStr; + govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000056bc75e2d63100000"; // 1e20; + govPackageBytes = serialize("mirrorFee", govValue, TokenManager.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000008ac7230489e80000"; // 1e19 + govPackageBytes = serialize("syncFee", govValue, TokenManager.address); + await crossChain.handlePackage( + Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), + proof, + merkleHeight, + govChannelSeq, + GOV_CHANNEL_ID, + { from: relayer } + ); + + const mirrorFee = await tokenManager.mirrorFee(); + assert.equal(web3.utils.toBN(1e20).eq(mirrorFee), true, "Wrong mirrorFee"); + const syncFee = await tokenManager.syncFee(); + assert.equal(web3.utils.toBN(1e19).eq(syncFee), true, "Wrong syncFee"); + + await govHub.updateContractAddr( + BSCValidatorSet.address, + SlashIndicator.address, + SystemReward.address, + MockLightClient.address, + TokenHub.address, + RelayerIncentivize.address, + RelayerHub.address, + GovHub.address, + TokenManager.address, + accounts[8] + ); + }); + it("iterate mirror failures", async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(miniToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("already bound")); + } - const bindPackage = buildBindPackage(0, "MALICIOU-A09", maliciousToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); + try { + await xyzToken.setName("", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } + + try { + await xyzToken.setName("XYZ TokenXYZ TokenXYZ TokenXYZ Token", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } - await maliciousToken.approve(tokenManager.address, web3.utils.toBN('1000000000000000000000000'), {from: owner}); - await tokenManager.approveBind(maliciousToken.address, "MALICIOU-A09", {from: owner, value: 1e16}); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("X", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [2,8]")); + } + + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZXYZXYZ", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [2,8]")); + } - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(maliciousToken.address); - assert.equal(bep2Symbol, "MALICIOU-A09", "wrong symbol"); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("X-Z", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol should only contain alphabet and number")); + } - const transferInPackage = buildTransferInPackage("MALICIOU-A09", maliciousToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XY_Z", { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol should only contain alphabet and number")); + } - let balance = await maliciousToken.balanceOf.call(accounts[2]); - assert.equal(balance.toNumber(), 0, "wrong balance"); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(1, { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } - tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(86, { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large decimals")); + } - let newTransferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - assert.equal(newTransferInSequence.toNumber(), transferInSequence.toNumber()+1, "wrong transferIn sequence"); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(18, { from: xyzTokenOwner }); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } - packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( - "0x01" + - "0000000000000000000000000000000000000000000000000000000000000000" - )); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(18, { from: xyzTokenOwner }); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee).add(web3.utils.toBN(1e9)), + }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee") + ); + } - packageBytes = RLP.encode([ - maliciousToken.address, //bep2TokenSymbol - ["0x000000000000000000000000000000000000000000000000000000174876E800"], //amount - ["0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"], //refund address - 1]); //refund address - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(18, { from: xyzTokenOwner }); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee).sub(web3.utils.toBN(1e9)), + }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee") + ); + } - tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); + try { + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(18, { from: xyzTokenOwner }); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("mirror pending")); + const mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "", mirrorFee, 1); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, { + from: relayer, + }); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + } + }); + it("successful mirror", async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); + await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); + await xyzToken.setDecimals(18, { from: xyzTokenOwner }); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const xyzTokenTotalSupply = await xyzToken.totalSupply(); + const xyzTokenDecimals = await xyzToken.decimals(); + const xyzTokenName = await xyzToken.name(); + const xyzTokenSymbol = await xyzToken.symbol(); + + const mirrorFee = await tokenManager.mirrorFee(); + const syncFee = await tokenManager.syncFee(); - let newRefundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - assert.equal(newRefundSequence.toNumber(), refundSequence.toNumber()+1, "wrong transferIn sequence"); - }); - it('Uint256 overflow in transferOut and batchTransferOutBNB', async () => { - const tokenHub = await TokenHub.deployed(); - - const sender = accounts[2]; - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - let recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - let amount = web3.utils.toBN("115792089237316195423570985008687907853269984665640564039457584007903129639936"); - - try { - await tokenHub.transferOut("0x0000000000000000000000000000000000000000", recipient, amount, expireTime, {from: sender, value: web3.utils.toBN("9999990000000000")}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("SafeMath: addition overflow")); - } - - const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - let amounts = [web3.utils.toBN("100000000000000000000000000000000000000000000000000000000000000000000000000000"), web3.utils.toBN("15792089237316195423570985008687907853269984665640564039457584007910000000000")]; - const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - - timestamp = Math.floor(Date.now() / 1000); - expireTime = (timestamp + 150); - - try { - await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN("9999990000000000")}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("SafeMath: addition overflow")); - } - }); - it('fail ack for transfer out', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - let initBalance3 = await abcToken.balanceOf.call(accounts[3]); - let initBalance4 = await abcToken.balanceOf.call(accounts[4]); - - packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( - "0x02" + - "0000000000000000000000000000000000000000000000000000000000000000" - )); - - packageBytes = RLP.encode([ - stringToBytes32("ABC-9C7"), - abcToken.address, - [1e6, 2e6], - ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], - [accounts[3], accounts[4]], - Math.floor(Date.now() / 1000) - ]); - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); - - let newBalance3 = await abcToken.balanceOf.call(accounts[3]); - let newBalance4 = await abcToken.balanceOf.call(accounts[4]); - - assert.equal(newBalance3.sub(initBalance3).eq(web3.utils.toBN(1e16)), true, "wrong balance"); - assert.equal(newBalance4.sub(initBalance4).eq(web3.utils.toBN(2e16)), true, "wrong balance"); - }); - it('Unbind Token', async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(1, "ABC-9C7", abcToken.address, 0, 0, 0); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); - assert.equal(bep2Symbol, "", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); - assert.equal(contractAddr, "0x0000000000000000000000000000000000000000", "wrong contract addr"); - - - const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); - - // refund should be successful - const refundAddr = accounts[2]; - packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( - "0x01" + - "0000000000000000000000000000000000000000000000000000000000000000" - )); - packageBytes = RLP.encode([ - abcToken.address, //bep2TokenSymbol - ["0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000"], //amount - [refundAddr], //refund address - 1]); //refund address - - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - let beforeRefundBalance = await abcToken.balanceOf.call(refundAddr); - - tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); - assert.equal(tx.receipt.status, true, "failed transaction"); - let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; - assert.equal(nestedEventValues[0].toString().toLowerCase(), abcToken.address.toLowerCase(), "wrong refund contract address"); - assert.equal(nestedEventValues[1].toString().toLowerCase(), refundAddr.toLowerCase(), "wrong refund address"); - - let afterRefundBalance = await abcToken.balanceOf.call(refundAddr); - assert.equal(afterRefundBalance.sub(beforeRefundBalance).eq(web3.utils.toBN(1e18)), true, "wrong balance"); - - // transferOut should be failed - const sender = accounts[2]; - timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - const amount = web3.utils.toBN(1e11); - const relayFee = web3.utils.toBN(2e16); - await abcToken.approve(tokenHub.address, amount, {from: sender}); - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); - } - }); - it('bind and transfer miniToken', async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "XYZ-9C7M", miniToken.address, 1e4, 5e3, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - - await miniToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(5e3)), {from: owner}); - let tx = await tokenManager.approveBind(miniToken.address, "XYZ-9C7M", {from: owner, value: 1e16}); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("XYZ-9C7M"), "wrong bep2TokenSymbol"); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); - assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("XYZ-9C7M"); - assert.equal(contractAddr, miniToken.address, "wrong contract addr"); - - let amount = web3.utils.toBN(1e18); - let recipient = accounts[3]; - await miniToken.approve(tokenHub.address, amount, {from: owner}); - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = (timestamp + 300); - const relayFee = web3.utils.toBN(1e16); - tx = await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); - truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { - return ev.amount.eq(web3.utils.toBN(amount)) && ev.bep20Addr.toString().toLowerCase() === miniToken.address.toLowerCase(); - }); - amount = web3.utils.toBN(5e17); - await miniToken.approve(tokenHub.address, amount, {from: owner}); - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = (timestamp + 300); - try { - await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("For miniToken, the transfer amount must not be less than 1")); - } - - amount = web3.utils.toBN(1e18); - const transferInPackage = buildTransferInPackage("XYZ-9C7M", miniToken.address, amount, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - const initBalance = await miniToken.balanceOf.call(accounts[2]); - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); - const newBalance = await miniToken.balanceOf.call(accounts[2]); - assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + let tx = await tokenManager.mirror(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(mirrorFee), }); - it('enable mirror and sync channel', async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - const govHub = await GovHub.deployed(); - - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, CrossChain.address); - - const owner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - const tokenMgrAddrStr = TokenManager.address.toString().replace("0x", ""); - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x04" + "01" + tokenMgrAddrStr; - let govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x05" + "01" + tokenMgrAddrStr; - govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000056bc75e2d63100000";// 1e20; - govPackageBytes = serialize("mirrorFee", govValue, TokenManager.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000008ac7230489e80000"; // 1e19 - govPackageBytes = serialize("syncFee", govValue, TokenManager.address); - await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - - const mirrorFee = await tokenManager.mirrorFee(); - assert.equal(web3.utils.toBN(1e20).eq(mirrorFee), true, "Wrong mirrorFee"); - const syncFee = await tokenManager.syncFee(); - assert.equal(web3.utils.toBN(1e19).eq(syncFee), true, "Wrong syncFee"); - - await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, accounts[8]); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedMirrorSynPackage = decodeMirrorSynPackage(nestedEventValues.payload); + assert.equal( + decodedMirrorSynPackage.mirrorSender.toLowerCase(), + player.toLowerCase(), + "Wrong mirror sender in mirror sync package" + ); + assert.equal( + decodedMirrorSynPackage.bep20Addr.toLowerCase(), + XYZToken.address.toLowerCase(), + "Wrong bep20 address in mirror sync package" + ); + assert.equal( + decodedMirrorSynPackage.bep20Name, + stringToBytes32(xyzTokenName), + "Wrong bep20 name in mirror sync package" + ); // name: XYZ Token + assert.equal( + decodedMirrorSynPackage.bep20Symbol, + stringToBytes32(xyzTokenSymbol), + "Wrong bep20 symbol in mirror sync package" + ); // symbol: XYZ + assert.equal( + web3.utils.toBN(decodedMirrorSynPackage.mirrorFee).mul(web3.utils.toBN(1e10)).eq(mirrorFee), + true, + "Wrong mirrorFee in mirror sync package" + ); + assert.equal( + web3.utils.hexToNumber(decodedMirrorSynPackage.bep20Decimals), + xyzTokenDecimals, + "Wrong decimals in mirror sync package" + ); + assert.equal( + web3.utils.toBN(decodedMirrorSynPackage.bep20Supply).eq(xyzTokenTotalSupply), + true, + "Wrong total supply in mirror sync package" + ); + let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + // mirror fail ack + let mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage( + Buffer.concat([ + buildFailAckPackagePrefix(), + mirrorFailAckPackageBytes.subarray(33, mirrorFailAckPackageBytes.length), + ]), + proof, + merkleHeight, + mirrorChannelSeq, + MIRROR_CHANNELID, + { from: relayer } + ); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success mirror + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(mirrorFee) }); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "XYZ-123", mirrorFee, 0); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, { + from: relayer, }); - it('iterate mirror failures', async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const mirrorFee = await tokenManager.mirrorFee(); - const xyzTokenOwner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(miniToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("already bound")); - } - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 100; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); - } - - try { - await xyzToken.setName("", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("name length must be in [1,32]")); - } - - try { - await xyzToken.setName("XYZ TokenXYZ TokenXYZ TokenXYZ Token", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("name length must be in [1,32]")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("X", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol length must be in [2,8]")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZXYZXYZ", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol length must be in [2,8]")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("X-Z", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol should only contain alphabet and number")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XY_Z", {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol should only contain alphabet and number")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(1, {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(86, {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large decimals")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(18, {from: xyzTokenOwner}); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(18, {from: xyzTokenOwner}); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).add(web3.utils.toBN(1e9))}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(18, {from: xyzTokenOwner}); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).sub(web3.utils.toBN(1e9))}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); - } - - try { - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(18, {from: xyzTokenOwner}); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("mirror pending")); - const mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "", mirrorFee, 1); - await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); - const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - } + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(xyzToken.address); + assert.equal(bep2Symbol, "XYZ-123", "wrong symbol"); + + await xyzToken.mint(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(syncFee) }); + nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal( + decodedSyncSynPackage.syncSender.toLowerCase(), + player.toLowerCase(), + "Wrong mirror sender in sync syn package" + ); + assert.equal( + decodedSyncSynPackage.bep20Addr.toLowerCase(), + XYZToken.address.toLowerCase(), + "Wrong bep20 address in sync syn package" + ); + assert.equal( + web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), + true, + "Wrong total supply in sync syn package" + ); + assert.equal( + web3.utils.toBN(decodedSyncSynPackage.syncFee).mul(web3.utils.toBN(1e10)).eq(syncFee), + true, + "Wrong mirrorFee in sync syn package" + ); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + // sync fail ack package + let syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + const syncFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage( + Buffer.concat([ + buildFailAckPackagePrefix(), + syncFailAckPackageBytes.subarray(33, syncFailAckPackageBytes.length), + ]), + proof, + merkleHeight, + syncChannelSeq, + SYNC_CHANNELID, + { from: relayer } + ); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success sync and sync ack + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(syncFee) }); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + await crossChain.handlePackage( + buildSyncAckPackage(player, xyzToken.address, syncFee, 0), + proof, + merkleHeight, + syncChannelSeq, + SYNC_CHANNELID, + { from: relayer } + ); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + }); + it("iterate sync failures", async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const defToken = await DEFToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const player = accounts[2]; + + const syncFee = await tokenManager.syncFee(); + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(defToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(miniToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound by mirror")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee), + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } + + try { + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), { from: xyzTokenOwner }); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(mirrorFee) }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + let tx = await tokenManager.sync(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee), }); - it('successful mirror', async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const xyzTokenOwner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); - await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); - await xyzToken.setDecimals(18, {from: xyzTokenOwner}); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const xyzTokenTotalSupply = await xyzToken.totalSupply(); - const xyzTokenDecimals = await xyzToken.decimals(); - const xyzTokenName = await xyzToken.name(); - const xyzTokenSymbol = await xyzToken.symbol(); - - const mirrorFee = await tokenManager.mirrorFee(); - const syncFee = await tokenManager.syncFee(); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - let tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedMirrorSynPackage = decodeMirrorSynPackage(nestedEventValues.payload); - assert.equal(decodedMirrorSynPackage.mirrorSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in mirror sync package"); - assert.equal(decodedMirrorSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in mirror sync package"); - assert.equal(decodedMirrorSynPackage.bep20Name, stringToBytes32(xyzTokenName), "Wrong bep20 name in mirror sync package"); // name: XYZ Token - assert.equal(decodedMirrorSynPackage.bep20Symbol, stringToBytes32(xyzTokenSymbol), "Wrong bep20 symbol in mirror sync package"); // symbol: XYZ - assert.equal(web3.utils.toBN(decodedMirrorSynPackage.mirrorFee).mul(web3.utils.toBN(1e10)).eq(mirrorFee), true, "Wrong mirrorFee in mirror sync package"); - assert.equal(web3.utils.hexToNumber(decodedMirrorSynPackage.bep20Decimals), xyzTokenDecimals, "Wrong decimals in mirror sync package"); - assert.equal(web3.utils.toBN(decodedMirrorSynPackage.bep20Supply).eq(xyzTokenTotalSupply), true, "Wrong total supply in mirror sync package"); - let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - - // mirror fail ack - let mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); - await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), mirrorFailAckPackageBytes.subarray(33, mirrorFailAckPackageBytes.length)]), proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - // success mirror - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - - mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "XYZ-123", mirrorFee, 0); - await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); - - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(xyzToken.address); - assert.equal(bep2Symbol, "XYZ-123", "wrong symbol"); - - - await xyzToken.mint(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); - - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); - nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); - assert.equal(decodedSyncSynPackage.syncSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in sync syn package"); - assert.equal(decodedSyncSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in sync syn package"); - assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); - assert.equal(web3.utils.toBN(decodedSyncSynPackage.syncFee).mul(web3.utils.toBN(1e10)).eq(syncFee), true, "Wrong mirrorFee in sync syn package"); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); - - // sync fail ack package - let syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); - const syncFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); - await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), syncFailAckPackageBytes.subarray(33, syncFailAckPackageBytes.length)]), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - // success sync and sync ack - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); - - syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); - await crossChain.handlePackage(buildSyncAckPackage(player, xyzToken.address, syncFee, 0), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - }); - it('iterate sync failures', async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const defToken = await DEFToken.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const mirrorFee = await tokenManager.mirrorFee(); - const xyzTokenOwner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - const syncFee = await tokenManager.syncFee(); - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(defToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee) - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("not bound")); - } - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(miniToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee) - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("not bound by mirror")); - } - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 100; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee) - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); - } - - try { - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } - - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); - const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); - - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); - nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); - assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); - }); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal( + web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), + true, + "Wrong total supply in sync syn package" + ); + }); }); diff --git a/test/ToolTest.js b/test/ToolTest.js index 9bcd161e..674ad3c4 100644 --- a/test/ToolTest.js +++ b/test/ToolTest.js @@ -1,19 +1,18 @@ const BSCValidatorSetTool = artifacts.require("tool/BSCValidatorSetTool"); -const Web3 = require('web3'); -const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const Web3 = require("web3"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); -contract('Tool', (accounts) => { - it('tool test', async () => { +contract("Tool", (accounts) => { + it("tool test", async () => { const toolInstance = await BSCValidatorSetTool.deployed(); await toolInstance.init(); }); - - it('decode payload header', async () => { - let payload = "0x00000000000000000000000000000000000000000000000000002386f26fc10000f85580a04142432d304237000000000000000000000000000000000000000000000000009450ee0de39df3b9c2bc8f8e33d9e4cd03dba9210c8b52b7d2dcc80cd2e40000008b31a17e847807b1bc00000012845f5efcc1" + + it("decode payload header", async () => { + let payload = + "0x00000000000000000000000000000000000000000000000000002386f26fc10000f85580a04142432d304237000000000000000000000000000000000000000000000000009450ee0de39df3b9c2bc8f8e33d9e4cd03dba9210c8b52b7d2dcc80cd2e40000008b31a17e847807b1bc00000012845f5efcc1"; const toolInstance = await BSCValidatorSetTool.deployed(); let x = await toolInstance.decodePayloadHeader.call(web3.utils.hexToBytes(payload)); assert.equal(x[2].toString(), "10000000000000000"); }); - }); - diff --git a/truffle-config.js b/truffle-config.js index 8c5be080..e2cf168c 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -45,8 +45,8 @@ module.exports = { development: { host: "127.0.0.1", // Localhost (default: none) port: 8545, // Standard Ethereum port (default: none) - network_id: "*", // Any network (default: none) - }, + network_id: "*" // Any network (default: none) + } // Another network with more advanced options... // advanced: { From 9de3519fe270c38f1efe83560812bd07d2630ca2 Mon Sep 17 00:00:00 2001 From: Loverush Date: Mon, 25 Apr 2022 11:38:52 +0800 Subject: [PATCH 04/48] Update for new fast finality rules and related issues --- .gitignore | 14 +- BLSkeystore.json | 45 + README.md | 2 +- abi/bscvalidatorset.abi | 2386 ++++++++++++++++------------ abi/crosschain.abi | 1644 +++++++++---------- abi/govhub.abi | 860 +++++----- abi/relayerhub.abi | 888 +++++------ abi/relayerincentivize.abi | 1532 +++++++++--------- abi/slashindicator.abi | 1411 ++++++++-------- abi/systemreward.abi | 853 +++++----- abi/tendermintlightclient.abi | 1239 +++++++-------- abi/tokenhub.abi | 2128 ++++++++++++------------- abi/tokenmanager.abi | 2253 ++++++++++++-------------- contracts/BSCValidatorSet.sol | 10 +- contracts/BSCValidatorSet.template | 8 +- contracts/SlashIndicator.sol | 99 +- contracts/SlashIndicator.template | 95 +- generate-validator.js | 25 +- genesis-template.json | 5 + genesis.json | 5 + test/GovHub.js | 15 - test/Slash.js | 189 ++- validators.js | 30 +- validators.template | 32 +- 24 files changed, 7856 insertions(+), 7912 deletions(-) create mode 100644 BLSkeystore.json diff --git a/.gitignore b/.gitignore index 8dce3875..255251ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,17 @@ node_modules/ build/ -.idea -pids -logs .idea/ +pids/ +logs/ contracts/flattened/*.sol #Hardhat files -cache -artifacts +cache/ +artifacts/ +contracts/artifacts/ .env .DS_Store -types -typechain-types +types/ +typechain-types/ diff --git a/BLSkeystore.json b/BLSkeystore.json new file mode 100644 index 00000000..908cffe2 --- /dev/null +++ b/BLSkeystore.json @@ -0,0 +1,45 @@ +{ + "public_key": [ + "8f2bc5decb56ad5f88d4c704f6ad616d5038cf1bc068419f4d7f3457a853d74048b1ba3531185d6d36d6bd6881034505", + "83126cd32592a6be5e9658805c5da32db2f5d39f2f294a230cf1689b52f8b8be2135802f6b6ca6b11765331de2bb8def", + "b9cafd2354b57acadd88992fd9dc38986ec29d8efd793acb693f0d0f6b8397cb2a9f8d66e01253579c7d38242d3760f6", + "b373f6a4dfc54e625c2796da0789cbb243e6a285329c3c075ab1a9268db45951a2d6c2a2aafd558efc8c5857bd71dbc0", + "ac0646a7851a75f2d0d8239e717ed1874ed83906eff3845cc7a29abd6064adb8a48c221c3d12624f136292b19c0d92de", + "992354e0ff65e8cb4088a72a241992bf68a192ea685f810bda7a193dc056af3be4bf1f65073cf5e906676d32f2eabe60", + "95d8bb8660a34a374a05a3b9c59609f4a6f5598bba8240b59ef61e94ed6161e00108bac0b817bcb4cf13001924d19539", + "b4c030c9c012ab39aea3117fc96203b18ffb5e979ae44f17de64e212a1a97975d419e2060294940a285778e2100ff023", + "ac1e598ae0ccbeeaafa31bc6faefa85c2ae3138699cac79169cd718f1a38445201454ec092a86f200e08a15266bdc6e9", + "af3ca3f530c61bf7e6b82db58dc6bd4c75192044128004510290289330ae1d33269ec873e0a8e890c2619cf3868c8880", + "987c6c786c2d293f4b5337344c8d29ab0264f80851d5698e597e201f7743af3f848a1ffb7c4802a73e06696d99f95e45", + "97d9423cb780f6a09e759a7327fc5e2542ddc54f9d2cd1b836abf30948f45059709510e8421df03ceccf2ef2ecc9c594", + "b71f0d38cc1d05995126fa0ba311541f0ed3c5c7df64e33c8037afa5d72a5a38a83103433b204f1512502748656cf06f", + "b800c8a040b76946ca14470e7a67c9ca76bf9868730336be57235505e1786f3417a969587be2ac7e6aad1ab21db9cff9", + "a625e9aa0681a842091d9cbc26daa9497a9d305acc36d04f2cb42e9aed90a561514f607625fbf84b23f98ce4baadadb5", + "98a7250b7492047cdb0b388e094db5dc073bba5a4bfc9ed2fc0ec68cba5cec1aad06d72a91ed03211f583f52e5e5d221", + "a8fa139e60271c25de8d5c83a4d0d15107152c193897d2307d334425c40d31104b6ee507e5eb3402419bca0625b58835", + "905024253dae51eb1836a3da59e5883f48d768bb73b4c8be76fd3a124af6ed252941653619ab1e429253fc2586c65383", + "a52c02e1279cbadb974a02404d7cece18d70a2835d004a4e7a25c9e120d794f62e76b9728a13ee84bc6567716238c59f", + "aacd7b81831bc19de3a26f013d2bba8cf5a76cf3c6acee742bace02e2a809a96f72245fb6cb54874b72d300a42b14fe3", + "8f16d65d4898459265d237328b419fad130b2cf2ee381e0a0fc3d5898e81b577a0157d0b99b92eda8891b46ff62c9ea9", + "90ddfd09c9af4d0b693a4013b7e42595ea7bb60ee7fb942a8460d63cd5f0e4c3138467b7c2a50518fa26fe9a2450dbc0", + "a2ec2a7e46bb5d99e7307c39b9ba96e0ef245e2588658b5ccb9a8c2f682a111de5775fec6e7508d19e06be40a260cc7d", + "86d0488587c7dd682988d13c7db0bf9994dd21fa886244a1ddd24aea753de38d32d0c762bd6fbeb137b1ae3118c65885", + "b3e34b6aff02bf146faf47e27d813e3c1bcf2a9a424c2ec95da39ea9dd974aeb239e47bd183ac75e8502ca6e610caf7c", + "b45752f376347597826c52202dd5a4695b7f73b4a111d9a39f8bd43220984ecd428280779befa314f4b24ce537b7448b", + "83c96f5cab6a2d0fb3c4c96c7a1bf992c776f10aa6e321157df8b07359bbfdc111587f529d3ed867b1c69a98f57fea6b", + "9107b995298a0a2becc7a1feecc6d8a0cae95d66384ef08adb9dc74023357fb5c1dac1ce9de936eb4015d276150a4933", + "aa7049b3ce18e503b8546b08ef48056780cfeb4a48e50f30d0da8a2b6261e77ed19c40bc8050df874e992072db591575", + "b28f8221b85d07f04d6037a56d96e621d4c25bf3aaff3e745231bcf102dfa34508ca92814854019487b6dcecdaa0bab0", + "a75e47260f047889767fc8cc7121440afa2b4fc372ebc1ef39f72912247ad2efa1e0dc4022d4c44ecab95032fa30df49", + "a76daaa9e8741e7d9a5970f10bc585ce42a3e5ce4e53faadf3327a3b7759223e35aeb30214c0ecf2bca46a2ea1c45855", + "a031dcf5b47643630aba6e0625c21da9e0f76388ea6bcdd33ede31f51a1d080ba322ba0c9aaa5137b18fd3c47453aec9", + "a9be92a80b0909c491cd9475001cc34ee1a766b95109cdc32c8cdfcf7135c8d0e862b8612d0ea79e74d02a09d5403993", + "b490893e8eb5f101b5178e6ff8279fe14eb78b764290095e6e595dfcc11371925dc0af4b9d4bce8e69ac83ce57984e3a", + "89ca38e186e1378b0778cb8d4f0f6d4eef4a15db97a4596a44621548090dfb893f833689b580b0f60a934fd31c271bb3", + "8b20e24ad933b9af0a55a6d34a08e10b832a10f389154dc0dec79b63a38b79ea2f0d9f4fa664b3c06b1b2437cb58236f", + "a1484f2b97137fb957daad064ca6cbe5b99549249ceb51f42e928ec091f94fed642ddffe3a9916769538decd0a9937bf", + "89abcc45efe76bec679ca35c27adbd66fb9712a278e3c8530ab25cfaf997765aee574f5c5745dbb873dbf7e961684347", + "8addebd6ef7609df215e006987040d0a643858f3a4d791beaa77177d67529160e645fac54f0d8acdcd5a088393cb6681", + "85e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588" + ] +} \ No newline at end of file diff --git a/README.md b/README.md index dfe2f3ca..26747dae 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Run truffle test: ```shell script truffle compile truffle migrate -truffle test +npm run truffle:test ``` Run hardhat test: diff --git a/abi/bscvalidatorset.abi b/abi/bscvalidatorset.abi index c3194b70..e1be421e 100644 --- a/abi/bscvalidatorset.abi +++ b/abi/bscvalidatorset.abi @@ -1,1016 +1,1374 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "batchTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "batchTransferFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "reason", - "type": "bytes" - } - ], - "name": "batchTransferLowerFailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "deprecatedDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address payable", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "directTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address payable", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "directTransferFail", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "failReasonWithStr", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "systemTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "unexpectedPackage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorEmptyJailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorFelony", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorJailed", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "validatorMisdemeanor", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "validatorSetUpdated", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "DUSTY_INCOMING", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_CHECK_VALIDATORS", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_LEN_OF_VAL_MISMATCH", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_RELAYFEE_TOO_LARGE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_UNKNOWN_PACKAGE_TYPE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "EXPIRE_TIME_SECOND_GAP", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_VALIDATORSET_BYTES", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "JAIL_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_NUM_OF_VALIDATORS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "PRECISION", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATORS_UPDATE_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "currentValidatorSet", - "outputs": [ - { - "internalType": "address", - "name": "consensusAddress", - "type": "address" - }, - { - "internalType": "address payable", - "name": "feeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "BBCFeeAddress", - "type": "address" - }, - { - "internalType": "uint64", - "name": "votingPower", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "jailed", - "type": "bool" - }, - { - "internalType": "uint256", - "name": "incoming", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "currentValidatorSetMap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "expireTimeSecondGap", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numOfJailed", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "totalInComing", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "responsePayload", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "valAddr", - "type": "address" - } - ], - "name": "deposit", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getValidators", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "getIncoming", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "misdemeanor", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "felony", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "batchTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "batchTransferFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "reason", + "type": "bytes" + } + ], + "name": "batchTransferLowerFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deprecatedDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address payable", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "directTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address payable", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "directTransferFail", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "failReasonWithStr", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "feeBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "systemTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "unexpectedPackage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "validatorDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "validatorEmptyJailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "validatorEnterMaintenance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "validatorExitMaintenance", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "validatorFelony", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "validatorJailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "validatorMisdemeanor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "validatorSetUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BURN_ADDRESS", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BURN_RATIO_SCALE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DUSTY_INCOMING", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EPOCH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_CHECK_VALIDATORS", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_LEN_OF_VAL_MISMATCH", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_RELAYFEE_TOO_LARGE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_UNKNOWN_PACKAGE_TYPE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EXPIRE_TIME_SECOND_GAP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_BURN_RATIO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_FINALITY_REWARD_RATIO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_MAINTAIN_SLASH_SCALE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_MAX_NUM_OF_MAINTAINING", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_NUM_OF_CABINETS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_VALIDATORSET_BYTES", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "JAIL_MESSAGE_TYPE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_NUM_OF_VALIDATORS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PRECISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATORS_UPDATE_MESSAGE_TYPE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "burnRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "burnRatioInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "currentValidatorSet", + "outputs": [ + { + "internalType": "address", + "name": "consensusAddress", + "type": "address" + }, + { + "internalType": "address payable", + "name": "feeAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "BBCFeeAddress", + "type": "address" + }, + { + "internalType": "uint64", + "name": "votingPower", + "type": "uint64" + }, + { + "internalType": "bool", + "name": "jailed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "incoming", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "currentValidatorSetMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "expireTimeSecondGap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finalityRewardRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maintainSlashScale", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumOfCandidates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumOfMaintaining", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxNumOfWorkingCandidates", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numOfCabinets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numOfJailed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numOfMaintaining", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "previousHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalInComing", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "validatorExtraSet", + "outputs": [ + { + "internalType": "uint256", + "name": "enterMaintenanceHeight", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isMaintaining", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "voteAddress", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "responsePayload", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "valAddr", + "type": "address" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "getLivingValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMiningValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + }, + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getValidators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "isWorkingValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "getIncoming", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "isCurrentValidator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "valAddrs", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "weights", + "type": "uint256[]" + } + ], + "name": "distributeFinalityReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "misdemeanor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "felony", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getCurrentValidatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "canEnterMaintenance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "enterMaintenance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exitMaintenance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/crosschain.abi b/abi/crosschain.abi index 815d0054..1e745920 100644 --- a/abi/crosschain.abi +++ b/abi/crosschain.abi @@ -1,864 +1,784 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": true, - "internalType": "address", - "name": "contractAddr", - "type": "address" - } - ], - "name": "addChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "chainId", - "type": "uint16" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "oracleSequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "packageSequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "crossChainPackage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bool", - "name": "isEnable", - "type": "bool" - } - ], - "name": "enableOrDisableChannel", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "packageType", - "type": "uint8" - }, - { - "indexed": true, - "internalType": "uint64", - "name": "packageSequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - } - ], - "name": "receivedPackage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "lowLevelData", - "type": "bytes" - } - ], - "name": "unexpectedFailureAssertionInPackageHandler", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "unexpectedRevertInPackageHandler", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint64", - "name": "packageSequence", - "type": "uint64" - }, - { - "indexed": true, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "payload", - "type": "bytes" - } - ], - "name": "unsupportedPackage", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "ACK_PACKAGE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_KEY_PREFIX", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "FAIL_ACK_PACKAGE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_BATCH_SIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STORE_NAME", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYN_PACKAGE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "batchSizeForOracle", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "name": "channelHandlerContractMap", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "name": "channelReceiveSequenceMap", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "name": "channelSendSequenceMap", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "name": "isRelayRewardFromSystemReward", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "oracleSequence", - "outputs": [ - { - "internalType": "int64", - "name": "", - "type": "int64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "previousTxHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - }, - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "name": "registeredContractChannelMap", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "txCounter", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint8", - "name": "packageType", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "relayFee", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "encodePayload", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "bytes", - "name": "payload", - "type": "bytes" - }, - { - "internalType": "bytes", - "name": "proof", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "packageSequence", - "type": "uint64" - }, - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - } - ], - "name": "handlePackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "relayFee", - "type": "uint256" - } - ], - "name": "sendSynPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + } + ], + "name": "addChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "chainId", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "oracleSequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "packageSequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "crossChainPackage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isEnable", + "type": "bool" + } + ], + "name": "enableOrDisableChannel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "packageType", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "uint64", + "name": "packageSequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + } + ], + "name": "receivedPackage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "lowLevelData", + "type": "bytes" + } + ], + "name": "unexpectedFailureAssertionInPackageHandler", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "reason", + "type": "string" + } + ], + "name": "unexpectedRevertInPackageHandler", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint64", + "name": "packageSequence", + "type": "uint64" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "payload", + "type": "bytes" + } + ], + "name": "unsupportedPackage", + "type": "event" + }, + { + "inputs": [], + "name": "ACK_PACKAGE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_KEY_PREFIX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FAIL_ACK_PACKAGE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_BATCH_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STORE_NAME", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYN_PACKAGE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchSizeForOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "channelHandlerContractMap", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "channelReceiveSequenceMap", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "channelSendSequenceMap", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "isRelayRewardFromSystemReward", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracleSequence", + "outputs": [ + { + "internalType": "int64", + "name": "", + "type": "int64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "previousTxHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "name": "registeredContractChannelMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "txCounter", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "packageType", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "relayFee", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "encodePayload", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "payload", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "packageSequence", + "type": "uint64" + }, + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + } + ], + "name": "handlePackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "relayFee", + "type": "uint256" + } + ], + "name": "sendSynPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/govhub.abi b/abi/govhub.abi index 981fd424..fb3a9020 100644 --- a/abi/govhub.abi +++ b/abi/govhub.abi @@ -1,458 +1,406 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes", - "name": "message", - "type": "bytes" - } - ], - "name": "failReasonWithBytes", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "message", - "type": "string" - } - ], - "name": "failReasonWithStr", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_TARGET_CONTRACT_FAIL", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_TARGET_NOT_CONTRACT", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "PARAM_UPDATE_MESSAGE_TYPE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "responsePayload", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "message", + "type": "bytes" + } + ], + "name": "failReasonWithBytes", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "message", + "type": "string" + } + ], + "name": "failReasonWithStr", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_TARGET_CONTRACT_FAIL", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_TARGET_NOT_CONTRACT", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "PARAM_UPDATE_MESSAGE_TYPE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "responsePayload", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/relayerhub.abi b/abi/relayerhub.abi index 719c4cc6..a4851bc2 100644 --- a/abi/relayerhub.abi +++ b/abi/relayerhub.abi @@ -1,475 +1,417 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_relayer", - "type": "address" - } - ], - "name": "relayerRegister", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_relayer", - "type": "address" - } - ], - "name": "relayerUnRegister", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_DUES", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_REQUIRED_DEPOSIT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "dues", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "requiredDeposit", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "register", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "unregister", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "isRelayer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_relayer", + "type": "address" + } + ], + "name": "relayerRegister", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_relayer", + "type": "address" + } + ], + "name": "relayerUnRegister", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_DUES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_REQUIRED_DEPOSIT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dues", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "requiredDeposit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "register", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "unregister", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "isRelayer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/relayerincentivize.abi b/abi/relayerincentivize.abi index b389ff6b..c452d088 100644 --- a/abi/relayerincentivize.abi +++ b/abi/relayerincentivize.abi @@ -1,807 +1,729 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "sequence", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "roundRewardForHeaderRelayer", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "roundRewardForTransferRelayer", - "type": "uint256" - } - ], - "name": "distributeCollectedReward", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "relayer", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "rewardToRelayer", - "type": "event" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CALLER_COMPENSATION_DENOMINATOR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CALLER_COMPENSATION_MOLECULE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "HEADER_RELAYER_REWARD_RATE_DENOMINATOR", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "HEADER_RELAYER_REWARD_RATE_MOLECULE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAXIMUM_WEIGHT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ROUND_SIZE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "callerCompensationDenominator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "callerCompensationMolecule", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "collectedRewardForHeaderRelayer", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "collectedRewardForTransferRelayer", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "countInRound", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "headerRelayerAddressRecord", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "headerRelayerRewardRateDenominator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "headerRelayerRewardRateMolecule", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "headerRelayersSubmitCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "packageRelayerAddressRecord", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "packageRelayersSubmitCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "relayerRewardVault", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "roundSequence", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "headerRelayerAddr", - "type": "address" - }, - { - "internalType": "address payable", - "name": "packageRelayer", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "fromSystemReward", - "type": "bool" - } - ], - "name": "addReward", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "relayerAddr", - "type": "address" - } - ], - "name": "claimRelayerReward", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "name": "calculateTransferRelayerWeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - } - ], - "name": "calculateHeaderRelayerWeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "sequence", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "roundRewardForHeaderRelayer", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "roundRewardForTransferRelayer", + "type": "uint256" + } + ], + "name": "distributeCollectedReward", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "relayer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rewardToRelayer", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CALLER_COMPENSATION_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CALLER_COMPENSATION_MOLECULE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HEADER_RELAYER_REWARD_RATE_DENOMINATOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "HEADER_RELAYER_REWARD_RATE_MOLECULE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_WEIGHT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ROUND_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "callerCompensationDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "callerCompensationMolecule", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "collectedRewardForHeaderRelayer", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "collectedRewardForTransferRelayer", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "countInRound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dynamicExtraIncentiveAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "headerRelayerAddressRecord", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "headerRelayerRewardRateDenominator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "headerRelayerRewardRateMolecule", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "headerRelayersSubmitCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "packageRelayerAddressRecord", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "packageRelayersSubmitCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "relayerRewardVault", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "roundSequence", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "headerRelayerAddr", + "type": "address" + }, + { + "internalType": "address payable", + "name": "packageRelayer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "fromSystemReward", + "type": "bool" + } + ], + "name": "addReward", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "relayerAddr", + "type": "address" + } + ], + "name": "claimRelayerReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "calculateTransferRelayerWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "calculateHeaderRelayerWeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/slashindicator.abi b/abi/slashindicator.abi index 60eb3d90..01450fad 100644 --- a/abi/slashindicator.abi +++ b/abi/slashindicator.abi @@ -1,674 +1,741 @@ [ - { - "anonymous": false, - "inputs": [], - "name": "crashResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "indicatorCleaned", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "code", - "type": "uint32" - } - ], - "name": "knownResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint32", - "name": "code", - "type": "uint32" - } - ], - "name": "unKnownResponse", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "validatorSlashed", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BSC_RELAYER_REWARD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "DECREASE_RATE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "FELONY_THRESHOLD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MISDEMEANOR_THRESHOLD", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "felonyThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "indicators", - "outputs": [ - { - "internalType": "uint256", - "name": "height", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "count", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "exist", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "misdemeanorThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "previousHeight", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "validators", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "slash", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "clean", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "validator", - "type": "address" - } - ], - "name": "getSlashIndicator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } + { + "anonymous": false, + "inputs": [], + "name": "crashResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "indicatorCleaned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "code", + "type": "uint32" + } + ], + "name": "knownResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "code", + "type": "uint32" + } + ], + "name": "unKnownResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "validatorSlashed", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BSC_RELAYER_REWARD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DECREASE_RATE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "FELONY_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_FINALITY_SLASH_REWARD_RATIO", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MISDEMEANOR_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "felonyThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finalitySlashRewardRatio", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "indicators", + "outputs": [ + { + "internalType": "uint256", + "name": "height", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "exist", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "misdemeanorThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "previousHeight", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "validators", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "slash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "clean", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "uint256", + "name": "srcNum", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "srcHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "tarNum", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "tarHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct SlashIndicator.VoteData", + "name": "voteA", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "srcNum", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "srcHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "tarNum", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "tarHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "sig", + "type": "bytes" + } + ], + "internalType": "struct SlashIndicator.VoteData", + "name": "voteB", + "type": "tuple" + }, + { + "internalType": "address", + "name": "valAddr", + "type": "address" + } + ], + "internalType": "struct SlashIndicator.FinalityEvidence", + "name": "_evidence", + "type": "tuple" + } + ], + "name": "submitFinalityViolationEvidence", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "sendFelonyPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "getSlashIndicator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSlashThresholds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/systemreward.abi b/abi/systemreward.abi index aca3233f..621ecc47 100644 --- a/abi/systemreward.abi +++ b/abi/systemreward.abi @@ -1,428 +1,429 @@ [ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "receiveDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "rewardEmpty", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "rewardTo", - "type": "event" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_REWARDS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "numOperator", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "claimRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "addr", - "type": "address" - } - ], - "name": "isOperator", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "receiveDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "rewardEmpty", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rewardTo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "updateOperator", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_REWARDS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "numOperator", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claimRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "isOperator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/tendermintlightclient.abi b/abi/tendermintlightclient.abi index 8ed2dc61..93dc47fc 100644 --- a/abi/tendermintlightclient.abi +++ b/abi/tendermintlightclient.abi @@ -1,657 +1,586 @@ [ - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "initHeight", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "appHash", - "type": "bytes32" - } - ], - "name": "initConsensusState", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "height", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "preValidatorSetChangeHeight", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "appHash", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bool", - "name": "validatorChanged", - "type": "bool" - } - ], - "name": "syncConsensusState", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_CONSENSUS_STATE_BYTES", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_REWARD_FOR_VALIDATOR_SER_CHANGE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "chainID", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "initialHeight", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "latestHeight", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "lightClientConsensusStates", - "outputs": [ - { - "internalType": "uint64", - "name": "preValidatorSetChangeHeight", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "appHash", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "curValidatorSetHash", - "type": "bytes32" - }, - { - "internalType": "bytes", - "name": "nextValidatorSet", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "rewardForValidatorSetChange", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "name": "submitters", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "bytes", - "name": "header", - "type": "bytes" - }, - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "syncTendermintHeader", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "isHeaderSynced", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "getAppHash", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint64", - "name": "height", - "type": "uint64" - } - ], - "name": "getSubmitter", - "outputs": [ - { - "internalType": "address payable", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getChainID", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "initHeight", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "appHash", + "type": "bytes32" + } + ], + "name": "initConsensusState", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "height", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "preValidatorSetChangeHeight", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "appHash", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "validatorChanged", + "type": "bool" + } + ], + "name": "syncConsensusState", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_CONSENSUS_STATE_BYTES", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_REWARD_FOR_VALIDATOR_SER_CHANGE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chainID", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialHeight", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "latestHeight", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "lightClientConsensusStates", + "outputs": [ + { + "internalType": "uint64", + "name": "preValidatorSetChangeHeight", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "appHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "curValidatorSetHash", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "nextValidatorSet", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rewardForValidatorSetChange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "submitters", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "header", + "type": "bytes" + }, + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "syncTendermintHeader", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "isHeaderSynced", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "getAppHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "height", + "type": "uint64" + } + ], + "name": "getSubmitter", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getChainID", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/tokenhub.abi b/abi/tokenhub.abi index b6fd77de..e7a4c756 100644 --- a/abi/tokenhub.abi +++ b/abi/tokenhub.abi @@ -1,1120 +1,1012 @@ [ - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "receiveDeposit", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "refundAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "status", - "type": "uint32" - } - ], - "name": "refundFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "refundAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "status", - "type": "uint32" - } - ], - "name": "refundSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "rewardTo", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "refundAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "transferInSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "senderAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "relayFee", - "type": "uint256" - } - ], - "name": "transferOutSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "unexpectedPackage", - "type": "event" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, - "inputs": [], - "name": "BEP2_TOKEN_DECIMALS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BEP2_TOKEN_SYMBOL_FOR_BNB", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INIT_MINIMUM_RELAY_FEE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAXIMUM_BEP20_SYMBOL_LEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_BEP2_TOTAL_SUPPLY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_GAS_FOR_CALLING_BEP20", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_GAS_FOR_TRANSFER_BNB", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MINIMUM_BEP20_SYMBOL_LEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "REWARD_UPPER_LIMIT", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TEN_DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_FAILURE_TIMEOUT", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_FAILURE_UNBOUND_TOKEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_FAILURE_UNKNOWN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_SUCCESS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "bep20ContractDecimals", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "relayFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "init", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address payable", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "claimRewards", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "getMiniRelayFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "expireTime", - "type": "uint64" - } - ], - "name": "transferOut", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address[]", - "name": "recipientAddrs", - "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "amounts", - "type": "uint256[]" - }, - { - "internalType": "address[]", - "name": "refundAddrs", - "type": "address[]" - }, - { - "internalType": "uint64", - "name": "expireTime", - "type": "uint64" - } - ], - "name": "batchTransferOutBNB", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes32", - "name": "bep2Symbol", - "type": "bytes32" - } - ], - "name": "getContractAddrByBEP2Symbol", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - } - ], - "name": "getBep2SymbolByContractAddr", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "bytes32", - "name": "bep2Symbol", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "decimals", - "type": "uint256" - } - ], - "name": "bindToken", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "bytes32", - "name": "bep2Symbol", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - } - ], - "name": "unbindToken", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - } - ], - "name": "getBoundContract", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - } - ], - "name": "getBoundBep2Symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "receiveDeposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "refundAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "status", + "type": "uint32" + } + ], + "name": "refundFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "refundAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "status", + "type": "uint32" + } + ], + "name": "refundSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rewardTo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "refundAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferInSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "senderAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "relayFee", + "type": "uint256" + } + ], + "name": "transferOutSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "unexpectedPackage", + "type": "event" + }, + { + "inputs": [], + "name": "BEP2_TOKEN_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BEP2_TOKEN_SYMBOL_FOR_BNB", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_MINIMUM_RELAY_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_BEP20_SYMBOL_LEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_BEP2_TOTAL_SUPPLY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_GAS_FOR_CALLING_BEP20", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_GAS_FOR_TRANSFER_BNB", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_BEP20_SYMBOL_LEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "REWARD_UPPER_LIMIT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TEN_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_FAILURE_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_FAILURE_UNBOUND_TOKEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_FAILURE_UNKNOWN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_SUCCESS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "bep20ContractDecimals", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "relayFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "claimRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getMiniRelayFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" + } + ], + "name": "transferOut", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "recipientAddrs", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "refundAddrs", + "type": "address[]" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" + } + ], + "name": "batchTransferOutBNB", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "bep2Symbol", + "type": "bytes32" + } + ], + "name": "getContractAddrByBEP2Symbol", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + } + ], + "name": "getBep2SymbolByContractAddr", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "bep2Symbol", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "decimals", + "type": "uint256" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "bep2Symbol", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "getBoundContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + } + ], + "name": "getBoundBep2Symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file diff --git a/abi/tokenmanager.abi b/abi/tokenmanager.abi index 1d03235b..8a0e31d1 100644 --- a/abi/tokenmanager.abi +++ b/abi/tokenmanager.abi @@ -1,1202 +1,1055 @@ [ - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint32", - "name": "failedReason", - "type": "uint32" - } - ], - "name": "bindFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "peggyAmount", - "type": "uint256" - } - ], - "name": "bindSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "mirrorFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "bep2Symbol", - "type": "bytes32" - } - ], - "name": "mirrorSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "paramChange", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "reason", - "type": "string" - } - ], - "name": "syncFailure", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "bep20Addr", - "type": "address" - } - ], - "name": "syncSuccess", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "indexed": false, - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "unexpectedPackage", - "type": "event" - }, - { - "constant": true, - "inputs": [], - "name": "BEP2_TOKEN_DECIMALS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_PACKAGE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_ALREADY_BOUND_TOKEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_DECIMALS_MISMATCH", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_REJECTED", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_SUCCESS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_SYMBOL_MISMATCH", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_TIMEOUT", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_TOO_MUCH_TOKENHUB_BALANCE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "BIND_STATUS_TOTAL_SUPPLY_MISMATCH", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CODE_OK", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "CROSS_CHAIN_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "ERROR_FAIL_DECODE", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GOV_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "INCENTIVIZE_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "LIGHT_CLIENT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAXIMUM_BEP20_SYMBOL_LEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_BEP2_TOTAL_SUPPLY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MAX_GAS_FOR_TRANSFER_BNB", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MINIMUM_BEP20_SYMBOL_LEN", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MIRROR_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MIRROR_STATUS_ALREADY_BOUND", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MIRROR_STATUS_DUPLICATED_BEP2_SYMBOL", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MIRROR_STATUS_SUCCESS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "MIRROR_STATUS_TIMEOUT", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "RELAYERHUB_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SLASH_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "STAKING_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYNC_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYNC_STATUS_NOT_BOUND_MIRROR", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYNC_STATUS_SUCCESS", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYNC_STATUS_TIMEOUT", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "SYSTEM_REWARD_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TEN_DECIMALS", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_HUB_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TOKEN_MANAGER_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_IN_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "TRANSFER_OUT_CHANNELID", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "UNBIND_PACKAGE", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "VALIDATOR_CONTRACT_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "alreadyInit", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - } - ], - "name": "approveBind", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "bindPackageRecord", - "outputs": [ - { - "internalType": "uint8", - "name": "packageType", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "bep2TokenSymbol", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "internalType": "uint256", - "name": "totalSupply", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "peggyAmount", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "bep20Decimals", - "type": "uint8" - }, - { - "internalType": "uint64", - "name": "expireTime", - "type": "uint64" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "boundByMirror", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "bscChainID", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - } - ], - "name": "expireBind", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleFailAckPackage", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint8", - "name": "channelId", - "type": "uint8" - }, - { - "internalType": "bytes", - "name": "msgBytes", - "type": "bytes" - } - ], - "name": "handleSynPackage", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expireTime", - "type": "uint64" - } - ], - "name": "mirror", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "mirrorFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "mirrorPendingRecord", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "queryRequiredLockAmountForBind", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "contractAddr", - "type": "address" - }, - { - "internalType": "string", - "name": "bep2Symbol", - "type": "string" - } - ], - "name": "rejectBind", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "bep20Addr", - "type": "address" - }, - { - "internalType": "uint64", - "name": "expireTime", - "type": "uint64" - } - ], - "name": "sync", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "syncFee", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "string", - "name": "key", - "type": "string" - }, - { - "internalType": "bytes", - "name": "value", - "type": "bytes" - } - ], - "name": "updateParam", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "failedReason", + "type": "uint32" + } + ], + "name": "bindFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "peggyAmount", + "type": "uint256" + } + ], + "name": "bindSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "errCode", + "type": "uint8" + } + ], + "name": "mirrorFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "bep2Symbol", + "type": "bytes32" + } + ], + "name": "mirrorSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "errCode", + "type": "uint8" + } + ], + "name": "syncFailure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "bep20Addr", + "type": "address" + } + ], + "name": "syncSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "unexpectedPackage", + "type": "event" + }, + { + "inputs": [], + "name": "BEP2_TOKEN_DECIMALS", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_PACKAGE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_ALREADY_BOUND_TOKEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_DECIMALS_MISMATCH", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_REJECTED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_SYMBOL_MISMATCH", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_TOO_MUCH_TOKENHUB_BALANCE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BIND_STATUS_TOTAL_SUPPLY_MISMATCH", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LOG_MAX_UINT256", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAXIMUM_BEP20_SYMBOL_LEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_BEP2_TOTAL_SUPPLY", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_GAS_FOR_TRANSFER_BNB", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MINIMUM_BEP20_SYMBOL_LEN", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIRROR_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIRROR_STATUS_ALREADY_BOUND", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIRROR_STATUS_DUPLICATED_BEP2_SYMBOL", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIRROR_STATUS_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYNC_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYNC_STATUS_NOT_BOUND_MIRROR", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYNC_STATUS_TIMEOUT", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TEN_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNBIND_PACKAGE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "bindPackageRecord", + "outputs": [ + { + "internalType": "uint8", + "name": "packageType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "bep2TokenSymbol", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "totalSupply", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "peggyAmount", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "bep20Decimals", + "type": "uint8" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "boundByMirror", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "mirrorFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mirrorPendingRecord", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "channelId", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "approveBind", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddr", + "type": "address" + }, + { + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "rejectBind", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "bep2Symbol", + "type": "string" + } + ], + "name": "expireBind", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" + } + ], + "name": "mirror", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "bep20Addr", + "type": "address" + }, + { + "internalType": "uint64", + "name": "expireTime", + "type": "uint64" + } + ], + "name": "sync", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "symbol", + "type": "string" + } + ], + "name": "queryRequiredLockAmountForBind", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } ] \ No newline at end of file diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index 05855b42..e28eb662 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -33,7 +33,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public constant EXPIRE_TIME_SECOND_GAP = 1000; uint256 public constant MAX_NUM_OF_VALIDATORS = 41; - bytes public constant INIT_VALIDATORSET_BYTES = hex"f84580f842f840949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164"; + bytes public constant INIT_VALIDATORSET_BYTES = hex"f87680f873f871949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164b085e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588"; uint32 public constant ERROR_UNKNOWN_PACKAGE_TYPE = 101; uint32 public constant ERROR_FAIL_CHECK_VALIDATORS = 102; @@ -77,7 +77,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public maxNumOfWorkingCandidates; // BEP-126 Fast Finality - uint256 public constant FINALITY_REWARD_RATIO = 10; + uint256 public constant INIT_FINALITY_REWARD_RATIO = 10; uint256 public finalityRewardRatio; uint256 public previousHeight; @@ -131,7 +131,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } modifier oncePerBlock() { - require(block.number > previousHeight, "can not distribute finality reward twice in one block"); + require(block.number > previousHeight, "can not do this twice in one block"); _; previousHeight = block.number; } @@ -519,7 +519,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyInit { if (finalityRewardRatio == 0) { - finalityRewardRatio = FINALITY_REWARD_RATIO; + finalityRewardRatio = INIT_FINALITY_REWARD_RATIO; } uint256 totalValue; @@ -685,7 +685,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (Memory.compareStrings(key, "finalityRewardRatio")) { require(value.length == 32, "length of finalityRewardRatio mismatch"); uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); - require(newFinalityRewardRatio >= 10 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); diff --git a/contracts/BSCValidatorSet.template b/contracts/BSCValidatorSet.template index 72d734d8..6c69a090 100644 --- a/contracts/BSCValidatorSet.template +++ b/contracts/BSCValidatorSet.template @@ -76,7 +76,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public maxNumOfWorkingCandidates; // BEP-126 Fast Finality - uint256 public constant FINALITY_REWARD_RATIO = 10; + uint256 public constant INIT_FINALITY_REWARD_RATIO = 10; uint256 public finalityRewardRatio; uint256 public previousHeight; @@ -130,7 +130,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } modifier oncePerBlock() { - require(block.number > previousHeight, "can not distribute finality reward twice in one block"); + require(block.number > previousHeight, "can not do this twice in one block"); _; previousHeight = block.number; } @@ -518,7 +518,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica function distributeFinalityReward(address[] calldata valAddrs, uint256[] calldata weights) external onlyCoinbase oncePerBlock onlyInit { if (finalityRewardRatio == 0) { - finalityRewardRatio = FINALITY_REWARD_RATIO; + finalityRewardRatio = INIT_FINALITY_REWARD_RATIO; } uint256 totalValue; @@ -684,7 +684,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (Memory.compareStrings(key, "finalityRewardRatio")) { require(value.length == 32, "length of finalityRewardRatio mismatch"); uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); - require(newFinalityRewardRatio >= 10 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index f48ffef9..c86e6101 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -3,7 +3,6 @@ pragma experimental ABIEncoderV2; import "./System.sol"; import "./lib/BytesToTypes.sol"; -import "./lib/BytesLib.sol"; import "./lib/TypesToBytes.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; @@ -34,10 +33,8 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati uint256 public felonyThreshold; // BEP-126 Fast Finality - uint256 public constant FINALITY_DISTANCE = 11; - uint256 public constant FINALITY_SLASH_REWARD_RATIO = 20; + uint256 public constant INIT_FINALITY_SLASH_REWARD_RATIO = 20; - uint256 public finalityDistance; uint256 public finalitySlashRewardRatio; event validatorSlashed(address indexed validator); @@ -55,13 +52,17 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } // Proof that a validator misbehaved in fast finality + struct VoteData { + uint256 srcNum; + bytes32 srcHash; + uint256 tarNum; + bytes32 tarHash; + bytes sig; + } + struct FinalityEvidence { - uint256 numA; - bytes32 headerA; - bytes sigA; - uint256 numB; - bytes32 headerB; - bytes sigB; + VoteData voteA; + VoteData voteB; address valAddr; } @@ -184,28 +185,23 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } function submitFinalityViolationEvidence(FinalityEvidence calldata _evidence) external onlyInit onlyRelayer { - if (finalityDistance == 0 || finalitySlashRewardRatio == 0) { - finalityDistance = FINALITY_DISTANCE; - finalitySlashRewardRatio = FINALITY_SLASH_REWARD_RATIO; + if (finalitySlashRewardRatio == 0) { + finalitySlashRewardRatio = INIT_FINALITY_SLASH_REWARD_RATIO; } - - require( - (_evidence.numA < _evidence.numB && _evidence.numA + finalityDistance >= _evidence.numB) || - (_evidence.numB < _evidence.numA && _evidence.numB + finalityDistance >= _evidence.numA), - "too long distance between blocks" - ); - require( - _evidence.numA < block.number && _evidence.numA + 256 > block.number && - _evidence.numB < block.number && _evidence.numB + 256 > block.number, - "block number out of range" - ); - - bytes32 _headerA = blockhash(_evidence.numA); - bytes32 _headerB = blockhash(_evidence.numB); - if (_headerA != _evidence.headerA && _headerB != _evidence.headerB) { - revert(string(abi.encodePacked("neither header is in local fork"))); - } else if (_headerA == _evidence.headerA && _headerB == _evidence.headerB) { - revert(string(abi.encodePacked("both headers are in local fork"))); + uint256 srcNumA = _evidence.voteA.srcNum; + uint256 tarNumA = _evidence.voteA.tarNum; + uint256 srcNumB = _evidence.voteB.srcNum; + uint256 tarNumB = _evidence.voteB.tarNum; + + require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && + _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); + require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); + + // Vote rules check + if (!((srcNumA < srcNumB && srcNumB < tarNumB && tarNumB < tarNumA) || + (srcNumB < srcNumA && srcNumA < tarNumA && tarNumA < tarNumB)) && + !(tarNumA == tarNumB)) { + revert(string(abi.encodePacked("no violation of vote rules"))); } // BLS verification @@ -226,21 +222,26 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati // to avoid too deep stack { - bytes memory bytesNumA; - bytes memory bytesNumB; - bytes memory bytesHeaderA; - bytes memory bytesHeaderB; - TypesToBytes.uintToBytes(32, _evidence.numA, bytesNumA); - TypesToBytes.bytes32ToBytes(32, _evidence.headerA, bytesHeaderA); - TypesToBytes.uintToBytes(32, _evidence.numB, bytesNumB); - TypesToBytes.bytes32ToBytes(32, _evidence.headerB, bytesHeaderB); - - input = BytesLib.concat(bytesNumA, bytesHeaderA); - input = BytesLib.concat(input, _evidence.sigA); - input = BytesLib.concat(input, bytesNumB); - input = BytesLib.concat(input, bytesHeaderB); - input = BytesLib.concat(input, _evidence.sigB); - input = BytesLib.concat(input, voteAddress); + bytes memory pre = new bytes(32); + bytes memory cur = new bytes(32); + TypesToBytes.uintToBytes(32, srcNumA, pre); + TypesToBytes.uintToBytes(32, tarNumA, cur); + input = abi.encodePacked(pre, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteA.sig); + TypesToBytes.uintToBytes(32, srcNumB, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.uintToBytes(32, tarNumB, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteB.sig); + input = abi.encodePacked(input, voteAddress); } // call the precompiled contract to verify the BLS signature @@ -257,7 +258,6 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); emit validatorSlashed(_evidence.valAddr); - } function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { @@ -276,11 +276,6 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); felonyThreshold = newFelonyThreshold; - } else if (Memory.compareStrings(key, "finalityDistance")) { - require(value.length == 32, "length of finalityDistance mismatch"); - uint256 newFinalityDistance = BytesToTypes.bytesToUint256(32, value); - require(newFinalityDistance >= 1 && newFinalityDistance <= 21, "the finality distance out of range"); - finalityDistance = newFinalityDistance; } else if (Memory.compareStrings(key, "finalitySlashRewardRatio")) { require(value.length == 32, "length of finalitySlashRewardRatio mismatch"); uint256 newFinalitySlashRewardRatio = BytesToTypes.bytesToUint256(32, value); diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index f76cde2d..09c2e128 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -3,7 +3,6 @@ pragma experimental ABIEncoderV2; import "./System.sol"; import "./lib/BytesToTypes.sol"; -import "./lib/BytesLib.sol"; import "./lib/TypesToBytes.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; @@ -34,10 +33,8 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati uint256 public felonyThreshold; // BEP-126 Fast Finality - uint256 public constant FINALITY_DISTANCE = 11; - uint256 public constant FINALITY_SLASH_REWARD_RATIO = 20; + uint256 public constant INIT_FINALITY_SLASH_REWARD_RATIO = 20; - uint256 public finalityDistance; uint256 public finalitySlashRewardRatio; event validatorSlashed(address indexed validator); @@ -55,13 +52,17 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } // Proof that a validator misbehaved in fast finality + struct VoteData { + uint256 srcNum; + bytes32 srcHash; + uint256 tarNum; + bytes32 tarHash; + bytes sig; + } + struct FinalityEvidence { - uint256 numA; - bytes32 headerA; - bytes sigA; - uint256 numB; - bytes32 headerB; - bytes sigB; + VoteData voteA; + VoteData voteB; address valAddr; } @@ -190,28 +191,23 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } function submitFinalityViolationEvidence(FinalityEvidence calldata _evidence) external onlyInit onlyRelayer { - if (finalityDistance == 0 || finalitySlashRewardRatio == 0) { - finalityDistance = FINALITY_DISTANCE; - finalitySlashRewardRatio = FINALITY_SLASH_REWARD_RATIO; + if (finalitySlashRewardRatio == 0) { + finalitySlashRewardRatio = INIT_FINALITY_SLASH_REWARD_RATIO; } + uint256 srcNumA = _evidence.voteA.srcNum; + uint256 tarNumA = _evidence.voteA.tarNum; + uint256 srcNumB = _evidence.voteB.srcNum; + uint256 tarNumB = _evidence.voteB.tarNum; - require( - (_evidence.numA < _evidence.numB && _evidence.numA + finalityDistance >= _evidence.numB) || - (_evidence.numB < _evidence.numA && _evidence.numB + finalityDistance >= _evidence.numA), - "too long distance between blocks" - ); - require( - _evidence.numA < block.number && _evidence.numA + 256 > block.number && - _evidence.numB < block.number && _evidence.numB + 256 > block.number, - "block number out of range" - ); + require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && + _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); + require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); - bytes32 _headerA = blockhash(_evidence.numA); - bytes32 _headerB = blockhash(_evidence.numB); - if (_headerA != _evidence.headerA && _headerB != _evidence.headerB) { - revert(string(abi.encodePacked("neither header is in local fork"))); - } else if (_headerA == _evidence.headerA && _headerB == _evidence.headerB) { - revert(string(abi.encodePacked("both headers are in local fork"))); + // Vote rules check + if (!((srcNumA < srcNumB && srcNumB < tarNumB && tarNumB < tarNumA) || + (srcNumB < srcNumA && srcNumA < tarNumA && tarNumA < tarNumB)) && + !(tarNumA == tarNumB)) { + revert(string(abi.encodePacked("no violation of vote rules"))); } // BLS verification @@ -232,21 +228,26 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati // to avoid too deep stack { - bytes memory bytesNumA; - bytes memory bytesNumB; - bytes memory bytesHeaderA; - bytes memory bytesHeaderB; - TypesToBytes.uintToBytes(32, _evidence.numA, bytesNumA); - TypesToBytes.bytes32ToBytes(32, _evidence.headerA, bytesHeaderA); - TypesToBytes.uintToBytes(32, _evidence.numB, bytesNumB); - TypesToBytes.bytes32ToBytes(32, _evidence.headerB, bytesHeaderB); - - input = BytesLib.concat(bytesNumA, bytesHeaderA); - input = BytesLib.concat(input, _evidence.sigA); - input = BytesLib.concat(input, bytesNumB); - input = BytesLib.concat(input, bytesHeaderB); - input = BytesLib.concat(input, _evidence.sigB); - input = BytesLib.concat(input, voteAddress); + bytes memory pre = new bytes(32); + bytes memory cur = new bytes(32); + TypesToBytes.uintToBytes(32, srcNumA, pre); + TypesToBytes.uintToBytes(32, tarNumA, cur); + input = abi.encodePacked(pre, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteA.sig); + TypesToBytes.uintToBytes(32, srcNumB, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.uintToBytes(32, tarNumB, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); + input = abi.encodePacked(input, cur); + TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteB.sig); + input = abi.encodePacked(input, voteAddress); } // call the precompiled contract to verify the BLS signature @@ -263,7 +264,6 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); emit validatorSlashed(_evidence.valAddr); - } function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { @@ -282,11 +282,6 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); felonyThreshold = newFelonyThreshold; - } else if (Memory.compareStrings(key, "finalityDistance")) { - require(value.length == 32, "length of finalityDistance mismatch"); - uint256 newFinalityDistance = BytesToTypes.bytesToUint256(32, value); - require(newFinalityDistance >= 1 && newFinalityDistance <= 21, "the finality distance out of range"); - finalityDistance = newFinalityDistance; } else if (Memory.compareStrings(key, "finalitySlashRewardRatio")) { require(value.length == 32, "length of finalitySlashRewardRatio mismatch"); uint256 newFinalitySlashRewardRatio = BytesToTypes.bytesToUint256(32, value); diff --git a/generate-validator.js b/generate-validator.js index b23556fb..338d3605 100644 --- a/generate-validator.js +++ b/generate-validator.js @@ -1,35 +1,38 @@ const fs = require("fs"); -const readline = require('readline'); +const readline = require("readline"); const nunjucks = require("nunjucks"); - +const BLSKeys = require("./BLSkeystore.json"); async function processValidatorConf() { - const fileStream = fs.createReadStream(__dirname + '/validators.conf'); + const fileStream = fs.createReadStream(__dirname + "/validators.conf"); + const publicKey = BLSKeys.public_key; const rl = readline.createInterface({ input: fileStream, - crlfDelay: Infinity + crlfDelay: Infinity, }); let validators = []; for await (const line of rl) { // Each line in input.txt will be successively available here as `line`. - let vs = line.split(",") + let vs = line.split(","); validators.push({ consensusAddr: vs[0], feeAddr: vs[1], bscFeeAddr: vs[2], votingPower: vs[3], - }) + bLSPublicKey: "0x" + publicKey.pop() + }); } return validators } -processValidatorConf().then(function (validators) { +processValidatorConf().then(function (validators, bLSPublicKeys) { const data = { - validators: validators + validators: validators, + bLSPublicKeys: bLSPublicKeys, }; - const templateString = fs.readFileSync(__dirname + '/validators.template').toString(); + const templateString = fs.readFileSync(__dirname + "/validators.template").toString(); const resultString = nunjucks.renderString(templateString, data); - fs.writeFileSync(__dirname + '/validators.js', resultString); + fs.writeFileSync(__dirname + "/validators.js", resultString); console.log("BSCValidatorSet file updated."); -}) +}); diff --git a/genesis-template.json b/genesis-template.json index ad3fd015..af1d4ef5 100644 --- a/genesis-template.json +++ b/genesis-template.json @@ -13,6 +13,11 @@ "muirGlacierBlock": 0, "ramanujanBlock": 0, "nielsBlock": 0, + "eulerBlock": 0, + "brunoBlock": 0, + "mirrorSyncBlock": 0, + "bonehBlock": 0, + "lynnBlock": 0, "parlia": { "period": 3, "epoch": 200 diff --git a/genesis.json b/genesis.json index 44ae7fce..c4eda28e 100644 --- a/genesis.json +++ b/genesis.json @@ -13,6 +13,11 @@ "muirGlacierBlock": 0, "ramanujanBlock": 0, "nielsBlock": 0, + "eulerBlock": 0, + "brunoBlock": 0, + "mirrorSyncBlock": 0, + "bonehBlock": 0, + "lynnBlock": 0, "parlia": { "period": 3, "epoch": 200 diff --git a/test/GovHub.js b/test/GovHub.js index 660b83f0..0280363c 100644 --- a/test/GovHub.js +++ b/test/GovHub.js @@ -533,21 +533,6 @@ contract("GovHub others", (accounts) => { return ev.message === "the misdemeanorThreshold out of range"; }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "finalityDistance", - "0x000000000000000000000000000000000000000000000000000000000000000f", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "finalityDistance"; - }); - let finalityDistance = await slashIndicator.finalityDistance.call(); - assert.equal(finalityDistance.toNumber(), 15, "value not equal"); - tx = await govHubInstance.handleSynPackage( GOV_CHANNEL_ID, serialize( diff --git a/test/Slash.js b/test/Slash.js index 9a4ed158..007ae149 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -346,7 +346,7 @@ contract("Clean SlashIndicator", (accounts) => { }); contract("finality slash SlashIndicator", (accounts) => { - it("valid finality evidence", async () => { + it("valid finality evidence: same target block", async () => { const slashInstance = await SlashIndicator.deployed(); const systemRewardInstance = await SystemReward.deployed(); let relayerAccount = accounts[8]; @@ -355,18 +355,38 @@ contract("finality slash SlashIndicator", (accounts) => { await systemRewardInstance.addOperator(slashInstance.address); let currentNumber = await web3.eth.getBlockNumber(); - let blockNumberA = currentNumber - 5; - let blockHashA = await web3.eth.getBlock(blockNumberA).then((x) => { + let srcNumA = currentNumber - 20; + let tarNumA = currentNumber - 10; + let srcNumB = currentNumber - 15; + let tarNumB = tarNumA; + let srcHashA = await web3.eth.getBlock(srcNumA).then((x) => { return x.hash; }); - + let tarHashA = await web3.eth.getBlock(tarNumA).then((x) => { + return x.hash; + }); + let srcHashB = await web3.eth.getBlock(srcNumB).then((x) => { + return x.hash; + }); + let tarHashB = tarHashA; + + let voteDataA = { + srcNum: srcNumA, + tarNum: tarNumA, + srcHash: srcHashA, + tarHash: tarHashA, + sig: Buffer.from("sigA") + } + let voteDataB = { + srcNum: srcNumB, + tarNum: tarNumB, + srcHash: srcHashB, + tarHash: tarHashB, + sig: Buffer.from("sigB") + } let evidence = { - numA: blockNumberA, - headerA: blockHashA, - sigA: Buffer.from("sigA"), - numB: currentNumber - 10, - headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigB: Buffer.from("sigB"), + voteA: voteDataA, + voteB: voteDataB, valAddr: accounts[0], }; @@ -378,88 +398,133 @@ contract("finality slash SlashIndicator", (accounts) => { }); }); - it("invalid finality evidence", async () => { + it("valid finality evidence: vote within span", async () => { const slashInstance = await SlashIndicator.deployed(); let relayerAccount = accounts[8]; let currentNumber = await web3.eth.getBlockNumber(); - let blockNumberA = currentNumber - 5; - let blockHashA = await web3.eth.getBlock(blockNumberA).then((x) => { + let srcNumA = currentNumber - 20; + let tarNumA = currentNumber - 10; + let srcNumB = currentNumber - 18; + let tarNumB = currentNumber - 15; + let srcHashA = await web3.eth.getBlock(srcNumA).then((x) => { return x.hash; }); - let evidence1 = { - numA: blockNumberA, - headerA: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigA: Buffer.from("sigA"), - numB: currentNumber - 10, - headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigB: Buffer.from("sigB"), - valAddr: accounts[0], - }; - let evidence2 = { - numA: blockNumberA, - headerA: blockHashA, - sigA: Buffer.from("sigA"), - numB: blockNumberA - 15, - headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigB: Buffer.from("sigB"), - valAddr: accounts[0], - }; - let evidence3 = { - numA: blockNumberA, - headerA: blockHashA, - sigA: Buffer.from("sigA"), - numB: currentNumber - 10, - headerB: await web3.eth.getBlock(currentNumber - 10).then((x) => { - return x.hash; - }), - sigB: Buffer.from("sigB"), + let tarHashA = await web3.eth.getBlock(tarNumA).then((x) => { + return x.hash; + }); + let srcHashB = await web3.eth.getBlock(srcNumA).then((x) => { + return x.hash; + }); + let tarHashB = await web3.eth.getBlock(tarNumB).then((x) => { + return x.hash; + }); + + let voteDataA = { + srcNum: srcNumA, + tarNum: tarNumA, + srcHash: srcHashA, + tarHash: tarHashA, + sig: Buffer.from("sigA") + } + let voteDataB = { + srcNum: srcNumB, + tarNum: tarNumB, + srcHash: srcHashB, + tarHash: tarHashB, + sig: Buffer.from("sigB") + } + let evidence = { + voteA: voteDataA, + voteB: voteDataB, valAddr: accounts[0], }; - let evidence4 = { - numA: currentNumber - 257, - headerA: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigA: Buffer.from("sigA"), - numB: currentNumber - 258, - headerB: "0x0000000000000000000000000000000000000000000000000000000000000000", - sigB: Buffer.from("sigB"), + + let tx = await slashInstance.submitFinalityViolationEvidence(evidence, { + from: relayerAccount, + }); + truffleAssert.eventEmitted(tx, "validatorSlashed", (ev) => { + return ev.validator === accounts[0]; + }); + }); + + it("invalid finality evidence", async () => { + const slashInstance = await SlashIndicator.deployed(); + let relayerAccount = accounts[8]; + + let currentNumber = await web3.eth.getBlockNumber(); + let srcNumA = currentNumber - 20; + let tarNumA = currentNumber - 10; + let srcNumB = currentNumber - 18; + let tarNumB = currentNumber - 12; + let srcHashA = await web3.eth.getBlock(srcNumA).then((x) => { + return x.hash; + }); + let tarHashA = await web3.eth.getBlock(tarNumA).then((x) => { + return x.hash; + }); + let srcHashB = await web3.eth.getBlock(srcNumA).then((x) => { + return x.hash; + }); + let tarHashB = await web3.eth.getBlock(tarNumB).then((x) => { + return x.hash; + }); + + let voteDataA = { + srcNum: srcNumA, + tarNum: tarNumA, + srcHash: srcHashA, + tarHash: tarHashA, + sig: Buffer.from("sigA") + } + let voteDataB = { + srcNum: srcNumB, + tarNum: tarNumB, + srcHash: srcHashB, + tarHash: tarHashB, + sig: Buffer.from("sigB") + } + let evidence = { + voteA: voteDataA, + voteB: voteDataB, valAddr: accounts[0], }; + evidence.voteA.tarNum = evidence.voteA.srcNum - 1; + let evidence1 = evidence; try { await slashInstance.submitFinalityViolationEvidence(evidence1, { from: relayerAccount }); assert.fail(); } catch (error) { assert.ok( - error.toString().includes("neither header is in local fork"), - "two headers from other fork should not be ok" + error.toString().includes("source number bigger than target number"), + "source number must smaller than target number" ); } + + evidence.voteA.tarNum = currentNumber - 10; + evidence.voteB.tarNum = currentNumber - 8; + let evidence2 = evidence; try { await slashInstance.submitFinalityViolationEvidence(evidence2, { from: relayerAccount }); assert.fail(); } catch (error) { assert.ok( - error.toString().includes("too long distance between blocks"), - "two blocks' number larger than 11 should not be ok" + error.toString().includes("no violation of vote rules"), + "no violation of vote rules" ); } + + evidence.voteB.tarNum = currentNumber - 12; + evidence.valAddr = accounts[1]; + let evidence3 = evidence; try { await slashInstance.submitFinalityViolationEvidence(evidence3, { from: relayerAccount }); assert.fail(); } catch (error) { assert.ok( - error.toString().includes("both headers are in local fork"), - "two headers from one fork should not be ok" - ); - } - try { - await slashInstance.submitFinalityViolationEvidence(evidence4, { from: relayerAccount }); - assert.fail(); - } catch (error) { - assert.ok( - error.toString().includes("block number out of range"), - "256 block before current height should not be ok" + error.toString().includes("validator not exist"), + "validator not exist" ); } }); diff --git a/validators.js b/validators.js index 355e0a99..9573a57d 100644 --- a/validators.js +++ b/validators.js @@ -10,44 +10,50 @@ const validators = [ votingPower: 0x0000000000000064 } ]; +const bLSPublicKeys = [ + "0x85e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588", +]; // =============== Do not edit below ==== -function generateExtradata(validators) { - let extraVanity =Buffer.alloc(32); - let validatorsBytes = extraDataSerialize(validators); - let extraSeal =Buffer.alloc(65); - return Buffer.concat([extraVanity,validatorsBytes,extraSeal]); +function generateExtradata(validators, bLSPublicKeys) { + let extraVanity = Buffer.alloc(32); + let validatorsBytes = extraDataSerialize(validators, bLSPublicKeys); + let extraSeal = Buffer.alloc(65); + return Buffer.concat([extraVanity, validatorsBytes, extraSeal]); } -function extraDataSerialize(validators) { +function extraDataSerialize(validators, bLSPublicKeys) { let n = validators.length; let arr = []; - for(let i = 0;i Date: Mon, 25 Apr 2022 15:44:23 +0800 Subject: [PATCH 05/48] Revert code format changes --- contracts/CrossChain.sol | 48 +- contracts/CrossChain.template | 48 +- contracts/RelayerIncentivize.sol | 78 +- contracts/RelayerIncentivize.template | 78 +- contracts/SlashIndicator.sol | 53 +- contracts/SlashIndicator.template | 56 +- contracts/System.sol | 2 +- contracts/System.template | 12 +- contracts/SystemReward.sol | 9 +- contracts/SystemReward.template | 13 +- contracts/TendermintLightClient.sol | 52 +- contracts/TendermintLightClient.template | 52 +- contracts/TokenHub.sol | 278 +-- contracts/TokenHub.template | 278 +-- contracts/interface/IBSCValidatorSet.sol | 2 +- generate-validator.js | 12 +- test/BSCValidatorSet.js | 801 +++---- test/GovHub.js | 1056 ++++----- test/RelayerHub.js | 52 +- test/Slash.js | 327 ++- test/SystemReward.js | 38 +- test/TestRelayerIncentivize.js | 742 +++--- test/TestTendermintLightClient.js | 31 +- test/TestTokenHub.js | 2749 +++++++++------------- test/ToolTest.js | 17 +- truffle-config.js | 4 +- validators.js | 6 +- validators.template | 12 +- 28 files changed, 2965 insertions(+), 3941 deletions(-) diff --git a/contracts/CrossChain.sol b/contracts/CrossChain.sol index bfc529b6..53ede1eb 100644 --- a/contracts/CrossChain.sol +++ b/contracts/CrossChain.sol @@ -12,7 +12,7 @@ import "./System.sol"; import "./MerkleProof.sol"; -contract CrossChain is System, ICrossChain, IParamSubscriber { +contract CrossChain is System, ICrossChain, IParamSubscriber{ // constant variables string constant public STORE_NAME = "ibc"; @@ -49,7 +49,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { uint64 expectedSequence = channelReceiveSequenceMap[_channelID]; require(_sequence == expectedSequence, "sequence not in order"); - channelReceiveSequenceMap[_channelID] = expectedSequence + 1; + channelReceiveSequenceMap[_channelID]=expectedSequence+1; _; } @@ -59,7 +59,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } modifier channelSupported(uint8 _channelID) { - require(channelHandlerContractMap[_channelID] != address(0x0), "channel is not supported"); + require(channelHandlerContractMap[_channelID]!=address(0x0), "channel is not supported"); _; } @@ -70,7 +70,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { // | length | prefix | sourceChainID| destinationChainID | channelID | sequence | // | 32 bytes | 1 byte | 2 bytes | 2 bytes | 1 bytes | 8 bytes | - function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns (bytes memory) { + function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns(bytes memory) { uint256 fullCROSS_CHAIN_KEY_PREFIX = CROSS_CHAIN_KEY_PREFIX | _channelID; bytes memory key = new bytes(14); @@ -120,37 +120,37 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { batchSizeForOracle = INIT_BATCH_SIZE; - oracleSequence = - 1; + oracleSequence = -1; previousTxHeight = 0; txCounter = 0; - alreadyInit = true; + alreadyInit=true; } - function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns (bytes memory) { +function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { uint256 payloadLength = msgBytes.length + 33; bytes memory payload = new bytes(payloadLength); uint256 ptr; assembly { ptr := payload } - ptr += 33; + ptr+=33; assembly { mstore(ptr, relayFee) } - ptr -= 32; + ptr-=32; assembly { mstore(ptr, packageType) } - ptr -= 1; + ptr-=1; assembly { mstore(ptr, payloadLength) } - ptr += 65; + ptr+=65; (uint256 src,) = Memory.fromBytes(msgBytes); Memory.copy(src, ptr, msgBytes.length); @@ -159,7 +159,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { // | type | relayFee |package | // | 1 byte | 32 bytes | bytes | - function decodePayloadHeader(bytes memory payload) internal pure returns (bool, uint8, uint256, bytes memory) { + function decodePayloadHeader(bytes memory payload) internal pure returns(bool, uint8, uint256, bytes memory) { if (payload.length < 33) { return (false, 0, 0, new bytes(0)); } @@ -170,27 +170,27 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } uint8 packageType; - ptr += 1; + ptr+=1; assembly { packageType := mload(ptr) } uint256 relayFee; - ptr += 32; + ptr+=32; assembly { relayFee := mload(ptr) } - ptr += 32; - bytes memory msgBytes = new bytes(payload.length - 33); - (uint256 dst,) = Memory.fromBytes(msgBytes); - Memory.copy(ptr, dst, payload.length - 33); + ptr+=32; + bytes memory msgBytes = new bytes(payload.length-33); + (uint256 dst, ) = Memory.fromBytes(msgBytes); + Memory.copy(ptr, dst, payload.length-33); return (true, packageType, relayFee, msgBytes); } function handlePackage(bytes calldata payload, bytes calldata proof, uint64 height, uint64 packageSequence, uint8 channelId) onlyInit onlyRelayer - sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { + sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { bytes memory payloadLocal = payload; // fix error: stack too deep, try removing local variables bytes memory proofLocal = proof; // fix error: stack too deep, try removing local variables require(MerkleProof.validateMerkleProof(ILightClient(LIGHT_CLIENT_ADDR).getAppHash(height), STORE_NAME, generateKey(packageSequence, channelId), payloadLocal, proofLocal), "invalid merkle proof"); @@ -207,7 +207,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { if (packageType == SYN_PACKAGE) { address handlerContract = channelHandlerContractMap[channelIdLocal]; try IApplication(handlerContract).handleSynPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { - if (responsePayload.length != 0) { + if (responsePayload.length!=0) { sendPackage(channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(ACK_PACKAGE, 0, responsePayload)); channelSendSequenceMap[channelIdLocal] = channelSendSequenceMap[channelIdLocal] + 1; } @@ -244,10 +244,10 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { if (block.number > previousTxHeight) { oracleSequence++; txCounter = 1; - previousTxHeight = block.number; + previousTxHeight=block.number; } else { txCounter++; - if (txCounter > batchSizeForOracle) { + if (txCounter>batchSizeForOracle) { oracleSequence++; txCounter = 1; } @@ -287,7 +287,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } require(isContract(handlerContract), "address is not a contract"); - channelHandlerContractMap[channelId] = handlerContract; + channelHandlerContractMap[channelId]=handlerContract; registeredContractChannelMap[handlerContract][channelId] = true; isRelayRewardFromSystemReward[channelId] = isRewardFromSystem; emit addChannel(channelId, handlerContract); @@ -306,7 +306,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { bool isEnable = (status == 1); address handlerContract = channelHandlerContractMap[channelId]; - if (handlerContract != address(0x00)) {//channel existing + if (handlerContract != address(0x00)) { //channel existing registeredContractChannelMap[handlerContract][channelId] = isEnable; emit enableOrDisableChannel(channelId, isEnable); } diff --git a/contracts/CrossChain.template b/contracts/CrossChain.template index 9b6234c1..c363268a 100644 --- a/contracts/CrossChain.template +++ b/contracts/CrossChain.template @@ -13,7 +13,7 @@ import "./System.sol"; {% else %}import "./MerkleProof.sol"; {% endif %} -contract CrossChain is System, ICrossChain, IParamSubscriber { +contract CrossChain is System, ICrossChain, IParamSubscriber{ // constant variables string constant public STORE_NAME = "ibc"; @@ -50,7 +50,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { uint64 expectedSequence = channelReceiveSequenceMap[_channelID]; require(_sequence == expectedSequence, "sequence not in order"); - channelReceiveSequenceMap[_channelID] = expectedSequence + 1; + channelReceiveSequenceMap[_channelID]=expectedSequence+1; _; } @@ -60,7 +60,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } modifier channelSupported(uint8 _channelID) { - require(channelHandlerContractMap[_channelID] != address(0x0), "channel is not supported"); + require(channelHandlerContractMap[_channelID]!=address(0x0), "channel is not supported"); _; } @@ -71,7 +71,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { // | length | prefix | sourceChainID| destinationChainID | channelID | sequence | // | 32 bytes | 1 byte | 2 bytes | 2 bytes | 1 bytes | 8 bytes | - function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns (bytes memory) { + function generateKey(uint64 _sequence, uint8 _channelID) internal pure returns(bytes memory) { uint256 fullCROSS_CHAIN_KEY_PREFIX = CROSS_CHAIN_KEY_PREFIX | _channelID; bytes memory key = new bytes(14); @@ -121,37 +121,37 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { batchSizeForOracle = INIT_BATCH_SIZE; - oracleSequence = - 1; + oracleSequence = -1; previousTxHeight = 0; txCounter = 0; - alreadyInit = true; + alreadyInit=true; } - function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns (bytes memory) { +function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { uint256 payloadLength = msgBytes.length + 33; bytes memory payload = new bytes(payloadLength); uint256 ptr; assembly { ptr := payload } - ptr += 33; + ptr+=33; assembly { mstore(ptr, relayFee) } - ptr -= 32; + ptr-=32; assembly { mstore(ptr, packageType) } - ptr -= 1; + ptr-=1; assembly { mstore(ptr, payloadLength) } - ptr += 65; + ptr+=65; (uint256 src,) = Memory.fromBytes(msgBytes); Memory.copy(src, ptr, msgBytes.length); @@ -160,7 +160,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { // | type | relayFee |package | // | 1 byte | 32 bytes | bytes | - function decodePayloadHeader(bytes memory payload) internal pure returns (bool, uint8, uint256, bytes memory) { + function decodePayloadHeader(bytes memory payload) internal pure returns(bool, uint8, uint256, bytes memory) { if (payload.length < 33) { return (false, 0, 0, new bytes(0)); } @@ -171,27 +171,27 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } uint8 packageType; - ptr += 1; + ptr+=1; assembly { packageType := mload(ptr) } uint256 relayFee; - ptr += 32; + ptr+=32; assembly { relayFee := mload(ptr) } - ptr += 32; - bytes memory msgBytes = new bytes(payload.length - 33); - (uint256 dst,) = Memory.fromBytes(msgBytes); - Memory.copy(ptr, dst, payload.length - 33); + ptr+=32; + bytes memory msgBytes = new bytes(payload.length-33); + (uint256 dst, ) = Memory.fromBytes(msgBytes); + Memory.copy(ptr, dst, payload.length-33); return (true, packageType, relayFee, msgBytes); } function handlePackage(bytes calldata payload, bytes calldata proof, uint64 height, uint64 packageSequence, uint8 channelId) onlyInit onlyRelayer - sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { + sequenceInOrder(packageSequence, channelId) blockSynced(height) channelSupported(channelId) external { bytes memory payloadLocal = payload; // fix error: stack too deep, try removing local variables bytes memory proofLocal = proof; // fix error: stack too deep, try removing local variables require(MerkleProof.validateMerkleProof(ILightClient(LIGHT_CLIENT_ADDR).getAppHash(height), STORE_NAME, generateKey(packageSequence, channelId), payloadLocal, proofLocal), "invalid merkle proof"); @@ -208,7 +208,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { if (packageType == SYN_PACKAGE) { address handlerContract = channelHandlerContractMap[channelIdLocal]; try IApplication(handlerContract).handleSynPackage(channelIdLocal, msgBytes) returns (bytes memory responsePayload) { - if (responsePayload.length != 0) { + if (responsePayload.length!=0) { sendPackage(channelSendSequenceMap[channelIdLocal], channelIdLocal, encodePayload(ACK_PACKAGE, 0, responsePayload)); channelSendSequenceMap[channelIdLocal] = channelSendSequenceMap[channelIdLocal] + 1; } @@ -245,10 +245,10 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { if (block.number > previousTxHeight) { oracleSequence++; txCounter = 1; - previousTxHeight = block.number; + previousTxHeight=block.number; } else { txCounter++; - if (txCounter > batchSizeForOracle) { + if (txCounter>batchSizeForOracle) { oracleSequence++; txCounter = 1; } @@ -288,7 +288,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { } require(isContract(handlerContract), "address is not a contract"); - channelHandlerContractMap[channelId] = handlerContract; + channelHandlerContractMap[channelId]=handlerContract; registeredContractChannelMap[handlerContract][channelId] = true; isRelayRewardFromSystemReward[channelId] = isRewardFromSystem; emit addChannel(channelId, handlerContract); @@ -307,7 +307,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber { bool isEnable = (status == 1); address handlerContract = channelHandlerContractMap[channelId]; - if (handlerContract != address(0x00)) {//channel existing + if (handlerContract != address(0x00)) { //channel existing registeredContractChannelMap[handlerContract][channelId] = isEnable; emit enableOrDisableChannel(channelId, isEnable); } diff --git a/contracts/RelayerIncentivize.sol b/contracts/RelayerIncentivize.sol index 531c7373..345df464 100644 --- a/contracts/RelayerIncentivize.sol +++ b/contracts/RelayerIncentivize.sol @@ -31,11 +31,11 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { mapping(address => uint256) public packageRelayersSubmitCount; address payable[] public packageRelayerAddressRecord; - uint256 public collectedRewardForHeaderRelayer = 0; - uint256 public collectedRewardForTransferRelayer = 0; + uint256 public collectedRewardForHeaderRelayer=0; + uint256 public collectedRewardForTransferRelayer=0; - uint256 public roundSequence = 0; - uint256 public countInRound = 0; + uint256 public roundSequence=0; + uint256 public countInRound=0; mapping(address => uint256) public relayerRewardVault; @@ -47,14 +47,14 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function init() onlyNotInit external { require(!alreadyInit, "already initialized"); - headerRelayerRewardRateMolecule = HEADER_RELAYER_REWARD_RATE_MOLECULE; - headerRelayerRewardRateDenominator = HEADER_RELAYER_REWARD_RATE_DENOMINATOR; - callerCompensationMolecule = CALLER_COMPENSATION_MOLECULE; - callerCompensationDenominator = CALLER_COMPENSATION_DENOMINATOR; + headerRelayerRewardRateMolecule=HEADER_RELAYER_REWARD_RATE_MOLECULE; + headerRelayerRewardRateDenominator=HEADER_RELAYER_REWARD_RATE_DENOMINATOR; + callerCompensationMolecule=CALLER_COMPENSATION_MOLECULE; + callerCompensationDenominator=CALLER_COMPENSATION_DENOMINATOR; alreadyInit = true; } - receive() external payable {} + receive() external payable{} function addReward(address payable headerRelayerAddr, address payable packageRelayer, uint256 amount, bool fromSystemReward) onlyInit onlyCrossChainContract external override returns (bool) { @@ -65,7 +65,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } else { actualAmount = ISystemReward(TOKEN_HUB_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), amount); if (dynamicExtraIncentiveAmount > 0) { - actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); + actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); } } @@ -75,17 +75,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { collectedRewardForHeaderRelayer = collectedRewardForHeaderRelayer.add(reward); collectedRewardForTransferRelayer = collectedRewardForTransferRelayer.add(actualAmount).sub(reward); - if (headerRelayersSubmitCount[headerRelayerAddr] == 0) { + if (headerRelayersSubmitCount[headerRelayerAddr]==0) { headerRelayerAddressRecord.push(headerRelayerAddr); } headerRelayersSubmitCount[headerRelayerAddr]++; - if (packageRelayersSubmitCount[packageRelayer] == 0) { + if (packageRelayersSubmitCount[packageRelayer]==0) { packageRelayerAddressRecord.push(packageRelayer); } packageRelayersSubmitCount[packageRelayer]++; - if (countInRound >= ROUND_SIZE) { + if (countInRound>=ROUND_SIZE) { emit distributeCollectedReward(roundSequence, collectedRewardForHeaderRelayer, collectedRewardForTransferRelayer); uint256 callerHeaderReward = distributeHeaderRelayerReward(); @@ -100,17 +100,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } function claimRelayerReward(address relayerAddr) external { - uint256 reward = relayerRewardVault[relayerAddr]; - require(reward > 0, "no relayer reward"); - relayerRewardVault[relayerAddr] = 0; - address payable recipient = address(uint160(relayerAddr)); - if (!recipient.send(reward)) { - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(reward); - emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); - return; - } - emit rewardToRelayer(relayerAddr, reward); + uint256 reward = relayerRewardVault[relayerAddr]; + require(reward > 0, "no relayer reward"); + relayerRewardVault[relayerAddr] = 0; + address payable recipient = address(uint160(relayerAddr)); + if (!recipient.send(reward)) { + address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); + systemPayable.transfer(reward); + emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); + return; + } + emit rewardToRelayer(relayerAddr, reward); } function calculateRewardForHeaderRelayer(uint256 reward) internal view returns (uint256) { @@ -120,7 +120,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributeHeaderRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForHeaderRelayer; - uint256 totalWeight = 0; + uint256 totalWeight=0; address payable[] memory relayers = headerRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -151,7 +151,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributePackageRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForTransferRelayer; - uint256 totalWeight = 0; + uint256 totalWeight=0; address payable[] memory relayers = packageRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -179,19 +179,19 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { return callerReward; } - function calculateTransferRelayerWeight(uint256 count) public pure returns (uint256) { + function calculateTransferRelayerWeight(uint256 count) public pure returns(uint256) { if (count <= MAXIMUM_WEIGHT) { return count; - } else if (MAXIMUM_WEIGHT < count && count <= 2 * MAXIMUM_WEIGHT) { + } else if (MAXIMUM_WEIGHT < count && count <= 2*MAXIMUM_WEIGHT) { return MAXIMUM_WEIGHT; - } else if (2 * MAXIMUM_WEIGHT < count && count <= (2 * MAXIMUM_WEIGHT + 3 * MAXIMUM_WEIGHT / 4)) { - return 3 * MAXIMUM_WEIGHT - count; + } else if (2*MAXIMUM_WEIGHT < count && count <= (2*MAXIMUM_WEIGHT + 3*MAXIMUM_WEIGHT/4)) { + return 3*MAXIMUM_WEIGHT - count; } else { - return count / 4; + return count/4; } } - function calculateHeaderRelayerWeight(uint256 count) public pure returns (uint256) { + function calculateHeaderRelayerWeight(uint256 count) public pure returns(uint256) { if (count <= MAXIMUM_WEIGHT) { return count; } else { @@ -199,32 +199,32 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } } - function updateParam(string calldata key, bytes calldata value) override external onlyGov { + function updateParam(string calldata key, bytes calldata value) override external onlyGov{ require(alreadyInit, "contract has not been initialized"); - if (Memory.compareStrings(key, "headerRelayerRewardRateMolecule")) { + if (Memory.compareStrings(key,"headerRelayerRewardRateMolecule")) { require(value.length == 32, "length of headerRelayerRewardRateMolecule mismatch"); uint256 newHeaderRelayerRewardRateMolecule = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateMolecule <= headerRelayerRewardRateDenominator, "new headerRelayerRewardRateMolecule shouldn't be greater than headerRelayerRewardRateDenominator"); headerRelayerRewardRateMolecule = newHeaderRelayerRewardRateMolecule; - } else if (Memory.compareStrings(key, "headerRelayerRewardRateDenominator")) { + } else if (Memory.compareStrings(key,"headerRelayerRewardRateDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newHeaderRelayerRewardRateDenominator = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateDenominator != 0 && newHeaderRelayerRewardRateDenominator >= headerRelayerRewardRateMolecule, "the new headerRelayerRewardRateDenominator must not be zero and no less than headerRelayerRewardRateMolecule"); headerRelayerRewardRateDenominator = newHeaderRelayerRewardRateDenominator; - } else if (Memory.compareStrings(key, "callerCompensationMolecule")) { + } else if (Memory.compareStrings(key,"callerCompensationMolecule")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationMolecule = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationMolecule <= callerCompensationDenominator, "new callerCompensationMolecule shouldn't be greater than callerCompensationDenominator"); callerCompensationMolecule = newCallerCompensationMolecule; - } else if (Memory.compareStrings(key, "callerCompensationDenominator")) { + } else if (Memory.compareStrings(key,"callerCompensationDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationDenominator = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationDenominator != 0 && newCallerCompensationDenominator >= callerCompensationMolecule, "the newCallerCompensationDenominator must not be zero and no less than callerCompensationMolecule"); callerCompensationDenominator = newCallerCompensationDenominator; - } else if (Memory.compareStrings(key, "dynamicExtraIncentiveAmount")) { + } else if (Memory.compareStrings(key,"dynamicExtraIncentiveAmount")) { require(value.length == 32, "length of dynamicExtraIncentiveAmount mismatch"); uint256 newDynamicExtraIncentiveAmount = BytesToTypes.bytesToUint256(32, value); - require(newDynamicExtraIncentiveAmount >= 0, "the newDynamicExtraIncentiveAmount must be no less than zero"); + require(newDynamicExtraIncentiveAmount >= 0 , "the newDynamicExtraIncentiveAmount must be no less than zero"); dynamicExtraIncentiveAmount = newDynamicExtraIncentiveAmount; } else { require(false, "unknown param"); diff --git a/contracts/RelayerIncentivize.template b/contracts/RelayerIncentivize.template index baac5ca5..9e0b8465 100644 --- a/contracts/RelayerIncentivize.template +++ b/contracts/RelayerIncentivize.template @@ -31,11 +31,11 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { mapping(address => uint256) public packageRelayersSubmitCount; address payable[] public packageRelayerAddressRecord; - uint256 public collectedRewardForHeaderRelayer = 0; - uint256 public collectedRewardForTransferRelayer = 0; + uint256 public collectedRewardForHeaderRelayer=0; + uint256 public collectedRewardForTransferRelayer=0; - uint256 public roundSequence = 0; - uint256 public countInRound = 0; + uint256 public roundSequence=0; + uint256 public countInRound=0; mapping(address => uint256) public relayerRewardVault; @@ -47,14 +47,14 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function init() onlyNotInit external { require(!alreadyInit, "already initialized"); - headerRelayerRewardRateMolecule = HEADER_RELAYER_REWARD_RATE_MOLECULE; - headerRelayerRewardRateDenominator = HEADER_RELAYER_REWARD_RATE_DENOMINATOR; - callerCompensationMolecule = CALLER_COMPENSATION_MOLECULE; - callerCompensationDenominator = CALLER_COMPENSATION_DENOMINATOR; + headerRelayerRewardRateMolecule=HEADER_RELAYER_REWARD_RATE_MOLECULE; + headerRelayerRewardRateDenominator=HEADER_RELAYER_REWARD_RATE_DENOMINATOR; + callerCompensationMolecule=CALLER_COMPENSATION_MOLECULE; + callerCompensationDenominator=CALLER_COMPENSATION_DENOMINATOR; alreadyInit = true; } - receive() external payable {} + receive() external payable{} {% if mock %} function addReward(address payable headerRelayerAddr, address payable packageRelayer, uint256 amount, bool fromSystemReward) external override returns (bool) { @@ -67,7 +67,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } else { actualAmount = ISystemReward(TOKEN_HUB_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), amount); if (dynamicExtraIncentiveAmount > 0) { - actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); + actualAmount = actualAmount.add(ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(address(uint160(INCENTIVIZE_ADDR)), dynamicExtraIncentiveAmount)); } } @@ -77,17 +77,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { collectedRewardForHeaderRelayer = collectedRewardForHeaderRelayer.add(reward); collectedRewardForTransferRelayer = collectedRewardForTransferRelayer.add(actualAmount).sub(reward); - if (headerRelayersSubmitCount[headerRelayerAddr] == 0) { + if (headerRelayersSubmitCount[headerRelayerAddr]==0) { headerRelayerAddressRecord.push(headerRelayerAddr); } headerRelayersSubmitCount[headerRelayerAddr]++; - if (packageRelayersSubmitCount[packageRelayer] == 0) { + if (packageRelayersSubmitCount[packageRelayer]==0) { packageRelayerAddressRecord.push(packageRelayer); } packageRelayersSubmitCount[packageRelayer]++; - if (countInRound >= ROUND_SIZE) { + if (countInRound>=ROUND_SIZE) { emit distributeCollectedReward(roundSequence, collectedRewardForHeaderRelayer, collectedRewardForTransferRelayer); uint256 callerHeaderReward = distributeHeaderRelayerReward(); @@ -102,17 +102,17 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } function claimRelayerReward(address relayerAddr) external { - uint256 reward = relayerRewardVault[relayerAddr]; - require(reward > 0, "no relayer reward"); - relayerRewardVault[relayerAddr] = 0; - address payable recipient = address(uint160(relayerAddr)); - if (!recipient.send(reward)) { - address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); - systemPayable.transfer(reward); - emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); - return; - } - emit rewardToRelayer(relayerAddr, reward); + uint256 reward = relayerRewardVault[relayerAddr]; + require(reward > 0, "no relayer reward"); + relayerRewardVault[relayerAddr] = 0; + address payable recipient = address(uint160(relayerAddr)); + if (!recipient.send(reward)) { + address payable systemPayable = address(uint160(SYSTEM_REWARD_ADDR)); + systemPayable.transfer(reward); + emit rewardToRelayer(SYSTEM_REWARD_ADDR, reward); + return; + } + emit rewardToRelayer(relayerAddr, reward); } function calculateRewardForHeaderRelayer(uint256 reward) internal view returns (uint256) { @@ -122,7 +122,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributeHeaderRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForHeaderRelayer; - uint256 totalWeight = 0; + uint256 totalWeight=0; address payable[] memory relayers = headerRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -153,7 +153,7 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { function distributePackageRelayerReward() internal returns (uint256) { uint256 totalReward = collectedRewardForTransferRelayer; - uint256 totalWeight = 0; + uint256 totalWeight=0; address payable[] memory relayers = packageRelayerAddressRecord; uint256[] memory relayerWeight = new uint256[](relayers.length); for (uint256 index = 0; index < relayers.length; index++) { @@ -181,19 +181,19 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { return callerReward; } - function calculateTransferRelayerWeight(uint256 count) public pure returns (uint256) { + function calculateTransferRelayerWeight(uint256 count) public pure returns(uint256) { if (count <= MAXIMUM_WEIGHT) { return count; - } else if (MAXIMUM_WEIGHT < count && count <= 2 * MAXIMUM_WEIGHT) { + } else if (MAXIMUM_WEIGHT < count && count <= 2*MAXIMUM_WEIGHT) { return MAXIMUM_WEIGHT; - } else if (2 * MAXIMUM_WEIGHT < count && count <= (2 * MAXIMUM_WEIGHT + 3 * MAXIMUM_WEIGHT / 4)) { - return 3 * MAXIMUM_WEIGHT - count; + } else if (2*MAXIMUM_WEIGHT < count && count <= (2*MAXIMUM_WEIGHT + 3*MAXIMUM_WEIGHT/4)) { + return 3*MAXIMUM_WEIGHT - count; } else { - return count / 4; + return count/4; } } - function calculateHeaderRelayerWeight(uint256 count) public pure returns (uint256) { + function calculateHeaderRelayerWeight(uint256 count) public pure returns(uint256) { if (count <= MAXIMUM_WEIGHT) { return count; } else { @@ -201,32 +201,32 @@ contract RelayerIncentivize is IRelayerIncentivize, System, IParamSubscriber { } } - function updateParam(string calldata key, bytes calldata value) override external onlyGov { + function updateParam(string calldata key, bytes calldata value) override external onlyGov{ require(alreadyInit, "contract has not been initialized"); - if (Memory.compareStrings(key, "headerRelayerRewardRateMolecule")) { + if (Memory.compareStrings(key,"headerRelayerRewardRateMolecule")) { require(value.length == 32, "length of headerRelayerRewardRateMolecule mismatch"); uint256 newHeaderRelayerRewardRateMolecule = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateMolecule <= headerRelayerRewardRateDenominator, "new headerRelayerRewardRateMolecule shouldn't be greater than headerRelayerRewardRateDenominator"); headerRelayerRewardRateMolecule = newHeaderRelayerRewardRateMolecule; - } else if (Memory.compareStrings(key, "headerRelayerRewardRateDenominator")) { + } else if (Memory.compareStrings(key,"headerRelayerRewardRateDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newHeaderRelayerRewardRateDenominator = BytesToTypes.bytesToUint256(32, value); require(newHeaderRelayerRewardRateDenominator != 0 && newHeaderRelayerRewardRateDenominator >= headerRelayerRewardRateMolecule, "the new headerRelayerRewardRateDenominator must not be zero and no less than headerRelayerRewardRateMolecule"); headerRelayerRewardRateDenominator = newHeaderRelayerRewardRateDenominator; - } else if (Memory.compareStrings(key, "callerCompensationMolecule")) { + } else if (Memory.compareStrings(key,"callerCompensationMolecule")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationMolecule = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationMolecule <= callerCompensationDenominator, "new callerCompensationMolecule shouldn't be greater than callerCompensationDenominator"); callerCompensationMolecule = newCallerCompensationMolecule; - } else if (Memory.compareStrings(key, "callerCompensationDenominator")) { + } else if (Memory.compareStrings(key,"callerCompensationDenominator")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newCallerCompensationDenominator = BytesToTypes.bytesToUint256(32, value); require(newCallerCompensationDenominator != 0 && newCallerCompensationDenominator >= callerCompensationMolecule, "the newCallerCompensationDenominator must not be zero and no less than callerCompensationMolecule"); callerCompensationDenominator = newCallerCompensationDenominator; - } else if (Memory.compareStrings(key, "dynamicExtraIncentiveAmount")) { + } else if (Memory.compareStrings(key,"dynamicExtraIncentiveAmount")) { require(value.length == 32, "length of dynamicExtraIncentiveAmount mismatch"); uint256 newDynamicExtraIncentiveAmount = BytesToTypes.bytesToUint256(32, value); - require(newDynamicExtraIncentiveAmount >= 0, "the newDynamicExtraIncentiveAmount must be no less than zero"); + require(newDynamicExtraIncentiveAmount >= 0 , "the newDynamicExtraIncentiveAmount must be no less than zero"); dynamicExtraIncentiveAmount = newDynamicExtraIncentiveAmount; } else { require(false, "unknown param"); diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index c86e6101..e9b6325b 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -14,7 +14,7 @@ import "./interface/ISystemReward.sol"; import "./lib/CmnPkg.sol"; import "./lib/RLPEncode.sol"; -contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplication { +contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication{ using RLPEncode for *; uint256 public constant MISDEMEANOR_THRESHOLD = 50; @@ -74,19 +74,19 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati modifier onlyZeroGasPrice() { - require(tx.gasprice == 0, "gasprice is not zero"); + require(tx.gasprice == 0 , "gasprice is not zero"); _; } - - function init() external onlyNotInit { + + function init() external onlyNotInit{ misdemeanorThreshold = MISDEMEANOR_THRESHOLD; felonyThreshold = FELONY_THRESHOLD; alreadyInit = true; } /*********************** Implement cross chain app ********************************/ - function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns (bytes memory) { + function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns(bytes memory) { require(false, "receive unexpected syn package"); } @@ -106,7 +106,7 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } /*********************** External func ********************************/ - function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice { + function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { return; } @@ -130,51 +130,52 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati emit validatorSlashed(validator); } + // To prevent validator misbehaving and leaving, do not clean slash record to zero, but decrease by felonyThreshold/DECREASE_RATE . // Clean is an effective implement to reorganize "validators" and "indicators". - function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit { - if (validators.length == 0) { + function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit{ + if(validators.length == 0){ return; } uint i = 0; - uint j = validators.length - 1; - for (; i <= j;) { + uint j = validators.length-1; + for (;i <= j;) { bool findLeft = false; bool findRight = false; - for (; i < j; i++) { + for(;i felonyThreshold / DECREASE_RATE) { - leftIndicator.count = leftIndicator.count - felonyThreshold / DECREASE_RATE; + if(leftIndicator.count > felonyThreshold/DECREASE_RATE){ + leftIndicator.count = leftIndicator.count - felonyThreshold/DECREASE_RATE; indicators[validators[i]] = leftIndicator; - } else { + }else{ findLeft = true; break; } } - for (; i <= j; j--) { + for(;i<=j;j--){ Indicator memory rightIndicator = indicators[validators[j]]; - if (rightIndicator.count > felonyThreshold / DECREASE_RATE) { - rightIndicator.count = rightIndicator.count - felonyThreshold / DECREASE_RATE; + if(rightIndicator.count > felonyThreshold/DECREASE_RATE){ + rightIndicator.count = rightIndicator.count - felonyThreshold/DECREASE_RATE; indicators[validators[j]] = rightIndicator; findRight = true; break; - } else { + }else{ delete indicators[validators[j]]; validators.pop(); } // avoid underflow - if (j == 0) { + if(j==0){ break; } } // swap element in array - if (findLeft && findRight) { + if (findLeft && findRight){ delete indicators[validators[i]]; validators[i] = validators[j]; validators.pop(); } // avoid underflow - if (j == 0) { + if(j==0){ break; } // move to next @@ -265,13 +266,13 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { - if (Memory.compareStrings(key, "misdemeanorThreshold")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ + if (Memory.compareStrings(key,"misdemeanorThreshold")) { require(value.length == 32, "length of misdemeanorThreshold mismatch"); uint256 newMisdemeanorThreshold = BytesToTypes.bytesToUint256(32, value); require(newMisdemeanorThreshold >= 1 && newMisdemeanorThreshold < felonyThreshold, "the misdemeanorThreshold out of range"); misdemeanorThreshold = newMisdemeanorThreshold; - } else if (Memory.compareStrings(key, "felonyThreshold")) { + } else if (Memory.compareStrings(key,"felonyThreshold")) { require(value.length == 32, "length of felonyThreshold mismatch"); uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); @@ -284,11 +285,11 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } else { require(false, "unknown param"); } - emit paramChange(key, value); + emit paramChange(key,value); } /*********************** query api ********************************/ - function getSlashIndicator(address validator) external view returns (uint256, uint256) { + function getSlashIndicator(address validator) external view returns (uint256,uint256) { Indicator memory indicator = indicators[validator]; return (indicator.height, indicator.count); } diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index 09c2e128..c30011e1 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -14,7 +14,7 @@ import "./interface/ISystemReward.sol"; import "./lib/CmnPkg.sol"; import "./lib/RLPEncode.sol"; -contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplication { +contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication{ using RLPEncode for *; uint256 public constant MISDEMEANOR_THRESHOLD = 50; @@ -76,23 +76,22 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati {% if mock %} require(true, "gasprice is not zero"); {% else %} - require(tx.gasprice == 0, "gasprice is not zero"); + require(tx.gasprice == 0 , "gasprice is not zero"); {% endif %} _; } -{% if mock %} + {% if mock %} function getSlashValidators() external view returns (address[] memory) { return validators; - } -{% endif %} - function init() external onlyNotInit { + }{% endif %} + function init() external onlyNotInit{ misdemeanorThreshold = MISDEMEANOR_THRESHOLD; felonyThreshold = FELONY_THRESHOLD; alreadyInit = true; } /*********************** Implement cross chain app ********************************/ - function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns (bytes memory) { + function handleSynPackage(uint8, bytes calldata) external onlyCrossChainContract onlyInit override returns(bytes memory) { require(false, "receive unexpected syn package"); } @@ -112,7 +111,7 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } /*********************** External func ********************************/ - function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice { + function slash(address validator) external onlyCoinbase onlyInit oncePerBlock onlyZeroGasPrice{ if (!IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).isCurrentValidator(validator)) { return; } @@ -136,51 +135,52 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati emit validatorSlashed(validator); } + // To prevent validator misbehaving and leaving, do not clean slash record to zero, but decrease by felonyThreshold/DECREASE_RATE . // Clean is an effective implement to reorganize "validators" and "indicators". - function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit { - if (validators.length == 0) { + function clean() external override(ISlashIndicator) onlyValidatorContract onlyInit{ + if(validators.length == 0){ return; } uint i = 0; - uint j = validators.length - 1; - for (; i <= j;) { + uint j = validators.length-1; + for (;i <= j;) { bool findLeft = false; bool findRight = false; - for (; i < j; i++) { + for(;i felonyThreshold / DECREASE_RATE) { - leftIndicator.count = leftIndicator.count - felonyThreshold / DECREASE_RATE; + if(leftIndicator.count > felonyThreshold/DECREASE_RATE){ + leftIndicator.count = leftIndicator.count - felonyThreshold/DECREASE_RATE; indicators[validators[i]] = leftIndicator; - } else { + }else{ findLeft = true; break; } } - for (; i <= j; j--) { + for(;i<=j;j--){ Indicator memory rightIndicator = indicators[validators[j]]; - if (rightIndicator.count > felonyThreshold / DECREASE_RATE) { - rightIndicator.count = rightIndicator.count - felonyThreshold / DECREASE_RATE; + if(rightIndicator.count > felonyThreshold/DECREASE_RATE){ + rightIndicator.count = rightIndicator.count - felonyThreshold/DECREASE_RATE; indicators[validators[j]] = rightIndicator; findRight = true; break; - } else { + }else{ delete indicators[validators[j]]; validators.pop(); } // avoid underflow - if (j == 0) { + if(j==0){ break; } } // swap element in array - if (findLeft && findRight) { + if (findLeft && findRight){ delete indicators[validators[i]]; validators[i] = validators[j]; validators.pop(); } // avoid underflow - if (j == 0) { + if(j==0){ break; } // move to next @@ -271,13 +271,13 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { - if (Memory.compareStrings(key, "misdemeanorThreshold")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ + if (Memory.compareStrings(key,"misdemeanorThreshold")) { require(value.length == 32, "length of misdemeanorThreshold mismatch"); uint256 newMisdemeanorThreshold = BytesToTypes.bytesToUint256(32, value); require(newMisdemeanorThreshold >= 1 && newMisdemeanorThreshold < felonyThreshold, "the misdemeanorThreshold out of range"); misdemeanorThreshold = newMisdemeanorThreshold; - } else if (Memory.compareStrings(key, "felonyThreshold")) { + } else if (Memory.compareStrings(key,"felonyThreshold")) { require(value.length == 32, "length of felonyThreshold mismatch"); uint256 newFelonyThreshold = BytesToTypes.bytesToUint256(32, value); require(newFelonyThreshold <= 1000 && newFelonyThreshold > misdemeanorThreshold, "the felonyThreshold out of range"); @@ -290,11 +290,11 @@ contract SlashIndicator is ISlashIndicator, System, IParamSubscriber, IApplicati } else { require(false, "unknown param"); } - emit paramChange(key, value); + emit paramChange(key,value); } /*********************** query api ********************************/ - function getSlashIndicator(address validator) external view returns (uint256, uint256) { + function getSlashIndicator(address validator) external view returns (uint256,uint256) { Indicator memory indicator = indicators[validator]; return (indicator.height, indicator.count); } diff --git a/contracts/System.sol b/contracts/System.sol index 951910ff..7d64ddc2 100644 --- a/contracts/System.sol +++ b/contracts/System.sol @@ -24,7 +24,7 @@ contract System { address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002; address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003; address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004; - address public constant INCENTIVIZE_ADDR = 0x0000000000000000000000000000000000001005; + address public constant INCENTIVIZE_ADDR=0x0000000000000000000000000000000000001005; address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006; address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; diff --git a/contracts/System.template b/contracts/System.template index cec65ee3..4ceba2da 100644 --- a/contracts/System.template +++ b/contracts/System.template @@ -19,11 +19,11 @@ contract System { uint8 constant public SLASH_CHANNELID = 0x0b; uint16 constant public bscChainID = 0x{{bscChainId}}; {% if mock %} - address public VALIDATOR_CONTRACT_ADDR; - address public SLASH_CONTRACT_ADDR; - address public SYSTEM_REWARD_ADDR; - address public LIGHT_CLIENT_ADDR; - address public TOKEN_HUB_ADDR; + address public VALIDATOR_CONTRACT_ADDR; + address public SLASH_CONTRACT_ADDR; + address public SYSTEM_REWARD_ADDR; + address public LIGHT_CLIENT_ADDR; + address public TOKEN_HUB_ADDR; address public INCENTIVIZE_ADDR; address public RELAYERHUB_CONTRACT_ADDR; address public GOV_HUB_ADDR; @@ -48,7 +48,7 @@ contract System { address public constant SYSTEM_REWARD_ADDR = 0x0000000000000000000000000000000000001002; address public constant LIGHT_CLIENT_ADDR = 0x0000000000000000000000000000000000001003; address public constant TOKEN_HUB_ADDR = 0x0000000000000000000000000000000000001004; - address public constant INCENTIVIZE_ADDR = 0x0000000000000000000000000000000000001005; + address public constant INCENTIVIZE_ADDR=0x0000000000000000000000000000000000001005; address public constant RELAYERHUB_CONTRACT_ADDR = 0x0000000000000000000000000000000000001006; address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; diff --git a/contracts/SystemReward.sol b/contracts/SystemReward.sol index ed0c8df7..5e65d9c7 100644 --- a/contracts/SystemReward.sol +++ b/contracts/SystemReward.sol @@ -29,12 +29,13 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { event paramChange(string key, bytes value); - receive() external payable { - if (msg.value > 0) { + receive() external payable{ + if (msg.value>0) { emit receiveDeposit(msg.sender, msg.value); } } + function claimRewards(address payable to, uint256 amount) external override(ISystemReward) doInit returns (uint256) { if (!operators[msg.sender]) { return 0; @@ -44,7 +45,7 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { if (actualAmount > MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount > 0) { + if (actualAmount>0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { @@ -72,4 +73,4 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { } emit paramChange(key, value); } -} +} \ No newline at end of file diff --git a/contracts/SystemReward.template b/contracts/SystemReward.template index 7c846bf4..c62a74e6 100644 --- a/contracts/SystemReward.template +++ b/contracts/SystemReward.template @@ -24,7 +24,7 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { {% if mock %} event newOperator(address indexed operator); event deleteOperator(address indexed operator); -{% endif %} + {% endif %} event rewardTo(address indexed to, uint256 amount); event rewardEmpty(); event receiveDeposit(address indexed from, uint256 amount); @@ -32,12 +32,13 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { event paramChange(string key, bytes value); - receive() external payable { - if (msg.value > 0) { + receive() external payable{ + if (msg.value>0) { emit receiveDeposit(msg.sender, msg.value); } } -{% if mock %} + + {% if mock %} modifier onlyOperatorExist(address _operator) { require(operators[_operator], "the operator do not exist"); _; @@ -69,7 +70,7 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { if (actualAmount > MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount > 0) { + if (actualAmount>0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { @@ -97,4 +98,4 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { } emit paramChange(key, value); } -} +} \ No newline at end of file diff --git a/contracts/TendermintLightClient.sol b/contracts/TendermintLightClient.sol index 537925ed..418dbe32 100644 --- a/contracts/TendermintLightClient.sol +++ b/contracts/TendermintLightClient.sol @@ -7,13 +7,13 @@ import "./interface/ISystemReward.sol"; import "./interface/IParamSubscriber.sol"; import "./System.sol"; -contract TendermintLightClient is ILightClient, System, IParamSubscriber { +contract TendermintLightClient is ILightClient, System, IParamSubscriber{ struct ConsensusState { - uint64 preValidatorSetChangeHeight; + uint64 preValidatorSetChangeHeight; bytes32 appHash; bytes32 curValidatorSetHash; - bytes nextValidatorSet; + bytes nextValidatorSet; } mapping(uint64 => ConsensusState) public lightClientConsensusStates; @@ -23,7 +23,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { bytes32 public chainID; bytes constant public INIT_CONSENSUS_STATE_BYTES = hex"42696e616e63652d436861696e2d4e696c650000000000000000000000000000000000000000000229eca254b3859bffefaf85f4c95da9fbd26527766b784272789c30ec56b380b6eb96442aaab207bc59978ba3dd477690f5c5872334fc39e627723daa97e441e88ba4515150ec3182bc82593df36f8abb25a619187fcfab7e552b94e64ed2deed000000e8d4a51000"; - uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = 1e16; + uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = 1e16; uint256 public rewardForValidatorSetChange; event initConsensusState(uint64 initHeight, bytes32 appHash); @@ -75,17 +75,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { //32 + 32 + 8 + 32 + 32 + cs.nextValidatorSet.length; uint256 length = 136 + cs.nextValidatorSet.length; - bytes memory input = new bytes(length + header.length); + bytes memory input = new bytes(length+header.length); uint256 ptr = Memory.dataPtr(input); require(encodeConsensusState(cs, preValidatorSetChangeHeight, ptr, length), "failed to serialize consensus state"); // write header to input uint256 src; - ptr = ptr + length; + ptr = ptr+length; (src, length) = Memory.fromBytes(header); Memory.copy(src, ptr, length); - length = input.length + 32; + length = input.length+32; // Maximum validator quantity is 99 bytes32[128] memory result; /* solium-disable-next-line */ @@ -103,11 +103,11 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { length := mload(add(result, 0)) } bool validatorChanged = false; - if ((length & (0x01 << 248)) != 0x00) { + if ((length&(0x01<<248))!=0x00) { validatorChanged = true; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, rewardForValidatorSetChange); } - length = length & 0xffffffffffffffff; + length = length&0xffffffffffffffff; /* solium-disable-next-line */ assembly { @@ -145,7 +145,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { function getChainID() external view returns (string memory) { bytes memory chainIDBytes = new bytes(32); assembly { - mstore(add(chainIDBytes, 32), sload(chainID_slot)) + mstore(add(chainIDBytes,32), sload(chainID_slot)) } uint8 chainIDLength = 0; @@ -175,36 +175,36 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { uint256 length; (src, length) = Memory.fromBytes(cs.nextValidatorSet); Memory.copy(src, outputPtr, length); - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; bytes32 hash = cs.curValidatorSetHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; hash = cs.appHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; /* solium-disable-next-line */ assembly { mstore(outputPtr, height) } - outputPtr = outputPtr - 8; + outputPtr = outputPtr-8; /* solium-disable-next-line */ assembly { mstore(outputPtr, sload(chainID_slot)) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; // size doesn't contain length - size = size - 32; + size = size-32; /* solium-disable-next-line */ assembly { mstore(outputPtr, size) @@ -216,22 +216,22 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { // | chainID | height | appHash | curValidatorSetHash | [{validator pubkey, voting power}] | // | 32 bytes | 8 bytes | 32 bytes | 32 bytes | [{32 bytes, 8 bytes}] | /* solium-disable-next-line */ - function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns (ConsensusState memory, uint64) { - ptr = ptr + 8; + function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns(ConsensusState memory, uint64) { + ptr = ptr+8; uint64 height; /* solium-disable-next-line */ assembly { height := mload(ptr) } - ptr = ptr + 32; + ptr = ptr+32; bytes32 appHash; /* solium-disable-next-line */ assembly { appHash := mload(ptr) } - ptr = ptr + 32; + ptr = ptr+32; bytes32 curValidatorSetHash; /* solium-disable-next-line */ assembly { @@ -245,17 +245,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { if (!leaveOutValidatorSet) { uint256 dest; uint256 length; - cs.nextValidatorSet = new bytes(size - 104); - (dest, length) = Memory.fromBytes(cs.nextValidatorSet); + cs.nextValidatorSet = new bytes(size-104); + (dest,length) = Memory.fromBytes(cs.nextValidatorSet); - Memory.copy(ptr + 32, dest, length); + Memory.copy(ptr+32, dest, length); } return (cs, height); } - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { - if (Memory.compareStrings(key, "rewardForValidatorSetChange")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ + if (Memory.compareStrings(key,"rewardForValidatorSetChange")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newRewardForValidatorSetChange = BytesToTypes.bytesToUint256(32, value); require(newRewardForValidatorSetChange > 0 && newRewardForValidatorSetChange <= 1e18, "the newRewardForValidatorSetChange out of range"); @@ -265,4 +265,4 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { } emit paramChange(key, value); } -} +} \ No newline at end of file diff --git a/contracts/TendermintLightClient.template b/contracts/TendermintLightClient.template index 7976a617..13511ed7 100644 --- a/contracts/TendermintLightClient.template +++ b/contracts/TendermintLightClient.template @@ -7,13 +7,13 @@ import "./interface/ISystemReward.sol"; import "./interface/IParamSubscriber.sol"; import "./System.sol"; -contract TendermintLightClient is ILightClient, System, IParamSubscriber { +contract TendermintLightClient is ILightClient, System, IParamSubscriber{ struct ConsensusState { - uint64 preValidatorSetChangeHeight; + uint64 preValidatorSetChangeHeight; bytes32 appHash; bytes32 curValidatorSetHash; - bytes nextValidatorSet; + bytes nextValidatorSet; } mapping(uint64 => ConsensusState) public lightClientConsensusStates; @@ -23,7 +23,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { bytes32 public chainID; bytes constant public INIT_CONSENSUS_STATE_BYTES = hex"{{initConsensusStateBytes}}"; - uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = {{rewardForValidatorSetChange}}; + uint256 constant public INIT_REWARD_FOR_VALIDATOR_SER_CHANGE = {{rewardForValidatorSetChange}}; uint256 public rewardForValidatorSetChange; event initConsensusState(uint64 initHeight, bytes32 appHash); @@ -75,17 +75,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { //32 + 32 + 8 + 32 + 32 + cs.nextValidatorSet.length; uint256 length = 136 + cs.nextValidatorSet.length; - bytes memory input = new bytes(length + header.length); + bytes memory input = new bytes(length+header.length); uint256 ptr = Memory.dataPtr(input); require(encodeConsensusState(cs, preValidatorSetChangeHeight, ptr, length), "failed to serialize consensus state"); // write header to input uint256 src; - ptr = ptr + length; + ptr = ptr+length; (src, length) = Memory.fromBytes(header); Memory.copy(src, ptr, length); - length = input.length + 32; + length = input.length+32; // Maximum validator quantity is 99 bytes32[128] memory result; /* solium-disable-next-line */ @@ -103,11 +103,11 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { length := mload(add(result, 0)) } bool validatorChanged = false; - if ((length & (0x01 << 248)) != 0x00) { + if ((length&(0x01<<248))!=0x00) { validatorChanged = true; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, rewardForValidatorSetChange); } - length = length & 0xffffffffffffffff; + length = length&0xffffffffffffffff; /* solium-disable-next-line */ assembly { @@ -145,7 +145,7 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { function getChainID() external view returns (string memory) { bytes memory chainIDBytes = new bytes(32); assembly { - mstore(add(chainIDBytes, 32), sload(chainID_slot)) + mstore(add(chainIDBytes,32), sload(chainID_slot)) } uint8 chainIDLength = 0; @@ -175,36 +175,36 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { uint256 length; (src, length) = Memory.fromBytes(cs.nextValidatorSet); Memory.copy(src, outputPtr, length); - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; bytes32 hash = cs.curValidatorSetHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; hash = cs.appHash; /* solium-disable-next-line */ assembly { mstore(outputPtr, hash) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; /* solium-disable-next-line */ assembly { mstore(outputPtr, height) } - outputPtr = outputPtr - 8; + outputPtr = outputPtr-8; /* solium-disable-next-line */ assembly { mstore(outputPtr, sload(chainID_slot)) } - outputPtr = outputPtr - 32; + outputPtr = outputPtr-32; // size doesn't contain length - size = size - 32; + size = size-32; /* solium-disable-next-line */ assembly { mstore(outputPtr, size) @@ -216,22 +216,22 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { // | chainID | height | appHash | curValidatorSetHash | [{validator pubkey, voting power}] | // | 32 bytes | 8 bytes | 32 bytes | 32 bytes | [{32 bytes, 8 bytes}] | /* solium-disable-next-line */ - function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns (ConsensusState memory, uint64) { - ptr = ptr + 8; + function decodeConsensusState(uint256 ptr, uint256 size, bool leaveOutValidatorSet) internal pure returns(ConsensusState memory, uint64) { + ptr = ptr+8; uint64 height; /* solium-disable-next-line */ assembly { height := mload(ptr) } - ptr = ptr + 32; + ptr = ptr+32; bytes32 appHash; /* solium-disable-next-line */ assembly { appHash := mload(ptr) } - ptr = ptr + 32; + ptr = ptr+32; bytes32 curValidatorSetHash; /* solium-disable-next-line */ assembly { @@ -245,17 +245,17 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { if (!leaveOutValidatorSet) { uint256 dest; uint256 length; - cs.nextValidatorSet = new bytes(size - 104); - (dest, length) = Memory.fromBytes(cs.nextValidatorSet); + cs.nextValidatorSet = new bytes(size-104); + (dest,length) = Memory.fromBytes(cs.nextValidatorSet); - Memory.copy(ptr + 32, dest, length); + Memory.copy(ptr+32, dest, length); } return (cs, height); } - function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov { - if (Memory.compareStrings(key, "rewardForValidatorSetChange")) { + function updateParam(string calldata key, bytes calldata value) external override onlyInit onlyGov{ + if (Memory.compareStrings(key,"rewardForValidatorSetChange")) { require(value.length == 32, "length of rewardForValidatorSetChange mismatch"); uint256 newRewardForValidatorSetChange = BytesToTypes.bytesToUint256(32, value); require(newRewardForValidatorSetChange > 0 && newRewardForValidatorSetChange <= 1e18, "the newRewardForValidatorSetChange out of range"); @@ -265,4 +265,4 @@ contract TendermintLightClient is ILightClient, System, IParamSubscriber { } emit paramChange(key, value); } -} +} \ No newline at end of file diff --git a/contracts/TokenHub.sol b/contracts/TokenHub.sol index 849e7889..72a93e76 100644 --- a/contracts/TokenHub.sol +++ b/contracts/TokenHub.sol @@ -28,7 +28,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256[] amounts; address[] recipients; address[] refundAddrs; - uint64 expireTime; + uint64 expireTime; } // BC to BSC @@ -46,7 +46,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256 amount; address recipient; address refundAddr; - uint64 expireTime; + uint64 expireTime; } // BSC to BC @@ -70,11 +70,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 constant public MAXIMUM_BEP20_SYMBOL_LEN = 8; uint8 constant public BEP2_TOKEN_DECIMALS = 8; bytes32 constant public BEP2_TOKEN_SYMBOL_FOR_BNB = 0x424E420000000000000000000000000000000000000000000000000000000000; // "BNB" - uint256 constant public MAX_GAS_FOR_CALLING_BEP20 = 50000; - uint256 constant public MAX_GAS_FOR_TRANSFER_BNB = 10000; + uint256 constant public MAX_GAS_FOR_CALLING_BEP20=50000; + uint256 constant public MAX_GAS_FOR_TRANSFER_BNB=10000; - uint256 constant public INIT_MINIMUM_RELAY_FEE = 2e15; - uint256 constant public REWARD_UPPER_LIMIT = 1e18; + uint256 constant public INIT_MINIMUM_RELAY_FEE =2e15; + uint256 constant public REWARD_UPPER_LIMIT =1e18; uint256 constant public TEN_DECIMALS = 1e10; uint256 public relayFee; @@ -97,32 +97,32 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function init() onlyNotInit external { relayFee = INIT_MINIMUM_RELAY_FEE; bep20ContractDecimals[address(0x0)] = 18; // BNB decimals is 18 - alreadyInit = true; + alreadyInit=true; } - receive() external payable { - if (msg.value > 0) { + receive() external payable{ + if (msg.value>0) { emit receiveDeposit(msg.sender, msg.value); } } - function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns (uint256) { + function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns(uint256) { uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > REWARD_UPPER_LIMIT) { return 0; } - if (actualAmount > 0) { + if (actualAmount>0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } return actualAmount; } - function getMiniRelayFee() external view override returns (uint256) { + function getMiniRelayFee() external view override returns(uint256) { return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns (bytes memory) { + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory) { if (channelId == TRANSFER_IN_CHANNELID) { return handleTransferInSynPackage(msgBytes); } else { @@ -153,15 +153,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx = 0; + uint256 idx=0; while (iter.hasNext()) { - if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); - else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); - else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); - else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); - else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); + if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); + else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); + else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); + else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); + else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); else if (idx == 5) { - transInSynPkg.expireTime = uint64(iter.next().toUint()); + transInSynPkg.expireTime = uint64(iter.next().toUint()); success = true; } else break; @@ -179,17 +179,17 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return elements.encodeList(); } - function handleTransferInSynPackage(bytes memory msgBytes) internal returns (bytes memory) { + function handleTransferInSynPackage(bytes memory msgBytes) internal returns(bytes memory) { (TransferInSynPackage memory transInSynPkg, bool success) = decodeTransferInSynPackage(msgBytes); require(success, "unrecognized transferIn package"); uint32 resCode = doTransferIn(transInSynPkg); if (resCode != TRANSFER_IN_SUCCESS) { uint256 bep2Amount = convertToBep2Amount(transInSynPkg.amount, bep20ContractDecimals[transInSynPkg.contractAddr]); TransferInRefundPackage memory transInAckPkg = TransferInRefundPackage({ - bep2TokenSymbol : transInSynPkg.bep2TokenSymbol, - refundAmount : bep2Amount, - refundAddr : transInSynPkg.refundAddr, - status : resCode + bep2TokenSymbol: transInSynPkg.bep2TokenSymbol, + refundAmount: bep2Amount, + refundAddr: transInSynPkg.refundAddr, + status: resCode }); return encodeTransferInRefundPackage(transInAckPkg); } else { @@ -198,14 +198,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function doTransferIn(TransferInSynPackage memory transInSynPkg) internal returns (uint32) { - if (transInSynPkg.contractAddr == address(0x0)) { + if (transInSynPkg.contractAddr==address(0x0)) { if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } if (address(this).balance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - (bool success,) = transInSynPkg.recipient.call{gas : MAX_GAS_FOR_TRANSFER_BNB, value : transInSynPkg.amount}(""); + (bool success, ) = transInSynPkg.recipient.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: transInSynPkg.amount}(""); if (!success) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } @@ -215,14 +215,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } - if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr] != transInSynPkg.bep2TokenSymbol) { + if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr]!= transInSynPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas : MAX_GAS_FOR_CALLING_BEP20}(address(this)); + uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP20}(address(this)); if (actualBalance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas : MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); + bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); if (success) { emit transferInSuccess(transInSynPkg.contractAddr, transInSynPkg.recipient, transInSynPkg.amount); return TRANSFER_IN_SUCCESS; @@ -232,38 +232,38 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } } - function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns (TransferOutAckPackage memory, bool) { + function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns(TransferOutAckPackage memory, bool) { TransferOutAckPackage memory transOutAckPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx = 0; + uint256 idx=0; while (iter.hasNext()) { - if (idx == 0) { - transOutAckPkg.contractAddr = iter.next().toAddress(); - } - else if (idx == 1) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAmounts = new uint256[](list.length); - for (uint256 index = 0; index < list.length; index++) { - transOutAckPkg.refundAmounts[index] = list[index].toUint(); + if (idx == 0) { + transOutAckPkg.contractAddr = iter.next().toAddress(); } - } - else if (idx == 2) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAddrs = new address[](list.length); - for (uint256 index = 0; index < list.length; index++) { - transOutAckPkg.refundAddrs[index] = list[index].toAddress(); + else if (idx == 1) { + RLPDecode.RLPItem[] memory list = iter.next().toList(); + transOutAckPkg.refundAmounts = new uint256[](list.length); + for (uint256 index=0; index= block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); bytes32 bep2TokenSymbol; uint256 convertedAmount; uint256 rewardForRelayer; - if (contractAddr == address(0x0)) { - require(msg.value >= amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); - require(amount % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); - rewardForRelayer = msg.value.sub(amount); + if (contractAddr==address(0x0)) { + require(msg.value>=amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); + require(amount%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); + rewardForRelayer=msg.value.sub(amount); convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 - bep2TokenSymbol = BEP2_TOKEN_SYMBOL_FOR_BNB; + bep2TokenSymbol=BEP2_TOKEN_SYMBOL_FOR_BNB; } else { bep2TokenSymbol = contractAddrToBEP2Symbol[contractAddr]; - require(bep2TokenSymbol != bytes32(0x00), "the contract has not been bound to any bep2 token"); - require(msg.value >= relayFee, "received BNB amount should be no less than the minimum relayFee"); - rewardForRelayer = msg.value; - uint256 bep20TokenDecimals = bep20ContractDecimals[contractAddr]; - require(bep20TokenDecimals <= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals > BEP2_TOKEN_DECIMALS && amount.mod(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)) == 0), "invalid transfer amount: precision loss in amount conversion"); - convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals); // convert to bep2 amount + require(bep2TokenSymbol!=bytes32(0x00), "the contract has not been bound to any bep2 token"); + require(msg.value>=relayFee, "received BNB amount should be no less than the minimum relayFee"); + rewardForRelayer=msg.value; + uint256 bep20TokenDecimals=bep20ContractDecimals[contractAddr]; + require(bep20TokenDecimals<=BEP2_TOKEN_DECIMALS || (bep20TokenDecimals>BEP2_TOKEN_DECIMALS && amount.mod(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS))==0), "invalid transfer amount: precision loss in amount conversion"); + convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals);// convert to bep2 amount if (isMiniBEP2Token(bep2TokenSymbol)) { - require(convertedAmount >= 1e8, "For miniToken, the transfer amount must not be less than 1"); + require(convertedAmount >= 1e8 , "For miniToken, the transfer amount must not be less than 1"); } - require(bep20TokenDecimals >= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals < BEP2_TOKEN_DECIMALS && convertedAmount > amount), "amount is too large, uint256 overflow"); - require(convertedAmount <= MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); + require(bep20TokenDecimals>=BEP2_TOKEN_DECIMALS || (bep20TokenDecimalsamount), "amount is too large, uint256 overflow"); + require(convertedAmount<=MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); require(IBEP20(contractAddr).transferFrom(msg.sender, address(this), amount)); } TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol : bep2TokenSymbol, - contractAddr : contractAddr, - amounts : new uint256[](1), - recipients : new address[](1), - refundAddrs : new address[](1), - expireTime : expireTime + bep2TokenSymbol: bep2TokenSymbol, + contractAddr: contractAddr, + amounts: new uint256[](1), + recipients: new address[](1), + refundAddrs: new address[](1), + expireTime: expireTime }); - transOutSynPkg.amounts[0] = convertedAmount; - transOutSynPkg.recipients[0] = recipient; - transOutSynPkg.refundAddrs[0] = msg.sender; + transOutSynPkg.amounts[0]=convertedAmount; + transOutSynPkg.recipients[0]=recipient; + transOutSynPkg.refundAddrs[0]=msg.sender; ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(contractAddr, msg.sender, amount, rewardForRelayer); return true; @@ -427,34 +427,34 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external override onlyInit payable returns (bool) { require(recipientAddrs.length == amounts.length, "Length of recipientAddrs doesn't equal to length of amounts"); require(recipientAddrs.length == refundAddrs.length, "Length of recipientAddrs doesn't equal to length of refundAddrs"); - require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); uint256 batchLength = amounts.length; uint256 totalAmount = 0; uint256 rewardForRelayer; uint256[] memory convertedAmounts = new uint256[](batchLength); for (uint i = 0; i < batchLength; i++) { - require(amounts[i] % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); + require(amounts[i]%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); totalAmount = totalAmount.add(amounts[i]); convertedAmounts[i] = amounts[i].div(TEN_DECIMALS); } - require(msg.value >= totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); + require(msg.value>=totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); rewardForRelayer = msg.value.sub(totalAmount); TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol : BEP2_TOKEN_SYMBOL_FOR_BNB, - contractAddr : address(0x00), - amounts : convertedAmounts, - recipients : recipientAddrs, - refundAddrs : refundAddrs, - expireTime : expireTime + bep2TokenSymbol: BEP2_TOKEN_SYMBOL_FOR_BNB, + contractAddr: address(0x00), + amounts: convertedAmounts, + recipients: recipientAddrs, + refundAddrs: refundAddrs, + expireTime: expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(address(0x0), msg.sender, totalAmount, rewardForRelayer); return true; } - function updateParam(string calldata key, bytes calldata value) override external onlyGov { + function updateParam(string calldata key, bytes calldata value) override external onlyGov{ require(value.length == 32, "expected value length is 32"); string memory localKey = key; bytes memory localValue = value; @@ -462,12 +462,12 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR assembly { bytes32Key := mload(add(localKey, 32)) } - if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) {// relayFee + if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) { // relayFee uint256 newRelayFee; assembly { newRelayFee := mload(add(localValue, 32)) } - require(newRelayFee <= 1e18 && newRelayFee % (TEN_DECIMALS) == 0, "the relayFee out of range"); + require(newRelayFee <= 1e18 && newRelayFee%(TEN_DECIMALS)==0, "the relayFee out of range"); relayFee = newRelayFee; } else { require(false, "unknown param"); @@ -475,11 +475,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR emit paramChange(key, value); } - function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns (address) { + function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns(address) { return bep2SymbolToContractAddr[bep2Symbol]; } - function getBep2SymbolByContractAddr(address contractAddr) external view override returns (bytes32) { + function getBep2SymbolByContractAddr(address contractAddr) external view override returns(bytes32) { return contractAddrToBEP2Symbol[contractAddr]; } @@ -494,43 +494,43 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR delete contractAddrToBEP2Symbol[contractAddr]; } - function isMiniBEP2Token(bytes32 symbol) internal pure returns (bool) { - bytes memory symbolBytes = new bytes(32); - assembly { - mstore(add(symbolBytes, 32), symbol) - } - uint8 symbolLength = 0; - for (uint8 j = 0; j < 32; j++) { - if (symbolBytes[j] != 0) { - symbolLength++; - } else { - break; - } - } - if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { - return false; - } - if (symbolBytes[symbolLength - 5] != 0x2d) {// '-' - return false; - } - if (symbolBytes[symbolLength - 1] != 'M') {// ABC-XXXM - return false; - } - return true; + function isMiniBEP2Token(bytes32 symbol) internal pure returns(bool) { + bytes memory symbolBytes = new bytes(32); + assembly { + mstore(add(symbolBytes, 32), symbol) + } + uint8 symbolLength = 0; + for (uint8 j = 0; j < 32; j++) { + if (symbolBytes[j] != 0) { + symbolLength++; + } else { + break; + } + } + if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { + return false; + } + if (symbolBytes[symbolLength-5] != 0x2d) { // '-' + return false; + } + if (symbolBytes[symbolLength-1] != 'M') { // ABC-XXXM + return false; + } + return true; } function convertToBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.div(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); + return amount.div(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); } - return amount.mul(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); + return amount.mul(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); } function convertFromBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.mul(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); + return amount.mul(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); } - return amount.div(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); + return amount.div(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); } function getBoundContract(string memory bep2Symbol) public view returns (address) { @@ -545,7 +545,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2SymbolBytes32 = contractAddrToBEP2Symbol[contractAddr]; bytes memory bep2SymbolBytes = new bytes(32); assembly { - mstore(add(bep2SymbolBytes, 32), bep2SymbolBytes32) + mstore(add(bep2SymbolBytes,32), bep2SymbolBytes32) } uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { @@ -557,7 +557,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } bytes memory bep2Symbol = new bytes(bep2SymbolLength); for (uint8 j = 0; j < bep2SymbolLength; j++) { - bep2Symbol[j] = bep2SymbolBytes[j]; + bep2Symbol[j] = bep2SymbolBytes[j]; } return string(bep2Symbol); } diff --git a/contracts/TokenHub.template b/contracts/TokenHub.template index 4a93b03a..a2979006 100644 --- a/contracts/TokenHub.template +++ b/contracts/TokenHub.template @@ -28,7 +28,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256[] amounts; address[] recipients; address[] refundAddrs; - uint64 expireTime; + uint64 expireTime; } // BC to BSC @@ -46,7 +46,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint256 amount; address recipient; address refundAddr; - uint64 expireTime; + uint64 expireTime; } // BSC to BC @@ -70,11 +70,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR uint8 constant public MAXIMUM_BEP20_SYMBOL_LEN = 8; uint8 constant public BEP2_TOKEN_DECIMALS = 8; bytes32 constant public BEP2_TOKEN_SYMBOL_FOR_BNB = 0x424E420000000000000000000000000000000000000000000000000000000000; // "BNB" - uint256 constant public MAX_GAS_FOR_CALLING_BEP20 = {{maxGasForCallingBEP20}}; - uint256 constant public MAX_GAS_FOR_TRANSFER_BNB = {{maxGasForTransferringBNB}}; + uint256 constant public MAX_GAS_FOR_CALLING_BEP20={{maxGasForCallingBEP20}}; + uint256 constant public MAX_GAS_FOR_TRANSFER_BNB={{maxGasForTransferringBNB}}; - uint256 constant public INIT_MINIMUM_RELAY_FEE = {{initRelayFee}}; - uint256 constant public REWARD_UPPER_LIMIT = {{rewardUpperLimit}}; + uint256 constant public INIT_MINIMUM_RELAY_FEE ={{initRelayFee}}; + uint256 constant public REWARD_UPPER_LIMIT ={{rewardUpperLimit}}; uint256 constant public TEN_DECIMALS = 1e10; uint256 public relayFee; @@ -97,32 +97,32 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function init() onlyNotInit external { relayFee = INIT_MINIMUM_RELAY_FEE; bep20ContractDecimals[address(0x0)] = 18; // BNB decimals is 18 - alreadyInit = true; + alreadyInit=true; } - receive() external payable { - if (msg.value > 0) { + receive() external payable{ + if (msg.value>0) { emit receiveDeposit(msg.sender, msg.value); } } - function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns (uint256) { + function claimRewards(address payable to, uint256 amount) onlyInit onlyRelayerIncentivize external override returns(uint256) { uint256 actualAmount = amount < address(this).balance ? amount : address(this).balance; if (actualAmount > REWARD_UPPER_LIMIT) { return 0; } - if (actualAmount > 0) { + if (actualAmount>0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } return actualAmount; } - function getMiniRelayFee() external view override returns (uint256) { + function getMiniRelayFee() external view override returns(uint256) { return relayFee; } - function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns (bytes memory) { + function handleSynPackage(uint8 channelId, bytes calldata msgBytes) onlyInit onlyCrossChainContract external override returns(bytes memory) { if (channelId == TRANSFER_IN_CHANNELID) { return handleTransferInSynPackage(msgBytes); } else { @@ -153,15 +153,15 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx = 0; + uint256 idx=0; while (iter.hasNext()) { - if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); - else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); - else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); - else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); - else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); + if (idx == 0) transInSynPkg.bep2TokenSymbol = bytes32(iter.next().toUint()); + else if (idx == 1) transInSynPkg.contractAddr = iter.next().toAddress(); + else if (idx == 2) transInSynPkg.amount = iter.next().toUint(); + else if (idx == 3) transInSynPkg.recipient = ((iter.next().toAddress())); + else if (idx == 4) transInSynPkg.refundAddr = iter.next().toAddress(); else if (idx == 5) { - transInSynPkg.expireTime = uint64(iter.next().toUint()); + transInSynPkg.expireTime = uint64(iter.next().toUint()); success = true; } else break; @@ -179,17 +179,17 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR return elements.encodeList(); } - function handleTransferInSynPackage(bytes memory msgBytes) internal returns (bytes memory) { + function handleTransferInSynPackage(bytes memory msgBytes) internal returns(bytes memory) { (TransferInSynPackage memory transInSynPkg, bool success) = decodeTransferInSynPackage(msgBytes); require(success, "unrecognized transferIn package"); uint32 resCode = doTransferIn(transInSynPkg); if (resCode != TRANSFER_IN_SUCCESS) { uint256 bep2Amount = convertToBep2Amount(transInSynPkg.amount, bep20ContractDecimals[transInSynPkg.contractAddr]); TransferInRefundPackage memory transInAckPkg = TransferInRefundPackage({ - bep2TokenSymbol : transInSynPkg.bep2TokenSymbol, - refundAmount : bep2Amount, - refundAddr : transInSynPkg.refundAddr, - status : resCode + bep2TokenSymbol: transInSynPkg.bep2TokenSymbol, + refundAmount: bep2Amount, + refundAddr: transInSynPkg.refundAddr, + status: resCode }); return encodeTransferInRefundPackage(transInAckPkg); } else { @@ -198,14 +198,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } function doTransferIn(TransferInSynPackage memory transInSynPkg) internal returns (uint32) { - if (transInSynPkg.contractAddr == address(0x0)) { + if (transInSynPkg.contractAddr==address(0x0)) { if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } if (address(this).balance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - (bool success,) = transInSynPkg.recipient.call{gas : MAX_GAS_FOR_TRANSFER_BNB, value : transInSynPkg.amount}(""); + (bool success, ) = transInSynPkg.recipient.call{gas: MAX_GAS_FOR_TRANSFER_BNB, value: transInSynPkg.amount}(""); if (!success) { return TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT; } @@ -215,14 +215,14 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR if (block.timestamp > transInSynPkg.expireTime) { return TRANSFER_IN_FAILURE_TIMEOUT; } - if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr] != transInSynPkg.bep2TokenSymbol) { + if (contractAddrToBEP2Symbol[transInSynPkg.contractAddr]!= transInSynPkg.bep2TokenSymbol) { return TRANSFER_IN_FAILURE_UNBOUND_TOKEN; } - uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas : MAX_GAS_FOR_CALLING_BEP20}(address(this)); + uint256 actualBalance = IBEP20(transInSynPkg.contractAddr).balanceOf{gas: MAX_GAS_FOR_CALLING_BEP20}(address(this)); if (actualBalance < transInSynPkg.amount) { return TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE; } - bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas : MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); + bool success = IBEP20(transInSynPkg.contractAddr).transfer{gas: MAX_GAS_FOR_CALLING_BEP20}(transInSynPkg.recipient, transInSynPkg.amount); if (success) { emit transferInSuccess(transInSynPkg.contractAddr, transInSynPkg.recipient, transInSynPkg.amount); return TRANSFER_IN_SUCCESS; @@ -232,38 +232,38 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } } - function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns (TransferOutAckPackage memory, bool) { + function decodeTransferOutAckPackage(bytes memory msgBytes) internal pure returns(TransferOutAckPackage memory, bool) { TransferOutAckPackage memory transOutAckPkg; RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); bool success = false; - uint256 idx = 0; + uint256 idx=0; while (iter.hasNext()) { - if (idx == 0) { - transOutAckPkg.contractAddr = iter.next().toAddress(); - } - else if (idx == 1) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAmounts = new uint256[](list.length); - for (uint256 index = 0; index < list.length; index++) { - transOutAckPkg.refundAmounts[index] = list[index].toUint(); + if (idx == 0) { + transOutAckPkg.contractAddr = iter.next().toAddress(); } - } - else if (idx == 2) { - RLPDecode.RLPItem[] memory list = iter.next().toList(); - transOutAckPkg.refundAddrs = new address[](list.length); - for (uint256 index = 0; index < list.length; index++) { - transOutAckPkg.refundAddrs[index] = list[index].toAddress(); + else if (idx == 1) { + RLPDecode.RLPItem[] memory list = iter.next().toList(); + transOutAckPkg.refundAmounts = new uint256[](list.length); + for (uint256 index=0; index= block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); bytes32 bep2TokenSymbol; uint256 convertedAmount; uint256 rewardForRelayer; - if (contractAddr == address(0x0)) { - require(msg.value >= amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); - require(amount % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); - rewardForRelayer = msg.value.sub(amount); + if (contractAddr==address(0x0)) { + require(msg.value>=amount.add(relayFee), "received BNB amount should be no less than the sum of transferOut BNB amount and minimum relayFee"); + require(amount%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); + rewardForRelayer=msg.value.sub(amount); convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 - bep2TokenSymbol = BEP2_TOKEN_SYMBOL_FOR_BNB; + bep2TokenSymbol=BEP2_TOKEN_SYMBOL_FOR_BNB; } else { bep2TokenSymbol = contractAddrToBEP2Symbol[contractAddr]; - require(bep2TokenSymbol != bytes32(0x00), "the contract has not been bound to any bep2 token"); - require(msg.value >= relayFee, "received BNB amount should be no less than the minimum relayFee"); - rewardForRelayer = msg.value; - uint256 bep20TokenDecimals = bep20ContractDecimals[contractAddr]; - require(bep20TokenDecimals <= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals > BEP2_TOKEN_DECIMALS && amount.mod(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)) == 0), "invalid transfer amount: precision loss in amount conversion"); - convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals); // convert to bep2 amount + require(bep2TokenSymbol!=bytes32(0x00), "the contract has not been bound to any bep2 token"); + require(msg.value>=relayFee, "received BNB amount should be no less than the minimum relayFee"); + rewardForRelayer=msg.value; + uint256 bep20TokenDecimals=bep20ContractDecimals[contractAddr]; + require(bep20TokenDecimals<=BEP2_TOKEN_DECIMALS || (bep20TokenDecimals>BEP2_TOKEN_DECIMALS && amount.mod(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS))==0), "invalid transfer amount: precision loss in amount conversion"); + convertedAmount = convertToBep2Amount(amount, bep20TokenDecimals);// convert to bep2 amount if (isMiniBEP2Token(bep2TokenSymbol)) { - require(convertedAmount >= 1e8, "For miniToken, the transfer amount must not be less than 1"); + require(convertedAmount >= 1e8 , "For miniToken, the transfer amount must not be less than 1"); } - require(bep20TokenDecimals >= BEP2_TOKEN_DECIMALS || (bep20TokenDecimals < BEP2_TOKEN_DECIMALS && convertedAmount > amount), "amount is too large, uint256 overflow"); - require(convertedAmount <= MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); + require(bep20TokenDecimals>=BEP2_TOKEN_DECIMALS || (bep20TokenDecimalsamount), "amount is too large, uint256 overflow"); + require(convertedAmount<=MAX_BEP2_TOTAL_SUPPLY, "amount is too large, exceed maximum bep2 token amount"); require(IBEP20(contractAddr).transferFrom(msg.sender, address(this), amount)); } TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol : bep2TokenSymbol, - contractAddr : contractAddr, - amounts : new uint256[](1), - recipients : new address[](1), - refundAddrs : new address[](1), - expireTime : expireTime + bep2TokenSymbol: bep2TokenSymbol, + contractAddr: contractAddr, + amounts: new uint256[](1), + recipients: new address[](1), + refundAddrs: new address[](1), + expireTime: expireTime }); - transOutSynPkg.amounts[0] = convertedAmount; - transOutSynPkg.recipients[0] = recipient; - transOutSynPkg.refundAddrs[0] = msg.sender; + transOutSynPkg.amounts[0]=convertedAmount; + transOutSynPkg.recipients[0]=recipient; + transOutSynPkg.refundAddrs[0]=msg.sender; ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(contractAddr, msg.sender, amount, rewardForRelayer); return true; @@ -427,34 +427,34 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external override onlyInit payable returns (bool) { require(recipientAddrs.length == amounts.length, "Length of recipientAddrs doesn't equal to length of amounts"); require(recipientAddrs.length == refundAddrs.length, "Length of recipientAddrs doesn't equal to length of refundAddrs"); - require(expireTime >= block.timestamp + 120, "expireTime must be two minutes later"); - require(msg.value % TEN_DECIMALS == 0, "invalid received BNB amount: precision loss in amount conversion"); + require(expireTime>=block.timestamp + 120, "expireTime must be two minutes later"); + require(msg.value%TEN_DECIMALS==0, "invalid received BNB amount: precision loss in amount conversion"); uint256 batchLength = amounts.length; uint256 totalAmount = 0; uint256 rewardForRelayer; uint256[] memory convertedAmounts = new uint256[](batchLength); for (uint i = 0; i < batchLength; i++) { - require(amounts[i] % TEN_DECIMALS == 0, "invalid transfer amount: precision loss in amount conversion"); + require(amounts[i]%TEN_DECIMALS==0, "invalid transfer amount: precision loss in amount conversion"); totalAmount = totalAmount.add(amounts[i]); convertedAmounts[i] = amounts[i].div(TEN_DECIMALS); } - require(msg.value >= totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); + require(msg.value>=totalAmount.add(relayFee.mul(batchLength)), "received BNB amount should be no less than the sum of transfer BNB amount and relayFee"); rewardForRelayer = msg.value.sub(totalAmount); TransferOutSynPackage memory transOutSynPkg = TransferOutSynPackage({ - bep2TokenSymbol : BEP2_TOKEN_SYMBOL_FOR_BNB, - contractAddr : address(0x00), - amounts : convertedAmounts, - recipients : recipientAddrs, - refundAddrs : refundAddrs, - expireTime : expireTime + bep2TokenSymbol: BEP2_TOKEN_SYMBOL_FOR_BNB, + contractAddr: address(0x00), + amounts: convertedAmounts, + recipients: recipientAddrs, + refundAddrs: refundAddrs, + expireTime: expireTime }); ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(TRANSFER_OUT_CHANNELID, encodeTransferOutSynPackage(transOutSynPkg), rewardForRelayer.div(TEN_DECIMALS)); emit transferOutSuccess(address(0x0), msg.sender, totalAmount, rewardForRelayer); return true; } - function updateParam(string calldata key, bytes calldata value) override external onlyGov { + function updateParam(string calldata key, bytes calldata value) override external onlyGov{ require(value.length == 32, "expected value length is 32"); string memory localKey = key; bytes memory localValue = value; @@ -462,12 +462,12 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR assembly { bytes32Key := mload(add(localKey, 32)) } - if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) {// relayFee + if (bytes32Key == bytes32(0x72656c6179466565000000000000000000000000000000000000000000000000)) { // relayFee uint256 newRelayFee; assembly { newRelayFee := mload(add(localValue, 32)) } - require(newRelayFee <= 1e18 && newRelayFee % (TEN_DECIMALS) == 0, "the relayFee out of range"); + require(newRelayFee <= 1e18 && newRelayFee%(TEN_DECIMALS)==0, "the relayFee out of range"); relayFee = newRelayFee; } else { require(false, "unknown param"); @@ -475,11 +475,11 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR emit paramChange(key, value); } - function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns (address) { + function getContractAddrByBEP2Symbol(bytes32 bep2Symbol) external view override returns(address) { return bep2SymbolToContractAddr[bep2Symbol]; } - function getBep2SymbolByContractAddr(address contractAddr) external view override returns (bytes32) { + function getBep2SymbolByContractAddr(address contractAddr) external view override returns(bytes32) { return contractAddrToBEP2Symbol[contractAddr]; } @@ -494,43 +494,43 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR delete contractAddrToBEP2Symbol[contractAddr]; } - function isMiniBEP2Token(bytes32 symbol) internal pure returns (bool) { - bytes memory symbolBytes = new bytes(32); - assembly { - mstore(add(symbolBytes, 32), symbol) - } - uint8 symbolLength = 0; - for (uint8 j = 0; j < 32; j++) { - if (symbolBytes[j] != 0) { - symbolLength++; - } else { - break; - } - } - if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { - return false; - } - if (symbolBytes[symbolLength - 5] != 0x2d) {// '-' - return false; - } - if (symbolBytes[symbolLength - 1] != 'M') {// ABC-XXXM - return false; - } - return true; + function isMiniBEP2Token(bytes32 symbol) internal pure returns(bool) { + bytes memory symbolBytes = new bytes(32); + assembly { + mstore(add(symbolBytes, 32), symbol) + } + uint8 symbolLength = 0; + for (uint8 j = 0; j < 32; j++) { + if (symbolBytes[j] != 0) { + symbolLength++; + } else { + break; + } + } + if (symbolLength < MINIMUM_BEP20_SYMBOL_LEN + 5) { + return false; + } + if (symbolBytes[symbolLength-5] != 0x2d) { // '-' + return false; + } + if (symbolBytes[symbolLength-1] != 'M') { // ABC-XXXM + return false; + } + return true; } function convertToBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.div(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); + return amount.div(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); } - return amount.mul(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); + return amount.mul(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); } function convertFromBep2Amount(uint256 amount, uint256 bep20TokenDecimals) internal pure returns (uint256) { if (bep20TokenDecimals > BEP2_TOKEN_DECIMALS) { - return amount.mul(10 ** (bep20TokenDecimals - BEP2_TOKEN_DECIMALS)); + return amount.mul(10**(bep20TokenDecimals-BEP2_TOKEN_DECIMALS)); } - return amount.div(10 ** (BEP2_TOKEN_DECIMALS - bep20TokenDecimals)); + return amount.div(10**(BEP2_TOKEN_DECIMALS-bep20TokenDecimals)); } function getBoundContract(string memory bep2Symbol) public view returns (address) { @@ -545,7 +545,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR bytes32 bep2SymbolBytes32 = contractAddrToBEP2Symbol[contractAddr]; bytes memory bep2SymbolBytes = new bytes(32); assembly { - mstore(add(bep2SymbolBytes, 32), bep2SymbolBytes32) + mstore(add(bep2SymbolBytes,32), bep2SymbolBytes32) } uint8 bep2SymbolLength = 0; for (uint8 j = 0; j < 32; j++) { @@ -557,7 +557,7 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } bytes memory bep2Symbol = new bytes(bep2SymbolLength); for (uint8 j = 0; j < bep2SymbolLength; j++) { - bep2Symbol[j] = bep2SymbolBytes[j]; + bep2Symbol[j] = bep2SymbolBytes[j]; } return string(bep2Symbol); } diff --git a/contracts/interface/IBSCValidatorSet.sol b/contracts/interface/IBSCValidatorSet.sol index 51f3e9fe..3a6f2407 100644 --- a/contracts/interface/IBSCValidatorSet.sol +++ b/contracts/interface/IBSCValidatorSet.sol @@ -3,7 +3,7 @@ pragma experimental ABIEncoderV2; interface IBSCValidatorSet { function misdemeanor(address validator) external; - function felony(address validator) external; + function felony(address validator)external; function isCurrentValidator(address validator) external view returns (bool); function getLivingValidators() external view returns(address[] memory, bytes[] memory); function getMiningValidators() external view returns(address[] memory, bytes[] memory); diff --git a/generate-validator.js b/generate-validator.js index 338d3605..7246b684 100644 --- a/generate-validator.js +++ b/generate-validator.js @@ -1,5 +1,5 @@ const fs = require("fs"); -const readline = require("readline"); +const readline = require('readline'); const nunjucks = require("nunjucks"); const BLSKeys = require("./BLSkeystore.json"); @@ -9,12 +9,12 @@ async function processValidatorConf() { const rl = readline.createInterface({ input: fileStream, - crlfDelay: Infinity, + crlfDelay: Infinity }); let validators = []; for await (const line of rl) { // Each line in input.txt will be successively available here as `line`. - let vs = line.split(","); + let vs = line.split(",") validators.push({ consensusAddr: vs[0], feeAddr: vs[1], @@ -31,8 +31,8 @@ processValidatorConf().then(function (validators, bLSPublicKeys) { validators: validators, bLSPublicKeys: bLSPublicKeys, }; - const templateString = fs.readFileSync(__dirname + "/validators.template").toString(); + const templateString = fs.readFileSync(__dirname + '/validators.template').toString(); const resultString = nunjucks.renderString(templateString, data); - fs.writeFileSync(__dirname + "/validators.js", resultString); + fs.writeFileSync(__dirname + '/validators.js', resultString); console.log("BSCValidatorSet file updated."); -}); +}) diff --git a/test/BSCValidatorSet.js b/test/BSCValidatorSet.js index 06062a0f..78f7f52e 100644 --- a/test/BSCValidatorSet.js +++ b/test/BSCValidatorSet.js @@ -3,12 +3,12 @@ const SystemReward = artifacts.require("SystemReward"); const LightClient = artifacts.require("MockLightClient"); const RelayerIncentivize = artifacts.require("RelayerIncentivize"); const TokenManager = artifacts.require("TokenManager"); -const crypto = require("crypto"); +const crypto = require('crypto'); const MockTokenHub = artifacts.require("mock/MockTokenHub"); -const Web3 = require("web3"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); -const RLP = require("rlp"); -const truffleAssert = require("truffle-assertions"); +const Web3 = require('web3'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); +const RLP = require('rlp'); +const truffleAssert = require('truffle-assertions'); const CrossChain = artifacts.require("CrossChain"); const GovHub = artifacts.require("GovHub"); const RelayerHub = artifacts.require("RelayerHub"); @@ -19,57 +19,55 @@ const SlashIndicator = artifacts.require("SlashIndicator"); const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; -const packageBytesPrefix = Buffer.from( - web3.utils.hexToBytes("0x00" + "000000000000000000000000000000000000000000000000002386F26FC10000") -); +const packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( + "0x00" + + "000000000000000000000000000000000000000000000000002386F26FC10000" +)); -contract("BSCValidatorSet", (accounts) => { - it("query basic info", async () => { +contract('BSCValidatorSet', (accounts) => { + it('query basic info', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let totalInComing = await validatorSetInstance.totalInComing.call(); - assert.equal(totalInComing, 0, "totalInComing should be 0"); + assert.equal(totalInComing,0, "totalInComing should be 0"); let consensusAddr = await validatorSetInstance.getValidators.call(); assert.equal(consensusAddr[0], accounts[0], "consensusAddr should be accounts[0]"); }); - it("deposit success and fail", async () => { + it('deposit success and fail', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); - let validator = accounts[0]; + let validator = accounts[0]; let systemAccount = accounts[0]; - let tx = await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); + let tx = await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); - truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "validatorDeposit",(ev) => { return ev.amount.toNumber() === 1e8 && ev.validator === validator; }); let tmpAccount = web3.eth.accounts.create(); - tx = await validatorSetInstance.deposit(tmpAccount.address, { - from: systemAccount, - value: 1e8, - }); + tx = await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: 1e8 }); - truffleAssert.eventEmitted(tx, "deprecatedDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "deprecatedDeposit",(ev) => { return ev.amount.toNumber() === 1e8 && ev.validator === tmpAccount.address; }); - try { - await validatorSetInstance.deposit(validator, { from: accounts[2], value: 1e8 }); + try{ + await validatorSetInstance.deposit(validator, {from: accounts[2], value: 1e8 }); assert.fail(); - } catch (error) { + }catch (error) { assert.ok(error.toString().includes("the message sender must be the block producer")); } - try { - await validatorSetInstance.deposit(validator, { from: systemAccount, value: 0 }); + try{ + await validatorSetInstance.deposit(validator, {from: systemAccount, value: 0 }); assert.fail(); - } catch (error) { + }catch (error) { assert.ok(error.toString().includes("deposit value is zero")); } let totalInComing = await validatorSetInstance.totalInComing.call(); - assert.equal(totalInComing.toNumber(), 1e8, "totalInComing should be 1e8"); + assert.equal(totalInComing.toNumber(),1e8, "totalInComing should be 1e8"); let balance_wei = await web3.eth.getBalance(validatorSetInstance.address); assert.equal(balance_wei, 2e8, "balance not equal"); @@ -178,27 +176,22 @@ contract("BSCValidatorSet", (accounts) => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let validator = accounts[0]; + let validator = accounts[0]; let systemAccount = accounts[0]; let tmpAccount = web3.eth.accounts.create(); // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); - for (let i = 0; i < 5; i++) { - await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); - await validatorSetInstance.deposit(tmpAccount.address, { from: systemAccount, value: 1e8 }); + + for(let i =0;i <5; i++){ + await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); + await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: 1e8 }); } - for (let i = 0; i < 5; i++) { - await validatorSetInstance.deposit(validator, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(tmpAccount.address, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); + for(let i =0;i <5; i++){ + await validatorSetInstance.deposit(validator, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(tmpAccount.address, {from: systemAccount, value: web3.utils.toBN(1e18) }); } let newValidator = web3.eth.accounts.create(); @@ -209,28 +202,19 @@ contract("BSCValidatorSet", (accounts) => { let totalInComing = await validatorSetInstance.totalInComing.call(); let relayerBalance = await web3.eth.getBalance(relayerAccount); - assert.equal( - totalInComing.toString(), - web3.utils.toBN(5e18).add(web3.utils.toBN(5e8)).toString(), - "totalInComing is not correct" - ); - assert.equal( - totalBalance.toString(), - web3.utils.toBN(1e19).add(web3.utils.toBN(1e9)).toString(), - "totalBalance is not correct" - ); + assert.equal(totalInComing.toString(), web3.utils.toBN(5e18).add(web3.utils.toBN(5e8)).toString(), "totalInComing is not correct"); + assert.equal(totalBalance.toString(), web3.utils.toBN(1e19).add(web3.utils.toBN(1e9)).toString(), "totalbalance is not correct"); // do update - let packageBytes = validatorUpdateRlpEncode([newValidator.address], [newValidator.address], [newValidator.address]); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode([newValidator.address], + [newValidator.address],[newValidator.address]); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(5e18).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(5e18).add(web3.utils.toBN(1e9)).toString(); }); @@ -241,18 +225,16 @@ contract("BSCValidatorSet", (accounts) => { totalInComing = await validatorSetInstance.totalInComing.call(); let afterRelayerBalance = await web3.eth.getBalance(relayerAccount); - assert.equal( - web3.utils.toBN(relayerBalance).sub(web3.utils.toBN(afterRelayerBalance)).toString(), - used_wei.toString(), - "totalInComing is not correct" - ); + assert.equal(web3.utils.toBN(relayerBalance).sub(web3.utils.toBN(afterRelayerBalance)).toString(), used_wei.toString(), "totalInComing is not correct"); assert.equal(totalInComing.toNumber(), 0, "totalInComing is not correct"); - assert.equal(totalBalance, 0, "totalBalance is not correct"); + assert.equal(totalBalance, 0, "totalbalance is not correct"); + }); + }); -contract("BSCValidatorSet", (accounts) => { - it("test distribute algorithm with 41 validators", async () => { +contract('BSCValidatorSet', (accounts) => { + it('test distribute algorithm with 41 validators', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -260,16 +242,15 @@ contract("BSCValidatorSet", (accounts) => { let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); let newValidators = []; - for (let i = 0; i < 41; i++) { - newValidators.push(web3.eth.accounts.create().address); + for(let i =0;i <41; i++) { + newValidators.push(web3.eth.accounts.create().address) } - let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(newValidators, + newValidators,newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); // do deposit let receipt; @@ -285,23 +266,23 @@ contract("BSCValidatorSet", (accounts) => { // do update let updateValidators = []; - for (let i = 0; i < 41; i++) { - updateValidators.push(web3.eth.accounts.create().address); + for(let i =0;i <41; i++) { + updateValidators.push(web3.eth.accounts.create().address) } - packageBytes = validatorUpdateRlpEncode(updateValidators, updateValidators, updateValidators); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); - console.log("The total gasUsed is", tx.receipt.gasUsed); + packageBytes = validatorUpdateRlpEncode(updateValidators, + updateValidators,updateValidators); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + console.log("The total gasUsd is", tx.receipt.gasUsed) }); + }); -contract("BSCValidatorSet", (accounts) => { - it("complicate validatorSet change and test validatorSet map", async () => { +contract('BSCValidatorSet', (accounts) => { + it('complicate validatorSet change and test valdiatorset map', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let validatorA = accounts[0]; + let validatorA = accounts[0]; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; @@ -309,121 +290,97 @@ contract("BSCValidatorSet", (accounts) => { let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); await validatorSetInstance.getValidators.call(); - let arrs = [ - [validatorB, validatorA, validatorC, validatorD], - [validatorB, validatorC, validatorE], - [validatorB, validatorC, validatorE], - [validatorE, validatorC, validatorB], - [validatorE, validatorC, validatorB, validatorA, validatorD], - [validatorE, validatorC, validatorB, validatorA], - ]; - for (let j = 0; j < arrs.length; j++) { + let arrs = [[validatorB,validatorA,validatorC,validatorD], + [validatorB,validatorC,validatorE], + [validatorB,validatorC,validatorE], + [validatorE,validatorC,validatorB], + [validatorE,validatorC,validatorB,validatorA,validatorD], + [validatorE,validatorC,validatorB,validatorA]]; + for(let j=0;j { - it("failed to update", async () => { + +contract('BSCValidatorSet', (accounts) => { + it('failed to update', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); const crossChain = await CrossChain.deployed(); - let validatorA = accounts[0]; + let validatorA = accounts[0]; let validatorB = web3.eth.accounts.create().address; let validatorC = web3.eth.accounts.create().address; let validatorD = web3.eth.accounts.create().address; let validatorE = web3.eth.accounts.create().address; let relayerAccount = accounts[8]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); - - let arrs = [ - [validatorB, validatorA, validatorC, validatorD], - [validatorB, validatorB, validatorE], - [validatorC, validatorC, validatorB], - [], - ]; + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); + + let arrs = [[validatorB,validatorA,validatorC,validatorD], + [validatorB,validatorB,validatorE], + [validatorC,validatorC,validatorB], + []]; let packageBytes = validatorUpdateRlpEncode(arrs[0], arrs[0], arrs[0]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - for (let j = 1; j < arrs.length - 1; j++) { + for(let j=1;j { + let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { return ev.message === "duplicate consensus address of validatorSet"; }); } - let arr = arrs[3]; + let arr =arrs[3]; - packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); truffleAssert.eventNotEmitted(tx, "failReasonWithStr"); // block the light client const lightClientInstance = await LightClient.deployed(); await lightClientInstance.setBlockNotSynced(true); let validArray = arrs[0]; - try { - packageBytes = validatorUpdateRlpEncode(validArray, validArray, validArray); - await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - crypto.randomBytes(32), - 100, - 0, - STAKE_CHANNEL_ID, - { from: relayerAccount } - ); + try{ + packageBytes = validatorUpdateRlpEncode(validArray, validArray,validArray); + await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), crypto.randomBytes(32),100, 0, STAKE_CHANNEL_ID, {from: relayerAccount}); assert.fail(); - } catch (error) { + }catch(error){ assert.ok(error.toString().includes("light client not sync the block yet")); } await lightClientInstance.setBlockNotSynced(false); - try { - packageBytes = validatorUpdateRlpEncode(validArray, validArray, validArray); - await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - crypto.randomBytes(32), - 100, - 0, - STAKE_CHANNEL_ID, - { from: accounts[4] } - ); + try{ + packageBytes = validatorUpdateRlpEncode(validArray, validArray,validArray); + await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), crypto.randomBytes(32),100, 0, STAKE_CHANNEL_ID, {from: accounts[4]}); assert.fail(); - } catch (error) { + }catch(error){ assert.ok(error.toString().includes("the msg sender is not a relayer")); } + }); }); -contract("BSCValidatorSet", (accounts) => { - it("complicate distribute", async () => { +contract('BSCValidatorSet', (accounts) => { + it('complicate distribute', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -437,52 +394,27 @@ contract("BSCValidatorSet", (accounts) => { let systemAccount = accounts[0]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); await validatorSetInstance.getValidators.call(); - let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; + let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorB, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorC, { - from: systemAccount, - value: web3.utils.toBN(1e17), - }); - await validatorSetInstance.deposit(validatorD, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(deprecated, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); + await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); + await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e5), - }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); - packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); let validatorCBalance = await web3.eth.getBalance(validatorC); @@ -490,28 +422,29 @@ contract("BSCValidatorSet", (accounts) => { let validatorEBalance = await web3.eth.getBalance(validatorE); let deprecatedBalance = await web3.eth.getBalance(deprecated); - assert.equal(validatorABalance, web3.utils.toBN(1e16)); - assert.equal(validatorBBalance, web3.utils.toBN(1e16)); - assert.equal(validatorCBalance, 0); - assert.equal(validatorDBalance, 0); - assert.equal(validatorEBalance, 0); - assert.equal(deprecatedBalance, 0); + assert.equal(validatorABalance,web3.utils.toBN(1e16)); + assert.equal(validatorBBalance,web3.utils.toBN(1e16)); + assert.equal(validatorCBalance,0); + assert.equal(validatorDBalance,0); + assert.equal(validatorEBalance,0); + assert.equal(deprecatedBalance,0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).toString(); }); }); }); -contract("BSCValidatorSet", (accounts) => { - it("complicate distribute when one validator fee addr is contract", async () => { + +contract('BSCValidatorSet', (accounts) => { + it('complicate distribute when one validar fee addr is contract', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); const crossChainInstance = await CrossChain.deployed(); @@ -526,52 +459,27 @@ contract("BSCValidatorSet", (accounts) => { let systemAccount = accounts[0]; // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); await validatorSetInstance.getValidators.call(); - let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; + let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorB, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorC, { - from: systemAccount, - value: web3.utils.toBN(1e17), - }); - await validatorSetInstance.deposit(validatorD, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(deprecated, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); + await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); + await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e5), - }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); - packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); @@ -580,33 +488,31 @@ contract("BSCValidatorSet", (accounts) => { let validatorEBalance = await web3.eth.getBalance(validatorE); let deprecatedBalance = await web3.eth.getBalance(deprecated); - assert.equal(validatorABalance, 0); - assert.equal(validatorBBalance, web3.utils.toBN(1e16)); - assert.equal(validatorCBalance, 0); - assert.equal(validatorDBalance, 0); - assert.equal(validatorEBalance, 0); - assert.equal(deprecatedBalance, 0); + assert.equal(validatorABalance,0); + assert.equal(validatorBBalance,web3.utils.toBN(1e16)); + assert.equal(validatorCBalance,0); + assert.equal(validatorDBalance,0); + assert.equal(validatorEBalance,0); + assert.equal(deprecatedBalance,0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "batchTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "directTransferFail", (ev) => { + truffleAssert.eventEmitted(tx, "directTransferFail",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { - return ( - ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).add(web3.utils.toBN(1e16)).toString() - ); + truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { + return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e5)).add(web3.utils.toBN(1e16)).toString(); }); }); }); -contract("BSCValidatorSet", (accounts) => { - it("complicate distribute when cross chain transfer failed", async () => { +contract('BSCValidatorSet', (accounts) => { + it('complicate distribute when cross chain transfer failed', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); const crossChainInstance = await CrossChain.deployed(); @@ -620,55 +526,30 @@ contract("BSCValidatorSet", (accounts) => { let deprecated = web3.eth.accounts.create().address; let relayerAccount = accounts[8]; let systemAccount = accounts[0]; - await tokenHub.setPanicBatchTransferOut(true); + await tokenHub.setPanicBatchTransferOut(true); // enough reward in system reward pool - await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); + await systemRewardInstance.send(web3.utils.toBN(1e18), {from: accounts[1]}); await validatorSetInstance.getValidators.call(); - let arr = [validatorA, validatorB, validatorC, validatorD, validatorE]; + let arr = [validatorA,validatorB,validatorC,validatorD,validatorE]; - let packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); // deposit A: 1e16 B:1e16 C:1e17, D: 1e18, E:1e19, deprecated: 1e18 - await validatorSetInstance.deposit(validatorA, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorB, { - from: systemAccount, - value: web3.utils.toBN(1e16), - }); - await validatorSetInstance.deposit(validatorC, { - from: systemAccount, - value: web3.utils.toBN(1e17), - }); - await validatorSetInstance.deposit(validatorD, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); - await validatorSetInstance.deposit(deprecated, { - from: systemAccount, - value: web3.utils.toBN(1e18), - }); + await validatorSetInstance.deposit(validatorA, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorB, {from: systemAccount, value: web3.utils.toBN(1e16) }); + await validatorSetInstance.deposit(validatorC, {from: systemAccount, value: web3.utils.toBN(1e17) }); + await validatorSetInstance.deposit(validatorD, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e18) }); + await validatorSetInstance.deposit(deprecated, {from: systemAccount, value: web3.utils.toBN(1e18) }); //add some dust incoming - await validatorSetInstance.deposit(validatorE, { - from: systemAccount, - value: web3.utils.toBN(1e5), - }); + await validatorSetInstance.deposit(validatorE, {from: systemAccount, value: web3.utils.toBN(1e5) }); - packageBytes = validatorUpdateRlpEncode(arr, arr, arr); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + packageBytes = validatorUpdateRlpEncode(arr, arr,arr); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); let validatorABalance = await web3.eth.getBalance(validatorA); let validatorBBalance = await web3.eth.getBalance(validatorB); @@ -685,23 +566,23 @@ contract("BSCValidatorSet", (accounts) => { assert.equal(deprecatedBalance, 0); truffleAssert.eventEmitted(tx, "validatorSetUpdated"); - truffleAssert.eventEmitted(tx, "batchTransferFailed", (ev) => { + truffleAssert.eventEmitted(tx, "batchTransferFailed",(ev) => { return ev.amount.toString() === web3.utils.toBN(21e17).toString(); }); - truffleAssert.eventEmitted(tx, "directTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "directTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "directTransferFail", (ev) => { + truffleAssert.eventEmitted(tx, "directTransferFail",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e16).toString(); }); - truffleAssert.eventEmitted(tx, "systemTransfer", (ev) => { + truffleAssert.eventEmitted(tx, "systemTransfer",(ev) => { return ev.amount.toString() === web3.utils.toBN(1e18).add(web3.utils.toBN(1e16)).toString(); }); }); }); -contract("BSCValidatorSet", (accounts) => { - it("validator jail", async () => { +contract('BSCValidatorSet', (accounts) => { + it('validator jail', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let newValidator1 = web3.eth.accounts.create(); @@ -710,84 +591,66 @@ contract("BSCValidatorSet", (accounts) => { let relayerAccount = accounts[8]; // do update - let packageBytes = validatorUpdateRlpEncode( - [newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address] - ); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode([newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address], [newValidator1.address, newValidator2.address, newValidator3.address]); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - let consensusAddrs = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddrs.length, 3); - assert.equal(consensusAddrs[0], newValidator1.address); - assert.equal(consensusAddrs[1], newValidator2.address); - assert.equal(consensusAddrs[2], newValidator3.address); + let consensusAddres = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddres.length, 3); + assert.equal(consensusAddres[0], newValidator1.address); + assert.equal(consensusAddres[1], newValidator2.address); + assert.equal(consensusAddres[2], newValidator3.address); - packageBytes = jailRlpEncode( - [newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address], - [newValidator1.address, newValidator2.address, newValidator3.address] - ); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + packageBytes = jailRlpEncode([newValidator1.address, newValidator2.address, newValidator3.address], + [newValidator1.address, newValidator2.address, newValidator3.address], [newValidator1.address, newValidator2.address, newValidator3.address]); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { return ev.message === "length of jail validators must be one"; }); packageBytes = jailRlpEncode([newValidator1.address], [newValidator1.address], [newValidator1.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - consensusAddrs = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddrs.length, 2); - assert.equal(consensusAddrs[0], newValidator2.address); - assert.equal(consensusAddrs[1], newValidator3.address); + consensusAddres = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddres.length, 2); + assert.equal(consensusAddres[0], newValidator2.address); + assert.equal(consensusAddres[1], newValidator3.address); // ok to re jail packageBytes = jailRlpEncode([newValidator1.address], [newValidator1.address], [newValidator1.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); packageBytes = jailRlpEncode([newValidator2.address], [newValidator2.address], [newValidator2.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - consensusAddrs = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddrs.length, 1); - assert.equal(consensusAddrs[0], newValidator3.address); + consensusAddres = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddres.length, 1); + assert.equal(consensusAddres[0], newValidator3.address); // can not jail if it is the last one validator packageBytes = jailRlpEncode([newValidator3.address], [newValidator3.address], [newValidator3.address]); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + + consensusAddres = await validatorSetInstance.getValidators.call(); + assert.equal(consensusAddres.length, 1); + assert.equal(consensusAddres[0], newValidator3.address); - consensusAddrs = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddrs.length, 1); - assert.equal(consensusAddrs[0], newValidator3.address); }); }); -contract("BSCValidatorSet", (accounts) => { - it("test distribute algorithm with more than 41 validators", async () => { +contract('BSCValidatorSet', (accounts) => { + it('test distribute algorithm with more than 41 validators', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let relayerAccount = accounts[8]; let newValidators = []; for (let i = 0; i < 42; i++) { - newValidators.push(web3.eth.accounts.create().address); + newValidators.push(web3.eth.accounts.create().address) } - let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); - let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(newValidators, + newValidators, newValidators); + let tx = await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { return ev.message === "the number of validators exceed the limit"; @@ -795,165 +658,97 @@ contract("BSCValidatorSet", (accounts) => { }); }); -contract("BSCValidatorSet", (accounts) => { - it("burn", async () => { +contract('BSCValidatorSet', (accounts) => { + it('burn', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); let systemAccount = accounts[0]; - let validator = accounts[0]; + let validator = accounts[0]; const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); + await relayerInstance.register({from: relayer, value: 1e20}); let initialBurnRatio = await validatorSetInstance.burnRatio.call(); assert.equal(web3.utils.toBN(initialBurnRatio).eq(web3.utils.toBN(0)), true, "wrong burnRatio"); - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - LightClient.address, - MockTokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - crossChain.address - ); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000BB8"; // 3000; + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000BB8";// 3000; let govPackageBytes = serializeGovPack("burnRatio", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); let burnRatio = await validatorSetInstance.burnRatio.call(); assert.equal(web3.utils.toBN(burnRatio).eq(web3.utils.toBN(3000)), true, "wrong burnRatio"); - let tx = await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e8 }); + let tx = await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e8 }); - truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "validatorDeposit",(ev) => { return ev.amount.toNumber() === 7e7 && ev.validator === validator; }); - truffleAssert.eventEmitted(tx, "feeBurned", (ev) => { + truffleAssert.eventEmitted(tx, "feeBurned",(ev) => { return ev.amount.toNumber() === 3e7; }); }); }); -contract("BSCValidatorSet", (accounts) => { - it("test set maxNumOfWorkingCandidates greater than maxNumOfCandidates", async () => { +contract('BSCValidatorSet', (accounts) => { + it('test set maxNumOfWorkingCandidates greater than maxNumOfCandidates', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); + await relayerInstance.register({from: relayer, value: 1e20}); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - LightClient.address, - MockTokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - crossChain.address - ); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); // should fail - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000002"; // 2; - let govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - let except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; + govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(0)), true, "wrong maxNumOfWorkingCandidates"); }); }); -contract("BSCValidatorSet", (accounts) => { - it("test set maxNumOfCandidates less than maxNumOfWorkingCandidates", async () => { +contract('BSCValidatorSet', (accounts) => { + it('test set maxNumOfCandidates less than maxNumOfWorkingCandidates', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); + await relayerInstance.register({from: relayer, value: 1e20}); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - LightClient.address, - MockTokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - crossChain.address - ); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); // set maxNumOfCandidates to 20 - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000014"; // 20; - let govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; + govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); - let except = await validatorSetInstance.maxNumOfCandidates.call(); + except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); // set maxNumOfWorkingCandidates to 10 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x000000000000000000000000000000000000000000000000000000000000000A"; // 10; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x000000000000000000000000000000000000000000000000000000000000000A";// 10; govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(10)), true, "wrong maxNumOfWorkingCandidates"); // set maxNumOfCandidates to 5 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000000000000000000005"; // 5; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000005";// 5; govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(5)), true, "wrong maxNumOfCandidates"); @@ -962,49 +757,30 @@ contract("BSCValidatorSet", (accounts) => { }); }); -contract("BSCValidatorSet", (accounts) => { - it("test getMiningValidators with 41 validators", async () => { +contract('BSCValidatorSet', (accounts) => { + it('test getMiningValidators with 41 validators', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); const relayer = accounts[2]; const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); + await relayerInstance.register({from: relayer, value: 1e20}); const crossChain = await CrossChain.deployed(); const govHub = await GovHub.deployed(); - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - LightClient.address, - MockTokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - crossChain.address - ); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, LightClient.address, MockTokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, crossChain.address); let relayerAccount = accounts[8]; let newValidators = []; for (let i = 0; i < 41; i++) { - newValidators.push(web3.eth.accounts.create().address); + newValidators.push(web3.eth.accounts.create().address) } - let packageBytes = validatorUpdateRlpEncode(newValidators, newValidators, newValidators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { - from: relayerAccount, - }); + let packageBytes = validatorUpdateRlpEncode(newValidators, + newValidators, newValidators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, {from: relayerAccount}); // set numOfCabinets to 21 let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x0000000000000000000000000000000000000000000000000000000000000015"; // 21; + let govValue = "0x0000000000000000000000000000000000000000000000000000000000000015";// 21; let govPackageBytes = serializeGovPack("numOfCabinets", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); let except = await validatorSetInstance.numOfCabinets.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(21)), true, "wrong numOfCabinets"); @@ -1017,38 +793,24 @@ contract("BSCValidatorSet", (accounts) => { assert.deepEqual(validators.slice(0, numOfCabinets), miningValidators, "wrong validators"); // set maxNumOfCandidates to 20 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000000000000000000014"; // 20; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000014";// 20; govPackageBytes = serializeGovPack("maxNumOfCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); except = await validatorSetInstance.maxNumOfCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(20)), true, "wrong maxNumOfCandidates"); // set maxNumOfWorkingCandidates to 2 - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000000000000000000002"; // 2; + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID) + govValue = "0x0000000000000000000000000000000000000000000000000000000000000002";// 2; govPackageBytes = serializeGovPack("maxNumOfWorkingCandidates", govValue, validatorSetInstance.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); except = await validatorSetInstance.maxNumOfWorkingCandidates.call(); assert.equal(web3.utils.toBN(except).eq(web3.utils.toBN(2)), true, "wrong maxNumOfWorkingCandidates"); - if (validators.length - numOfCabinets < maxNumOfWorkingCandidates) { + if ((validators.length - numOfCabinets) < maxNumOfWorkingCandidates){ maxNumOfWorkingCandidates = validators.length - numOfCabinets; } @@ -1058,34 +820,35 @@ contract("BSCValidatorSet", (accounts) => { return !exceptValues.includes(addr); }); // TODO, this is not always true, but as the epoch number is fixed during UT, the result is fixed. - assert(outValidator.length > 0, "no validator choose from candidates"); - assert(outValidator.length <= maxNumOfWorkingCandidates, "too many working candidates"); + assert(outValidator.length > 0, "no validator choose from candidates"); + assert(outValidator.length <= maxNumOfWorkingCandidates, "too many working candidates" ) + }); }); -function jailRlpEncode(consensusAddrList, feeAddrList, bscFeeAddrList) { +function jailRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) { let pkg = []; pkg.push(0x01); let n = consensusAddrList.length; let vals = []; - for (let i = 0; i < n; i++) { + for(let i = 0;i { - it("Gov validatorSet", async () => { - const govHubInstance = await GovHub.deployed(); - const bSCValidatorSetInstance = await BSCValidatorSet.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "expireTimeSecondGap", - "0x0000000000000000000000000000000000000000000000000000000000010000", - bSCValidatorSetInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "expireTimeSecondGap"; - }); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); - let reward = await bSCValidatorSetInstance.expireTimeSecondGap.call(); - assert.equal(reward.toNumber(), 65536, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "finalityRewardRatio", - "0x0000000000000000000000000000000000000000000000000000000000000032", - bSCValidatorSetInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "finalityRewardRatio"; - }); +contract('GovHub others', (accounts) => { + it("Gov validatorSet", async () => { + const govHubInstance = await GovHub.deployed(); + const bSCValidatorSetInstance =await BSCValidatorSet.deployed(); - let rewardRatio = await bSCValidatorSetInstance.finalityRewardRatio.call(); - assert.equal(rewardRatio.toNumber(), 50, "value not equal"); - }); - - it("Gov tokenhub", async () => { - const govHubInstance = await GovHub.deployed(); - const tokenHub = await TokenHub.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("relayFee", "0x00000000000000000000000000000000000000000000000000038d7ea4c68000", tokenHub.address), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "relayFee"; - }); + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("expireTimeSecondGap", "0x0000000000000000000000000000000000000000000000000000000000010000", bSCValidatorSetInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "expireTimeSecondGap"; + }); - let minimumRelayFee = await tokenHub.relayFee.call(); - assert.equal(minimumRelayFee.toNumber(), 1000000000000000, "value not equal"); - }); - - it("Gov tendermintLightClient", async () => { - const govHubInstance = await GovHub.deployed(); - const tendermintLightClient = await TendermintLightClient.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "rewardForValidatorSetChange", - "0x0000000000000000000000000000000000000000000000000000000000010000", - TendermintLightClient.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "rewardForValidatorSetChange"; - }); + let reward = await bSCValidatorSetInstance.expireTimeSecondGap.call(); + assert.equal(reward.toNumber(), 65536, "value not equal"); - let rewardForValidatorSetChange = await tendermintLightClient.rewardForValidatorSetChange.call(); - assert.equal(rewardForValidatorSetChange.toNumber(), 65536, "value not equal"); - }); - - it("Gov RelayerHub", async () => { - const govHubInstance = await GovHub.deployed(); - const relayerHub = await RelayerHub.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "requiredDeposit", - "0x0000000000000000000000000000000000000000000000000000000000010000", - relayerHub.address - ), - { from: relayerAccount } - ); - - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the requiredDeposit out of range"; - }); + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "finalityRewardRatio", + "0x0000000000000000000000000000000000000000000000000000000000000032", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "finalityRewardRatio"; + }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "requiredDeposit", - "0x0010000000000000000000000000000000000000000000000000000000000000", - relayerHub.address - ), - { from: relayerAccount } - ); - - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the requiredDeposit out of range"; + let rewardRatio = await bSCValidatorSetInstance.finalityRewardRatio.call(); + assert.equal(rewardRatio.toNumber(), 50, "value not equal"); }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "requiredDeposit", - "0x0000000000000000000000000000000000000000000000000000000000000000", - relayerHub.address - ), - { from: relayerAccount } - ); - - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the requiredDeposit out of range"; - }); + it('Gov tokenhub', async () => { + const govHubInstance = await GovHub.deployed(); + const tokenHub =await TokenHub.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("relayFee", "0x00000000000000000000000000000000000000000000000000038d7ea4c68000", tokenHub.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "relayFee"; + }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "requiredDeposit", - "0x0000000000000000000000000000000000000000000000056bc75e2d63000000", - relayerHub.address - ), - { from: relayerAccount } - ); - - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "requiredDeposit"; + let minimumRelayFee = await tokenHub.relayFee.call(); + assert.equal(minimumRelayFee.toNumber(), 1000000000000000, "value not equal"); }); - let requiredDeposit = await relayerHub.requiredDeposit.call(); - assert.equal(requiredDeposit.toString(), "99999999999998951424", "value not equal"); + it('Gov tendermintLightClient', async () => { + const govHubInstance = await GovHub.deployed(); + const tendermintLightClient =await TendermintLightClient.deployed(); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("dues", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - { from: relayerAccount } - ); + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("rewardForValidatorSetChange", "0x0000000000000000000000000000000000000000000000000000000000010000", TendermintLightClient.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "rewardForValidatorSetChange"; + }); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the dues out of range"; + let rewardForValidatorSetChange = await tendermintLightClient.rewardForValidatorSetChange.call(); + assert.equal(rewardForValidatorSetChange.toNumber(), 65536, "value not equal"); }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("dues", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), - { from: relayerAccount } - ); + it('Gov RelayerHub', async () => { + const govHubInstance = await GovHub.deployed(); + const relayerHub =await RelayerHub.deployed(); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the dues out of range"; - }); + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000000000000000010000", relayerHub.address), + {from: relayerAccount}); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("dues", "0x0000000000000000000000000000000000000000000000016bc75e2d63000000", relayerHub.address), - { from: relayerAccount } - ); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the requiredDeposit out of range"; + }); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "dues"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + {from: relayerAccount}); - let dues = await relayerHub.dues.call(); - assert.equal(dues.toString(), "26213023705160744960", "value not equal"); - }); - - it("Gov relayerIncentivize", async () => { - const govHubInstance = await GovHub.deployed(); - const relayerIncentivize = await RelayerIncentivize.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "headerRelayerRewardRateMolecule", - "0x000000000000000000000000000000000000000000000000000000000000000f", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { - return ev.key === "headerRelayerRewardRateMolecule"; - }); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the requiredDeposit out of range"; + }); - let headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); - assert.equal(headerRelayerRewardRateMolecule.toNumber(), 1, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "headerRelayerRewardRateMolecule", - "0x0000000000000000000000000000000000000000000000000000000000000002", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "headerRelayerRewardRateMolecule"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + {from: relayerAccount}); - headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); - assert.equal(headerRelayerRewardRateMolecule.toNumber(), 2, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "headerRelayerRewardRateDenominator", - "0x0000000000000000000000000000000000000000000000000000000000000001", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { - return ev.key === "headerRelayerRewardRateDenominator"; - }); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the requiredDeposit out of range"; + }); - let headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); - assert.equal(headerRelayerRewardRateDenominator.toNumber(), 5, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "headerRelayerRewardRateDenominator", - "0x0000000000000000000000000000000000000000000000000000000000000004", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "headerRelayerRewardRateDenominator"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("requiredDeposit", "0x0000000000000000000000000000000000000000000000056bc75e2d63000000", relayerHub.address), + {from: relayerAccount}); - headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); - assert.equal(headerRelayerRewardRateDenominator.toNumber(), 4, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "callerCompensationMolecule", - "0x0000000000000000000000000000000000000000000000000000000000000064", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { - return ev.key === "callerCompensationMolecule"; - }); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "requiredDeposit"; + }); - let callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); - assert.equal(callerCompensationMolecule.toNumber(), 1, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "callerCompensationMolecule", - "0x0000000000000000000000000000000000000000000000000000000000000010", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "callerCompensationMolecule"; - }); + let requiredDeposit = await relayerHub.requiredDeposit.call(); + assert.equal(requiredDeposit.toString(), "99999999999998951424", "value not equal"); - callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); - assert.equal(callerCompensationMolecule.toNumber(), 16, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "callerCompensationDenominator", - "0x000000000000000000000000000000000000000000000000000000000000000f", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventNotEmitted(tx, "paramChange", (ev) => { - return ev.key === "callerCompensationDenominator"; - }); - let callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); - assert.equal(callerCompensationDenominator.toNumber(), 80, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "callerCompensationDenominator", - "0x0000000000000000000000000000000000000000000000000000000000000020", - RelayerIncentivize.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "callerCompensationDenominator"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0010000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + {from: relayerAccount}); - callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); - assert.equal(callerCompensationDenominator.toNumber(), 32, "value not equal"); - }); - - it("Gov cross chain contract", async () => { - const govHubInstance = await GovHub.deployed(); - const crossChainInstance = await CrossChain.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "addOrUpdateChannel", - web3.utils.bytesToHex( - Buffer.concat([ - Buffer.from(web3.utils.hexToBytes("0x57")), - Buffer.from(web3.utils.hexToBytes("0x00")), - Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address)), - ]) - ), - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "addOrUpdateChannel"; - }); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the dues out of range"; + }); - await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "addOrUpdateChannel", - web3.utils.bytesToHex( - Buffer.concat([ - Buffer.from(web3.utils.hexToBytes("0x58")), - Buffer.from(web3.utils.hexToBytes("0x00")), - Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address)), - ]) - ), - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "addOrUpdateChannel"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0000000000000000000000000000000000000000000000000000000000000000", relayerHub.address), + {from: relayerAccount}); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "enableOrDisableChannel", - web3.utils.bytesToHex( - Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00"))]) - ), - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "enableOrDisableChannel"; - }); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the dues out of range"; + }); - let isChannelEnable = await crossChainInstance.registeredContractChannelMap.call( - RelayerIncentivize.address, - "0x57" - ); - assert.equal(isChannelEnable, false, "channel should be disabled"); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); - assert.equal(isChannelEnable, true, "channel should be enabled"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "enableOrDisableChannel", - web3.utils.bytesToHex( - Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x01"))]) - ), - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "enableOrDisableChannel"; - }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "enableOrDisableChannel", - web3.utils.bytesToHex( - Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00"))]) - ), - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "enableOrDisableChannel"; - }); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); - assert.equal(isChannelEnable, true, "channel should be enabled"); - isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); - assert.equal(isChannelEnable, false, "channel should be disabled"); - - let appAddr = await crossChainInstance.channelHandlerContractMap.call(0x57); - assert.equal(appAddr, RelayerIncentivize.address, "value not equal"); - let fromSys = await crossChainInstance.isRelayRewardFromSystemReward.call(0x57); - assert.equal(fromSys, true, "should from system reward"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "batchSizeForOracle", - "0x0000000000000000000000000000000000000000000000000000000000000064", - crossChainInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "batchSizeForOracle"; - }); - let batchSizeForOracle = await crossChainInstance.batchSizeForOracle.call(); - assert.equal(batchSizeForOracle, 100, "value not equal"); - }); - - it("Gov SlashIndicator", async () => { - const govHubInstance = await GovHub.deployed(); - const slashIndicator = await SlashIndicator.deployed(); - - const relayerAccount = accounts[8]; - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "felonyThreshold", - "0x0000000000000000000000000000000000000000000000000000000000000100", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "felonyThreshold"; - }); - let felonyThreshold = await slashIndicator.felonyThreshold.call(); - assert.equal(felonyThreshold.toNumber(), 256, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "felonyThreshold", - "0x0000000000000000000000000000000000000000000000000000000000010000", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the felonyThreshold out of range"; - }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("dues", "0x0000000000000000000000000000000000000000000000016bc75e2d63000000", relayerHub.address), + {from: relayerAccount}); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "felonyThreshold", - "0x0000000000000000000000000000000000000000000000000000000000000010", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the felonyThreshold out of range"; - }); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "dues"; + }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "misdemeanorThreshold", - "0x00000000000000000000000000000000000000000000000000000000000000f0", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "misdemeanorThreshold"; - }); - let misdemeanorThreshold = await slashIndicator.misdemeanorThreshold.call(); - assert.equal(misdemeanorThreshold.toNumber(), 240, "value not equal"); - - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "misdemeanorThreshold", - "0x0000000000000000000000000000000000000000000000000000000000000000", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the misdemeanorThreshold out of range"; - }); + let dues = await relayerHub.dues.call(); + assert.equal(dues.toString(), "26213023705160744960", "value not equal"); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "misdemeanorThreshold", - "0x0000000000000000000000000000000000000000000000000000000000010001", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the misdemeanorThreshold out of range"; }); - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "finalitySlashRewardRatio", - "0x0000000000000000000000000000000000000000000000000000000000000032", - slashIndicator.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "finalitySlashRewardRatio"; - }); - let finalitySlashRewardRatio = await slashIndicator.finalitySlashRewardRatio.call(); - assert.equal(finalitySlashRewardRatio.toNumber(), 50, "value not equal"); - }); - - it("Gov SystemReward", async () => { - const govHubInstance = await GovHub.deployed(); - const systemReward = await SystemReward.deployed(); - const validatorSet = await BSCValidatorSet.deployed(); - const slash = await SlashIndicator.deployed(); - const lightClient = await MockLightClient.deployed(); - const tokenHub = await TokenHub.deployed(); - const relayer = await RelayerIncentivize.deployed(); - const relayerHub = await RelayerHub.deployed(); - const govHub = await GovHub.deployed(); - const tokenManager = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); - - await systemReward.updateContractAddr( - validatorSet.address, - slash.address, - systemReward.address, - lightClient.address, - tokenHub.address, - relayer.address, - relayerHub.address, - govHub.address, - tokenManager.address, - crossChain.address - ); - - const relayerAccount = accounts[8]; - let newOperator = web3.eth.accounts.create(); - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("updateOperator", accounts[4], systemReward.address), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "paramChange", (ev) => { - return ev.key === "updateOperator"; - }); + it('Gov relayerIncentivize', async () => { + const govHubInstance = await GovHub.deployed(); + const relayerIncentivize =await RelayerIncentivize.deployed(); - await systemReward.send(1e8, { from: accounts[3] }); - tx = await systemReward.claimRewards(newOperator.address, 1e7, { from: accounts[4] }); - truffleAssert.eventEmitted(tx, "rewardTo", (ev) => { - return ev.amount.toNumber() === 1e7 && ev.to === newOperator.address; - }); + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateMolecule", "0x000000000000000000000000000000000000000000000000000000000000000f", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { + return ev.key === "headerRelayerRewardRateMolecule"; + }); - let balance_wei = await web3.eth.getBalance(newOperator.address); - assert.equal(balance_wei, 1e7, "balance not equal"); - }); - - it("Gov others failed", async () => { - const govHubInstance = await GovHub.deployed(); - const bSCValidatorSetInstance = await BSCValidatorSet.deployed(); - const migrationInstance = await Migration.deployed(); - const relayerAccount = accounts[8]; - - // unknown key - let tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "unknown key", - "0x0000000000000000000000000000000000000000000000000000000000010000", - bSCValidatorSetInstance.address - ), - { from: relayerAccount } - ); - - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "unknown param"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange"); - - // exceed range key - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "expireTimeSecondGap", - "0x000000000000010000000000000000000000000000000000000000000000000", - bSCValidatorSetInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the expireTimeSecondGap is out of range"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange"); - - // length mismatch - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize("expireTimeSecondGap", "0x10000", bSCValidatorSetInstance.address), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "length of expireTimeSecondGap mismatch"; - }); - truffleAssert.eventNotEmitted(tx, "paramChange"); - - // address do not exist - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "expireTimeSecondGap", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x1110000000000000000000000000000000001004" - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { - return ev.message === "the target is not a contract"; - }); + let headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); + assert.equal(headerRelayerRewardRateMolecule.toNumber(), 1, "value not equal"); - // method do no exist - tx = await govHubInstance.handleSynPackage( - GOV_CHANNEL_ID, - serialize( - "expireTimeSecondGap", - "0x0000000000000000000000000000000000000000000000000000000000000000", - migrationInstance.address - ), - { from: relayerAccount } - ); - truffleAssert.eventEmitted(tx, "failReasonWithBytes", (ev) => { - return ev.message === null; + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateMolecule", "0x0000000000000000000000000000000000000000000000000000000000000002", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "headerRelayerRewardRateMolecule"; + }); + + headerRelayerRewardRateMolecule = await relayerIncentivize.headerRelayerRewardRateMolecule.call(); + assert.equal(headerRelayerRewardRateMolecule.toNumber(), 2, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateDenominator", "0x0000000000000000000000000000000000000000000000000000000000000001", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { + return ev.key === "headerRelayerRewardRateDenominator"; + }); + + let headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); + assert.equal(headerRelayerRewardRateDenominator.toNumber(), 5, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("headerRelayerRewardRateDenominator", "0x0000000000000000000000000000000000000000000000000000000000000004", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "headerRelayerRewardRateDenominator"; + }); + + headerRelayerRewardRateDenominator = await relayerIncentivize.headerRelayerRewardRateDenominator.call(); + assert.equal(headerRelayerRewardRateDenominator.toNumber(), 4, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationMolecule", "0x0000000000000000000000000000000000000000000000000000000000000064", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { + return ev.key === "callerCompensationMolecule"; + }); + + let callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); + assert.equal(callerCompensationMolecule.toNumber(), 1, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationMolecule", "0x0000000000000000000000000000000000000000000000000000000000000010", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "callerCompensationMolecule"; + }); + + callerCompensationMolecule = await relayerIncentivize.callerCompensationMolecule.call(); + assert.equal(callerCompensationMolecule.toNumber(), 16, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationDenominator", "0x000000000000000000000000000000000000000000000000000000000000000f", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventNotEmitted(tx, "paramChange",(ev) => { + return ev.key === "callerCompensationDenominator"; + }); + + let callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); + assert.equal(callerCompensationDenominator.toNumber(), 80, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("callerCompensationDenominator", "0x0000000000000000000000000000000000000000000000000000000000000020", RelayerIncentivize.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "callerCompensationDenominator"; + }); + + callerCompensationDenominator = await relayerIncentivize.callerCompensationDenominator.call(); + assert.equal(callerCompensationDenominator.toNumber(), 32, "value not equal"); + }); + + it('Gov cross chain contract', async () => { + const govHubInstance = await GovHub.deployed(); + const crossChainInstance =await CrossChain.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("addOrUpdateChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00")), Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address))])), crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'addOrUpdateChannel'; + }); + + await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("addOrUpdateChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00")), Buffer.from(web3.utils.hexToBytes(RelayerIncentivize.address))])), crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'addOrUpdateChannel'; + }); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x00"))])), crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'enableOrDisableChannel'; + }); + + let isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); + assert.equal(isChannelEnable, false, "channel should be disabled"); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); + assert.equal(isChannelEnable, true, "channel should be enabled"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x57")), Buffer.from(web3.utils.hexToBytes("0x01"))])), crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'enableOrDisableChannel'; + }); + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("enableOrDisableChannel", web3.utils.bytesToHex(Buffer.concat([Buffer.from(web3.utils.hexToBytes("0x58")), Buffer.from(web3.utils.hexToBytes("0x00"))])), crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'enableOrDisableChannel'; + }); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x57"); + assert.equal(isChannelEnable, true, "channel should be enabled"); + isChannelEnable = await crossChainInstance.registeredContractChannelMap.call(RelayerIncentivize.address, "0x58"); + assert.equal(isChannelEnable, false, "channel should be disabled"); + + let appAddr = await crossChainInstance.channelHandlerContractMap.call(0x57); + assert.equal(appAddr, RelayerIncentivize.address, "value not equal"); + let fromSys = await crossChainInstance.isRelayRewardFromSystemReward.call(0x57); + assert.equal(fromSys, true, "should from system reward"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("batchSizeForOracle", "0x0000000000000000000000000000000000000000000000000000000000000064", crossChainInstance.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === 'batchSizeForOracle'; + }); + let batchSizeForOracle = await crossChainInstance.batchSizeForOracle.call(); + assert.equal(batchSizeForOracle, 100, "value not equal"); + }); + + + it('Gov SlashIndicator', async () => { + const govHubInstance = await GovHub.deployed(); + const slashIndicator =await SlashIndicator.deployed(); + + const relayerAccount = accounts[8]; + let tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000000100", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "felonyThreshold"; + }); + let felonyThreshold = await slashIndicator.felonyThreshold.call(); + assert.equal(felonyThreshold.toNumber(), 256, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000010000", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the felonyThreshold out of range"; + }); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("felonyThreshold", "0x0000000000000000000000000000000000000000000000000000000000000010", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the felonyThreshold out of range"; + }); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x00000000000000000000000000000000000000000000000000000000000000f0", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "paramChange",(ev) => { + return ev.key === "misdemeanorThreshold"; + }); + let misdemeanorThreshold = await slashIndicator.misdemeanorThreshold.call(); + assert.equal(misdemeanorThreshold.toNumber(), 240, "value not equal"); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x0000000000000000000000000000000000000000000000000000000000000000", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the misdemeanorThreshold out of range"; + }); + + tx = await govHubInstance.handleSynPackage(GOV_CHANNEL_ID, serialize("misdemeanorThreshold", "0x0000000000000000000000000000000000000000000000000000000000010001", slashIndicator.address), + {from: relayerAccount}); + truffleAssert.eventEmitted(tx, "failReasonWithStr",(ev) => { + return ev.message === "the misdemeanorThreshold out of range"; + }); + + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "finalitySlashRewardRatio", + "0x0000000000000000000000000000000000000000000000000000000000000032", + slashIndicator.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "finalitySlashRewardRatio"; + }); + let finalitySlashRewardRatio = await slashIndicator.finalitySlashRewardRatio.call(); + assert.equal(finalitySlashRewardRatio.toNumber(), 50, "value not equal"); + }); + + it("Gov SystemReward", async () => { + const govHubInstance = await GovHub.deployed(); + const systemReward = await SystemReward.deployed(); + const validatorSet = await BSCValidatorSet.deployed(); + const slash = await SlashIndicator.deployed(); + const lightClient = await MockLightClient.deployed(); + const tokenHub = await TokenHub.deployed(); + const relayer = await RelayerIncentivize.deployed(); + const relayerHub = await RelayerHub.deployed(); + const govHub = await GovHub.deployed(); + const tokenManager = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + + await systemReward.updateContractAddr( + validatorSet.address, + slash.address, + systemReward.address, + lightClient.address, + tokenHub.address, + relayer.address, + relayerHub.address, + govHub.address, + tokenManager.address, + crossChain.address + ); + + const relayerAccount = accounts[8]; + let newOperator = web3.eth.accounts.create(); + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("updateOperator", accounts[4], systemReward.address), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "paramChange", (ev) => { + return ev.key === "updateOperator"; + }); + + await systemReward.send(1e8, { from: accounts[3] }); + tx = await systemReward.claimRewards(newOperator.address, 1e7, { from: accounts[4] }); + truffleAssert.eventEmitted(tx, "rewardTo", (ev) => { + return ev.amount.toNumber() === 1e7 && ev.to === newOperator.address; + }); + + let balance_wei = await web3.eth.getBalance(newOperator.address); + assert.equal(balance_wei, 1e7, "balance not equal"); + }); + + it("Gov others failed", async () => { + const govHubInstance = await GovHub.deployed(); + const bSCValidatorSetInstance = await BSCValidatorSet.deployed(); + const migrationInstance = await Migration.deployed(); + const relayerAccount = accounts[8]; + + // unknown key + let tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "unknown key", + "0x0000000000000000000000000000000000000000000000000000000000010000", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "unknown param"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // exceed range key + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x000000000000010000000000000000000000000000000000000000000000000", + bSCValidatorSetInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the expireTimeSecondGap is out of range"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // length mismatch + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize("expireTimeSecondGap", "0x10000", bSCValidatorSetInstance.address), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "length of expireTimeSecondGap mismatch"; + }); + truffleAssert.eventNotEmitted(tx, "paramChange"); + + // address do not exist + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x1110000000000000000000000000000000001004" + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithStr", (ev) => { + return ev.message === "the target is not a contract"; + }); + + // method do no exist + tx = await govHubInstance.handleSynPackage( + GOV_CHANNEL_ID, + serialize( + "expireTimeSecondGap", + "0x0000000000000000000000000000000000000000000000000000000000000000", + migrationInstance.address + ), + { from: relayerAccount } + ); + truffleAssert.eventEmitted(tx, "failReasonWithBytes", (ev) => { + return ev.message === null; + }); }); - }); }); -function serialize(key, value, target, extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if (extra != null) { - pkg.push(extra); - } - return RLP.encode(pkg); +function serialize(key,value, target,extra) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if(extra != null){ + pkg.push(extra); + } + return RLP.encode(pkg); } diff --git a/test/RelayerHub.js b/test/RelayerHub.js index d8cb88af..a8509d4c 100644 --- a/test/RelayerHub.js +++ b/test/RelayerHub.js @@ -1,79 +1,71 @@ const RelayerHub = artifacts.require("RelayerHub"); const SystemReward = artifacts.require("SystemReward"); -const Web3 = require("web3"); -const truffleAssert = require("truffle-assertions"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const Web3 = require('web3'); +const truffleAssert = require('truffle-assertions'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); -contract("RelayerHub", (accounts) => { - it("register and unregister success", async () => { +contract('RelayerHub', (accounts) => { + it('register and unregister success', async () => { const relayerInstance = await RelayerHub.deployed(); const systemRewardInstance = await SystemReward.deployed(); - let tx = await relayerInstance.register({ from: accounts[3], value: 1e20 }); + let tx =await relayerInstance.register({from: accounts[3],value: 1e20}); truffleAssert.eventEmitted(tx, "relayerRegister"); let res = await relayerInstance.isRelayer.call(accounts[3]); - assert.equal(res, true); + assert.equal(res,true); let balanceBefore = await web3.eth.getBalance(accounts[3]); let systemRewardBefore = await web3.eth.getBalance(systemRewardInstance.address); - tx = await relayerInstance.unregister({ from: accounts[3] }); + tx =await relayerInstance.unregister({from: accounts[3]}); truffleAssert.eventEmitted(tx, "relayerUnRegister"); res = await relayerInstance.isRelayer.call(accounts[3]); - assert.equal(res, false); + assert.equal(res,false); let balanceAfter = await web3.eth.getBalance(accounts[3]); - assert.equal(res, false); + assert.equal(res,false); let deposit = await relayerInstance.requiredDeposit.call(); let dues = await relayerInstance.dues.call(); - assert.equal( - web3.utils - .toBN(balanceAfter) - .sub(web3.utils.toBN(balanceBefore)) - .add(web3.utils.toBN(2e10).mul(web3.utils.toBN(tx.receipt.gasUsed))) - .toString(), - deposit.sub(dues).toString() - ); + assert.equal(web3.utils.toBN(balanceAfter).sub(web3.utils.toBN(balanceBefore)).add(web3.utils.toBN(2e10).mul(web3.utils.toBN(tx.receipt.gasUsed))).toString(), deposit.sub(dues).toString()); let systemRewardAfter = await web3.eth.getBalance(systemRewardInstance.address); - assert.equal( - web3.utils.toBN(systemRewardAfter).sub(web3.utils.toBN(systemRewardBefore)).toString(), - web3.utils.toBN(1e17).toString() - ); + assert.equal(web3.utils.toBN(systemRewardAfter).sub(web3.utils.toBN(systemRewardBefore)).toString(), web3.utils.toBN(1e17).toString()) }); - it("fail to register", async () => { + it('fail to register', async () => { const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: accounts[3], value: 1e20 }); - // re-register + await relayerInstance.register({from: accounts[3],value: 1e20}); + // reregister try { - await relayerInstance.register({ from: accounts[3], value: 1e20 }); + await relayerInstance.register({from: accounts[3],value: 1e20}); assert.fail(); } catch (error) { assert.ok(error.toString().includes("relayer already exist")); } - await relayerInstance.unregister({ from: accounts[3] }); + await relayerInstance.unregister({from: accounts[3]}); try { - await relayerInstance.unregister({ from: accounts[3] }); + await relayerInstance.unregister({from: accounts[3]}); assert.fail(); } catch (error) { assert.ok(error.toString().includes("relayer do not exist")); } try { - await relayerInstance.register({ from: accounts[4], value: 2e20 }); + await relayerInstance.register({from: accounts[4],value: 2e20}); assert.fail(); } catch (error) { assert.ok(error.toString().includes("deposit value is not exactly the same")); } try { - await relayerInstance.register({ from: accounts[4], value: 1e10 }); + await relayerInstance.register({from: accounts[4],value: 1e10}); assert.fail(); } catch (error) { assert.ok(error.toString().includes("deposit value is not exactly the same")); } + }); }); + diff --git a/test/Slash.js b/test/Slash.js index 007ae149..ade40d71 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -1,15 +1,15 @@ const SlashIndicator = artifacts.require("SlashIndicator"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); -const Web3 = require("web3"); -const crypto = require("crypto"); -const RLP = require("rlp"); +const Web3 = require('web3'); +const crypto = require('crypto'); +const RLP = require('rlp'); const SystemReward = artifacts.require("SystemReward"); -const truffleAssert = require("truffle-assertions"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const truffleAssert = require('truffle-assertions'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); const STAKE_CHANNEL_ID = 0x08; -contract("SlashIndicator", (accounts) => { - it("slash success", async () => { +contract('SlashIndicator', (accounts) => { + it('slash success', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); @@ -18,15 +18,15 @@ contract("SlashIndicator", (accounts) => { let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; let validatorAccount = validatorAccounts[0]; - for (let i = 1; i < 10; i++) { + for (let i =1; i<10; i++){ await slashInstance.slash(validatorAccount, { from: accountOne }); - let res = await slashInstance.getSlashIndicator.call(validatorAccount); - let count = res[1].toNumber(); + let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); + let count =res[1].toNumber(); assert.equal(count, i, "slash num is not correct"); } }); - it("slash from no system account", async () => { + it('slash from no system account', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); @@ -34,20 +34,17 @@ contract("SlashIndicator", (accounts) => { let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; let validatorAccount = validatorAccounts[0]; // first slash - try { + try{ await slashInstance.slash(validatorAccount, { from: nonSystemAccount }); assert.fail(); - } catch (error) { - assert.ok( - error.toString().includes("the message sender must be the block producer"), - "slash from no system account should not be ok" - ); + }catch (error) { + assert.ok(error.toString().includes("the message sender must be the block producer"), "slash from no system account should not be ok"); } }); }); -contract("SlashIndicator: isOperator works", (accounts) => { - it("isOperator works", async () => { +contract('SlashIndicator: isOperator works', (accounts) => { + it('isOperator works', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorInstance = await BSCValidatorSet.deployed(); @@ -56,34 +53,36 @@ contract("SlashIndicator: isOperator works", (accounts) => { let validatorAccount = validatorAccounts[0]; // slash afterward - for (let i = 1; i < 10; i++) { + for (let i =1; i<10; i++){ await slashInstance.slash(validatorAccount, { from: accountOne }); - let res = await slashInstance.getSlashIndicator.call(validatorAccount); - let count = res[1].toNumber(); + let res= (await slashInstance.getSlashIndicator.call(validatorAccount)); + let count =res[1].toNumber(); assert.equal(count, i, "slash num is not correct for validator"); } }); }); -contract("SlashIndicator: catch emit event", (accounts) => { - it("catch emit event", async () => { - const slashInstance = await SlashIndicator.deployed(); - const validatorInstance = await BSCValidatorSet.deployed(); - const accountOne = accounts[0]; - let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; - let validatorAccount = validatorAccounts[0]; - for (let i = 1; i < 50; i++) { - let tx = await slashInstance.slash(validatorAccount, { from: accountOne }); - truffleAssert.eventEmitted(tx, "validatorSlashed", (ev) => { - return ev.validator === validatorAccount; - }); - } - }); +contract('SlashIndicator: catch emit event', (accounts) => { + it('catch emit event', async () => { + const slashInstance = await SlashIndicator.deployed(); + const validatorInstance = await BSCValidatorSet.deployed(); + + const accountOne = accounts[0]; + let validatorAccounts = (await validatorInstance.getMiningValidators.call())["0"]; + let validatorAccount = validatorAccounts[0]; + for (let i =1; i<50; i++){ + let tx = await slashInstance.slash(validatorAccount, { from: accountOne }); + truffleAssert.eventEmitted(tx, "validatorSlashed",(ev) => { + return ev.validator === validatorAccount; + }); + } + }); }); -contract("SlashIndicator", (accounts) => { - it("trigger misdemeanor", async () => { + +contract('SlashIndicator', (accounts) => { + it('trigger misdemeanor', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); const systemRewardInstance = await SystemReward.deployed(); @@ -93,72 +92,71 @@ contract("SlashIndicator", (accounts) => { let secondValidator = accounts[1]; let thirdValidator = accounts[2]; - await validatorSetInstance.deposit(validator, { from: systemAccount, value: 1e18 }); - await systemRewardInstance.addOperator(validatorSetInstance.address, { from: systemAccount }); + await validatorSetInstance.deposit(validator, {from: systemAccount, value: 1e18 }); + await systemRewardInstance.addOperator(validatorSetInstance.address, {from: systemAccount}); let amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) - for (let i = 1; i <= 50; i++) { + for (let i =1; i<=50; i++){ await slashInstance.slash(validator, { from: systemAccount }); } amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(), 0); + assert.equal(amount.toNumber(),0); - let packageBytes = validatorUpdateRlpEncode( - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator] - ); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); + let packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], + [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); - await validatorSetInstance.deposit(validator, { from: systemAccount, value: 2e18 }); + await validatorSetInstance.deposit(validator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); - for (let i = 1; i <= 4; i++) { + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + for (let i =1; i<=4; i++){ await slashInstance.slash(validator, { from: systemAccount }); } - let res = await slashInstance.getSlashIndicator.call(validator); - assert.equal(res[1].toNumber(), 50); + let res= (await slashInstance.getSlashIndicator.call(validator)); + assert.equal(res[1].toNumber(),50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(), 0); + assert.equal(amount.toNumber(),0); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) + - await validatorSetInstance.deposit(secondValidator, { from: systemAccount, value: 1e18 }); + await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 1e18 }); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); - for (let i = 1; i <= 50; i++) { + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) + for (let i =1; i<=50; i++){ await slashInstance.slash(secondValidator, { from: systemAccount }); } - res = await slashInstance.getSlashIndicator.call(secondValidator); - assert.equal(res[1].toNumber(), 50); + res= (await slashInstance.getSlashIndicator.call(secondValidator)); + assert.equal(res[1].toNumber(),50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toNumber(), 0); + assert.equal(amount.toNumber(),0); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) - for (let i = 1; i <= 50; i++) { + for (let i =1; i<=50; i++){ await slashInstance.slash(thirdValidator, { from: systemAccount }); } - res = await slashInstance.getSlashIndicator.call(thirdValidator); - assert.equal(res[1].toNumber(), 50); + res= (await slashInstance.getSlashIndicator.call(thirdValidator)); + assert.equal(res[1].toNumber(),50); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString()) amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString()); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString()) amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toNumber(), 0); + assert.equal(amount.toNumber(),0); + }); }); -contract("felony SlashIndicator", (accounts) => { - it("trigger felony ", async () => { +contract('felony SlashIndicator', (accounts) => { + it('trigger felony ', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); @@ -167,91 +165,83 @@ contract("felony SlashIndicator", (accounts) => { let secondValidator = accounts[1]; let thirdValidator = accounts[2]; - let packageBytes = validatorUpdateRlpEncode( - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator] - ); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); + let packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], + [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); - await validatorSetInstance.deposit(validator, { from: systemAccount, value: 2e18 }); + await validatorSetInstance.deposit(validator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case1: incoming of account1 is wrong"); - for (let i = 1; i <= 150; i++) { + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case1: incoming of account1 is wrong") + for (let i =1; i<=150; i++){ await slashInstance.slash(validator, { from: systemAccount }); } - let res = await slashInstance.getSlashIndicator.call(validator); - assert.equal(res[1].toNumber(), 0, "case1: slash indicator of account1 is wrong"); + let res= (await slashInstance.getSlashIndicator.call(validator)); + assert.equal(res[1].toNumber(),0, "case1: slash indicator of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toNumber(), 0, "case1: incoming of account1 is wrong"); + assert.equal(amount.toNumber(),0, "case1: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case1: incoming of account2 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case1: incoming of account3 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case1: incoming of account3 is wrong"); let consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length, 2, "case1: length of validators should be 2"); - assert.equal(consensusAddress[0], secondValidator, "case1: index 0 of validators should be account2"); - assert.equal(consensusAddress[1], thirdValidator, "case1: index 1 of validators should be account3"); - - packageBytes = validatorUpdateRlpEncode( - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator] - ); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); - - await validatorSetInstance.deposit(secondValidator, { from: systemAccount, value: 2e18 }); + assert.equal(consensusAddress.length,2, "case1: length of validators should be 2"); + assert.equal(consensusAddress[0],secondValidator, "case1: index 0 of validators should be account2"); + assert.equal(consensusAddress[1],thirdValidator, "case1: index 1 of validators should be account3"); + + packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], + [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); + + await validatorSetInstance.deposit(secondValidator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case2: incoming of account2 is wrong"); - for (let i = 1; i <= 150; i++) { + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case2: incoming of account2 is wrong") + for (let i =1; i<=150; i++){ await slashInstance.slash(secondValidator, { from: systemAccount }); } - res = await slashInstance.getSlashIndicator.call(secondValidator); - assert.equal(res[1].toNumber(), 0, "case2: slash indicator of account2 is wrong"); + res= (await slashInstance.getSlashIndicator.call(secondValidator)); + assert.equal(res[1].toNumber(),0, "case2: slash indicator of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toNumber(), 0, "case2: incoming of account2 is wrong"); + assert.equal(amount.toNumber(),0, "case2: incoming of account2 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case2: incoming of account1 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case2: incoming of account3 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case2: incoming of account3 is wrong"); consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length, 2, "case2: length of validators should be 2"); - assert.equal(consensusAddress[0], validator, "case2: index 0 of validators should be account1"); - assert.equal(consensusAddress[1], thirdValidator, "case2: index 1 of validators should be account3"); - - packageBytes = validatorUpdateRlpEncode( - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator], - [validator, secondValidator, thirdValidator] - ); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: accounts[8] }); - - await validatorSetInstance.deposit(thirdValidator, { from: systemAccount, value: 2e18 }); + assert.equal(consensusAddress.length,2, "case2: length of validators should be 2"); + assert.equal(consensusAddress[0],validator, "case2: index 0 of validators should be account1"); + assert.equal(consensusAddress[1],thirdValidator, "case2: index 1 of validators should be account3"); + + packageBytes = validatorUpdateRlpEncode([validator,secondValidator,thirdValidator], + [validator,secondValidator,thirdValidator],[validator,secondValidator,thirdValidator]); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: accounts[8]}); + + await validatorSetInstance.deposit(thirdValidator, {from: systemAccount, value: 2e18 }); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toString(), web3.utils.toBN(2e18).toString(), "case3: incoming of account3 is wrong"); - for (let i = 1; i <= 150; i++) { + assert.equal(amount.toString(),web3.utils.toBN(2e18).toString(), "case3: incoming of account3 is wrong") + for (let i =1; i<=150; i++){ await slashInstance.slash(thirdValidator, { from: systemAccount }); } - res = await slashInstance.getSlashIndicator.call(thirdValidator); - assert.equal(res[1].toNumber(), 0, "case3: slash indicator of account3 is wrong"); + res= (await slashInstance.getSlashIndicator.call(thirdValidator)); + assert.equal(res[1].toNumber(),0, "case3: slash indicator of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(thirdValidator); - assert.equal(amount.toNumber(), 0, "case3: incoming of account3 is wrong"); + assert.equal(amount.toNumber(),0, "case3: incoming of account3 is wrong"); amount = await validatorSetInstance.getIncoming.call(validator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case3: incoming of account1 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account1 is wrong"); amount = await validatorSetInstance.getIncoming.call(secondValidator); - assert.equal(amount.toString(), web3.utils.toBN(1e18).toString(), "case3: incoming of account2 is wrong"); + assert.equal(amount.toString(),web3.utils.toBN(1e18).toString(), "case3: incoming of account2 is wrong"); consensusAddress = await validatorSetInstance.getValidators.call(); - assert.equal(consensusAddress.length, 2, "case3: length of validators should be 2"); - assert.equal(consensusAddress[0], validator, "case3: index 0 of validators should be account1"); - assert.equal(consensusAddress[1], secondValidator, "case3: index 0 of validators should be account2"); + assert.equal(consensusAddress.length,2, "case3: length of validators should be 2"); + assert.equal(consensusAddress[0],validator, "case3: index 0 of validators should be account1"); + assert.equal(consensusAddress[1],secondValidator, "case3: index 0 of validators should be account2"); + }); }); -contract("Clean SlashIndicator", (accounts) => { - it("test slash clean", async () => { +contract('Clean SlashIndicator', (accounts) => { + it('test slash clean', async () => { const slashInstance = await SlashIndicator.deployed(); const validatorSetInstance = await BSCValidatorSet.deployed(); let newValidator = web3.eth.accounts.create(); @@ -260,85 +250,86 @@ contract("Clean SlashIndicator", (accounts) => { // case 1: all clean. let validators = []; - for (let i = 0; i < 20; i++) { + for(let i =0;i <20; i++){ validators.push(web3.eth.accounts.create().address); } // Do init - let packageBytes = validatorUpdateRlpEncode(validators, validators, validators); - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); + let packageBytes = validatorUpdateRlpEncode(validators, + validators,validators); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - for (let i = 0; i < 20; i++) { + for(let i =0;i <20;i++){ await slashInstance.slash(validators[i], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); - let res = await slashInstance.getSlashValidators.call(); + let res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 0); - for (let i = 0; i < 20; i++) { + for(let i =0;i <20;i++){ let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count = res[1].toNumber(); + let count =res[1].toNumber(); let height = res[0].toNumber(); assert.equal(count, 0); assert.equal(height, 0); } // case 2: all stay. - for (let i = 0; i < 20; i++) { - for (let j = 0; j < 5; j++) { + for(let i =0;i <20;i++){ + for(let j=0;j<5;j++){ await slashInstance.slash(validators[i], { from: accountOne }); } } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); - res = await slashInstance.getSlashValidators.call(); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 20); - for (let i = 0; i < 20; i++) { + for(let i =0;i <20;i++){ let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count = res[1].toNumber(); + let count =res[1].toNumber(); assert.equal(count, 1); } // case 3: partial stay. - for (let i = 0; i < 10; i++) { - for (let j = 0; j < 5; j++) { - await slashInstance.slash(validators[2 * i], { from: accountOne }); + for(let i =0;i <10;i++){ + for(let j=0;j<5;j++){ + await slashInstance.slash(validators[2*i], { from: accountOne }); } - await slashInstance.slash(validators[2 * i + 1], { from: accountOne }); + await slashInstance.slash(validators[2*i+1], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); - res = await slashInstance.getSlashValidators.call(); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 10); - for (let i = 0; i < 20; i++) { + for(let i =0;i <20;i++){ let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count = res[1].toNumber(); - if (i % 2 == 0) { + let count =res[1].toNumber(); + if(i%2==0){ assert.equal(count, 2); - } else { + }else{ assert.equal(count, 0); } } // case 4: partial stay. - for (let i = 0; i < 10; i++) { - for (let j = 0; j < 5; j++) { - await slashInstance.slash(validators[2 * i + 1], { from: accountOne }); + for(let i =0;i <10;i++){ + for(let j=0;j<5;j++){ + await slashInstance.slash(validators[2*i+1], { from: accountOne }); } - await slashInstance.slash(validators[2 * i], { from: accountOne }); + await slashInstance.slash(validators[2*i], { from: accountOne }); } // doclean - await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { from: relayerAccount }); - res = await slashInstance.getSlashValidators.call(); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID,packageBytes,{from: relayerAccount}); + res= (await slashInstance.getSlashValidators.call()); assert.equal(res.length, 10); - for (let i = 0; i < 20; i++) { + for(let i =0;i <20;i++){ let res = await slashInstance.getSlashIndicator.call(validators[i]); - let count = res[1].toNumber(); - if (i % 2 == 0) { + let count =res[1].toNumber(); + if(i%2==0){ assert.equal(count, 0); - } else { + }else{ assert.equal(count, 1); } } @@ -530,12 +521,12 @@ contract("finality slash SlashIndicator", (accounts) => { }); }); -function validatorUpdateRlpEncode(consensusAddrList, feeAddrList, bscFeeAddrList) { +function validatorUpdateRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) { let pkg = []; pkg.push(0x00); let n = consensusAddrList.length; let vals = []; - for (let i = 0; i < n; i++) { + for(let i = 0;i { - it("receive token success", async () => { +contract('SystemReward', (accounts) => { + it('receive token success', async () => { const systemRewardInstance = await SystemReward.deployed(); - let tx = await systemRewardInstance.send(1e8, { from: accounts[3] }); + let tx = await systemRewardInstance.send(1e8, {from: accounts[3]}); let balance_wei = await web3.eth.getBalance(systemRewardInstance.address); assert.equal(balance_wei, 1e8, "balance not equal"); - truffleAssert.eventEmitted(tx, "receiveDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "receiveDeposit",(ev) => { return ev.amount.toNumber() === 1e8 && ev.from === accounts[3]; }); }); - it("isOperator works", async () => { + it('isOperator works', async () => { const systemRewardInstance = await SystemReward.deployed(); let res = await systemRewardInstance.isOperator.call(accounts[0]); assert.ok(res, "accounts[0] should be operator"); @@ -28,16 +28,15 @@ contract("SystemReward", (accounts) => { assert.ok(!res, "accounts[4] should not be operator"); }); - it("claim reward success", async () => { + + it('claim reward success', async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); - await systemRewardInstance.send(1e8, { from: accounts[3] }); - let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, { - from: accounts[0], - }); + await systemRewardInstance.send(1e8, {from: accounts[3]}); + let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, {from: accounts[0]}) - truffleAssert.eventEmitted(tx, "rewardTo", (ev) => { + truffleAssert.eventEmitted(tx, "rewardTo",(ev) => { return ev.amount.toNumber() === 1e7 && ev.to === newAccount.address; }); @@ -45,7 +44,7 @@ contract("SystemReward", (accounts) => { assert.equal(balance_wei, 1e7, "balance not equal"); }); - it("claim reward failed", async () => { + it('claim reward failed', async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); @@ -57,13 +56,12 @@ contract("SystemReward", (accounts) => { }); }); -contract("SystemReward", (accounts) => { - it("claim empty reward", async () => { +contract('SystemReward', (accounts) => { + + it('claim empty reward', async () => { const systemRewardInstance = await SystemReward.deployed(); let newAccount = web3.eth.accounts.create(); - let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, { - from: accounts[0], - }); + let tx = await systemRewardInstance.claimRewards(newAccount.address, 1e7, {from: accounts[0]}) truffleAssert.eventEmitted(tx, "rewardEmpty"); let balance_wei = await web3.eth.getBalance(newAccount.address); assert.equal(balance_wei, 0, "balance not equal"); diff --git a/test/TestRelayerIncentivize.js b/test/TestRelayerIncentivize.js index efc80661..426d787d 100644 --- a/test/TestRelayerIncentivize.js +++ b/test/TestRelayerIncentivize.js @@ -5,468 +5,360 @@ const MockLightClient = artifacts.require("mock/MockLightClient"); const TokenHub = artifacts.require("TokenHub"); const TokenManager = artifacts.require("TokenManager"); const CrossChain = artifacts.require("CrossChain"); +const ABCToken = artifacts.require("ABCToken"); +const DEFToken = artifacts.require("DEFToken"); +const XYZToken = artifacts.require("test/XYZToken"); +const MiniToken = artifacts.require("test/MiniToken"); +const MaliciousToken = artifacts.require("test/MaliciousToken"); const RelayerHub = artifacts.require("RelayerHub"); const GovHub = artifacts.require("GovHub"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); const SlashIndicator = artifacts.require("SlashIndicator"); -const Web3 = require("web3"); -const RLP = require("rlp"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const Web3 = require('web3'); +const RLP = require('rlp'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); const GOV_CHANNEL_ID = 0x09; const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; -function serialize(key, value, target, extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if (extra != null) { - pkg.push(extra); - } - return RLP.encode(pkg); +function serialize(key,value, target,extra) { + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if(extra != null){ + pkg.push(extra); + } + return RLP.encode(pkg); } function toBytes32String(input) { - let initialInputHexStr = web3.utils.toBN(input).toString(16); - const initialInputHexStrLength = initialInputHexStr.length; - - let inputHexStr = initialInputHexStr; - for (let i = 0; i < 64 - initialInputHexStrLength; i++) { - inputHexStr = "0" + inputHexStr; - } - return inputHexStr; + let initialInputHexStr = web3.utils.toBN(input).toString(16); + const initialInputHexStrLength = initialInputHexStr.length; + + let inputHexStr = initialInputHexStr; + for (var i = 0; i < 64 - initialInputHexStrLength; i++) { + inputHexStr = '0' + inputHexStr; + } + return inputHexStr; } function buildSyncPackagePrefix(syncRelayFee) { - return Buffer.from(web3.utils.hexToBytes("0x00" + toBytes32String(syncRelayFee))); + return Buffer.from(web3.utils.hexToBytes( + "0x00" + toBytes32String(syncRelayFee) + )); } -contract("RelayerIncentivize", (accounts) => { - it("init incentivize", async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const systemReward = await SystemReward.deployed(); - - const systemRewardContract = await relayerIncentivize.SYSTEM_REWARD_ADDR.call(); - assert.equal(systemRewardContract, systemReward.address, "wrong system reward contract address"); - }); - it("header relayer incentivize", async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - - const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); - const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); - const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); - const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); - const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); - const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); - const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); - const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const roundSize = await relayerIncentivize.ROUND_SIZE.call(); - assert.equal(roundSize.toNumber(), 30, "wrong round size"); - const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); - assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); - - for (let i = 0; i < 1; i++) { - await relayerIncentivize.addReward(accounts[1], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 2; i++) { - await relayerIncentivize.addReward(accounts[2], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 3; i++) { - await relayerIncentivize.addReward(accounts[3], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 4; i++) { - await relayerIncentivize.addReward(accounts[4], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 5; i++) { - await relayerIncentivize.addReward(accounts[5], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 6; i++) { - await relayerIncentivize.addReward(accounts[6], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 7; i++) { - await relayerIncentivize.addReward(accounts[7], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } - for (let i = 0; i < 2; i++) { - await relayerIncentivize.addReward(accounts[8], accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } +contract('RelayerIncentivize', (accounts) => { + it('init incentivize', async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const systemReward = await SystemReward.deployed(); + let uselessAddr = web3.eth.accounts.create().address; - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 1, "wrong round sequence"); - - await relayerIncentivize.claimRelayerReward(accounts[1], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[2], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[3], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[4], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[5], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[6], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[7], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[8], { from: accounts[0] }); - - const newAccount1Balance = await web3.eth.getBalance(accounts[1]); - const newAccount2Balance = await web3.eth.getBalance(accounts[2]); - const newAccount3Balance = await web3.eth.getBalance(accounts[3]); - const newAccount4Balance = await web3.eth.getBalance(accounts[4]); - const newAccount5Balance = await web3.eth.getBalance(accounts[5]); - const newAccount6Balance = await web3.eth.getBalance(accounts[6]); - const newAccount7Balance = await web3.eth.getBalance(accounts[7]); - const newAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const rewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)); - const rewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)); - const rewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)); - const rewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)); - const rewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)); - const rewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)); - const rewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)); - const rewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)); - - assert.equal(rewardAccount1.lt(rewardAccount2), true, "wrong reward"); - assert.equal(rewardAccount2.lt(rewardAccount3), true, "wrong reward"); - assert.equal(rewardAccount3.eq(rewardAccount4), true, "wrong reward"); - assert.equal(rewardAccount4.eq(rewardAccount5), true, "wrong reward"); - assert.equal(rewardAccount5.eq(rewardAccount6), true, "wrong reward"); - assert.equal(rewardAccount6.eq(rewardAccount7), true, "wrong reward"); - assert.equal(rewardAccount8.eq(rewardAccount2), true, "wrong reward"); - }); - it("transfer relayer Incentivize", async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - - const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); - const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); - const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); - const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); - const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); - const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); - const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); - const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const gasPriceStr = await web3.eth.getGasPrice(); - const gasPrice = web3.utils.toBN(gasPriceStr); - - let account1TxFee = web3.utils.toBN(0); - let account2TxFee = web3.utils.toBN(0); - let account3TxFee = web3.utils.toBN(0); - let account4TxFee = web3.utils.toBN(0); - let account5TxFee = web3.utils.toBN(0); - let account6TxFee = web3.utils.toBN(0); - let account7TxFee = web3.utils.toBN(0); - let account8TxFee = web3.utils.toBN(0); - - const tokenHub = accounts[9]; - - for (let i = 0; i < 1; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[1], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account1TxFee = account1TxFee.add(txFee); - } - for (let i = 0; i < 2; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[2], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account2TxFee = account2TxFee.add(txFee); - } - for (let i = 0; i < 3; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[3], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account3TxFee = account3TxFee.add(txFee); - } - for (let i = 0; i < 4; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[4], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account4TxFee = account4TxFee.add(txFee); - } - for (let i = 0; i < 5; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[5], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account5TxFee = account5TxFee.add(txFee); - } - for (let i = 0; i < 6; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[6], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account6TxFee = account6TxFee.add(txFee); - } - for (let i = 0; i < 7; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[7], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account7TxFee = account7TxFee.add(txFee); - } - for (let i = 0; i < 2; i++) { - let tx = await relayerIncentivize.addReward(accounts[0], accounts[8], web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); - account8TxFee = account8TxFee.add(txFee); - } - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 2, "wrong round sequence"); - - await relayerIncentivize.claimRelayerReward(accounts[1], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[2], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[3], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[4], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[5], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[6], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[7], { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(accounts[8], { from: accounts[0] }); - - const newAccount1Balance = await web3.eth.getBalance(accounts[1]); - const newAccount2Balance = await web3.eth.getBalance(accounts[2]); - const newAccount3Balance = await web3.eth.getBalance(accounts[3]); - const newAccount4Balance = await web3.eth.getBalance(accounts[4]); - const newAccount5Balance = await web3.eth.getBalance(accounts[5]); - const newAccount6Balance = await web3.eth.getBalance(accounts[6]); - const newAccount7Balance = await web3.eth.getBalance(accounts[7]); - const newAccount8Balance = await web3.eth.getBalance(accounts[8]); - - const pureRewardAccount1 = web3.utils - .toBN(newAccount1Balance) - .sub(web3.utils.toBN(initialAccount1Balance)) - .sub(account1TxFee); - const pureRewardAccount2 = web3.utils - .toBN(newAccount2Balance) - .sub(web3.utils.toBN(initialAccount2Balance)) - .sub(account2TxFee); - const pureRewardAccount3 = web3.utils - .toBN(newAccount3Balance) - .sub(web3.utils.toBN(initialAccount3Balance)) - .sub(account3TxFee); - const pureRewardAccount4 = web3.utils - .toBN(newAccount4Balance) - .sub(web3.utils.toBN(initialAccount4Balance)) - .sub(account4TxFee); - const pureRewardAccount5 = web3.utils - .toBN(newAccount5Balance) - .sub(web3.utils.toBN(initialAccount5Balance)) - .sub(account5TxFee); - const pureRewardAccount6 = web3.utils - .toBN(newAccount6Balance) - .sub(web3.utils.toBN(initialAccount6Balance)) - .sub(account6TxFee); - const pureRewardAccount7 = web3.utils - .toBN(newAccount7Balance) - .sub(web3.utils.toBN(initialAccount7Balance)) - .sub(account7TxFee); - const pureRewardAccount8 = web3.utils - .toBN(newAccount8Balance) - .sub(web3.utils.toBN(initialAccount8Balance)) - .sub(account8TxFee); - - assert.equal(pureRewardAccount1.lt(pureRewardAccount2), true, "wrong reward"); - assert.equal(pureRewardAccount2.lt(pureRewardAccount3), true, "wrong reward"); - assert.equal(pureRewardAccount3.gt(pureRewardAccount4), true, "wrong reward"); - assert.equal(pureRewardAccount4.gt(pureRewardAccount5), true, "wrong reward"); - assert.equal(pureRewardAccount5.gt(pureRewardAccount6), true, "wrong reward"); - assert.equal(pureRewardAccount6.gt(pureRewardAccount7), true, "wrong reward"); - assert.equal(pureRewardAccount8.gt(pureRewardAccount2), true, "wrong reward"); // get extra 1/80 of total reward - assert.equal(pureRewardAccount8.lt(pureRewardAccount3), true, "wrong reward"); // get extra 1/80 of total reward - }); - it("non-payable address", async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const tendermintLightClient = await TendermintLightClient.deployed(); - - const tokenHub = accounts[9]; - const relayer = accounts[0]; - - for (let i = 0; i < 15; i++) { - await relayerIncentivize.addReward(tendermintLightClient.address, relayer, web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - } + const systemRewardContract = await relayerIncentivize.SYSTEM_REWARD_ADDR.call(); + assert.equal(systemRewardContract, systemReward.address, "wrong system reward contract address"); + }); + it('header relayer incentivize', async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + + const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); + const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); + const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); + const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); + const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); + const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); + const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); + const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const roundSize = await relayerIncentivize.ROUND_SIZE.call(); + assert.equal(roundSize.toNumber(), 30, "wrong round size"); + const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); + assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); + + for(let i=0; i<1; i++){ + await relayerIncentivize.addReward(accounts[1], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<2; i++){ + await relayerIncentivize.addReward(accounts[2], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<3; i++){ + await relayerIncentivize.addReward(accounts[3], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<4; i++){ + await relayerIncentivize.addReward(accounts[4], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<5; i++){ + await relayerIncentivize.addReward(accounts[5], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<6; i++){ + await relayerIncentivize.addReward(accounts[6], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<7; i++){ + await relayerIncentivize.addReward(accounts[7], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + for(let i=0; i<2; i++){ + await relayerIncentivize.addReward(accounts[8], accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 1, "wrong round sequence"); + + await relayerIncentivize.claimRelayerReward(accounts[1], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[2], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[3], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[4], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[5], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[6], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[7], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[8], {from: accounts[0]}); + + const newAccount1Balance = await web3.eth.getBalance(accounts[1]); + const newAccount2Balance = await web3.eth.getBalance(accounts[2]); + const newAccount3Balance = await web3.eth.getBalance(accounts[3]); + const newAccount4Balance = await web3.eth.getBalance(accounts[4]); + const newAccount5Balance = await web3.eth.getBalance(accounts[5]); + const newAccount6Balance = await web3.eth.getBalance(accounts[6]); + const newAccount7Balance = await web3.eth.getBalance(accounts[7]); + const newAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const rewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)); + const rewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)); + const rewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)); + const rewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)); + const rewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)); + const rewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)); + const rewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)); + const rewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)); + + assert.equal(rewardAccount1.lt(rewardAccount2), true, "wrong reward"); + assert.equal(rewardAccount2.lt(rewardAccount3), true, "wrong reward"); + assert.equal(rewardAccount3.eq(rewardAccount4), true, "wrong reward"); + assert.equal(rewardAccount4.eq(rewardAccount5), true, "wrong reward"); + assert.equal(rewardAccount5.eq(rewardAccount6), true, "wrong reward"); + assert.equal(rewardAccount6.eq(rewardAccount7), true, "wrong reward"); + assert.equal(rewardAccount8.eq(rewardAccount2), true, "wrong reward"); - for (let i = 0; i < 14; i++) { - await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), false, { - from: tokenHub, - }); - } + }); + it('transfer relayer Incentivize', async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + + const initialAccount1Balance = await web3.eth.getBalance(accounts[1]); + const initialAccount2Balance = await web3.eth.getBalance(accounts[2]); + const initialAccount3Balance = await web3.eth.getBalance(accounts[3]); + const initialAccount4Balance = await web3.eth.getBalance(accounts[4]); + const initialAccount5Balance = await web3.eth.getBalance(accounts[5]); + const initialAccount6Balance = await web3.eth.getBalance(accounts[6]); + const initialAccount7Balance = await web3.eth.getBalance(accounts[7]); + const initialAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const gasPriceStr = await web3.eth.getGasPrice(); + const gasPrice = web3.utils.toBN(gasPriceStr); + + let account1TxFee = web3.utils.toBN(0); + let account2TxFee = web3.utils.toBN(0); + let account3TxFee = web3.utils.toBN(0); + let account4TxFee = web3.utils.toBN(0); + let account5TxFee = web3.utils.toBN(0); + let account6TxFee = web3.utils.toBN(0); + let account7TxFee = web3.utils.toBN(0); + let account8TxFee = web3.utils.toBN(0); + + const tokenHub = accounts[9]; + + for(let i=0; i<1; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[1], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account1TxFee = account1TxFee.add(txFee) + } + for(let i=0; i<2; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[2], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account2TxFee = account2TxFee.add(txFee) + } + for(let i=0; i<3; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[3], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account3TxFee = account3TxFee.add(txFee) + } + for(let i=0; i<4; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[4], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account4TxFee = account4TxFee.add(txFee) + } + for(let i=0; i<5; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[5], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account5TxFee = account5TxFee.add(txFee) + } + for(let i=0; i<6; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[6], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account6TxFee = account6TxFee.add(txFee) + } + for(let i=0; i<7; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[7], web3.utils.toBN(1e16), false,{from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account7TxFee = account7TxFee.add(txFee) + } + for(let i=0; i<2; i++){ + let tx = await relayerIncentivize.addReward(accounts[0], accounts[8], web3.utils.toBN(1e16), false, {from: tokenHub}); + const txFee = web3.utils.toBN(tx.receipt.gasUsed).mul(gasPrice); + account8TxFee = account8TxFee.add(txFee) + } + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 2, "wrong round sequence"); + + await relayerIncentivize.claimRelayerReward(accounts[1], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[2], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[3], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[4], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[5], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[6], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[7], {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(accounts[8], {from: accounts[0]}); + + const newAccount1Balance = await web3.eth.getBalance(accounts[1]); + const newAccount2Balance = await web3.eth.getBalance(accounts[2]); + const newAccount3Balance = await web3.eth.getBalance(accounts[3]); + const newAccount4Balance = await web3.eth.getBalance(accounts[4]); + const newAccount5Balance = await web3.eth.getBalance(accounts[5]); + const newAccount6Balance = await web3.eth.getBalance(accounts[6]); + const newAccount7Balance = await web3.eth.getBalance(accounts[7]); + const newAccount8Balance = await web3.eth.getBalance(accounts[8]); + + const pureRewardAccount1 = web3.utils.toBN(newAccount1Balance).sub(web3.utils.toBN(initialAccount1Balance)).sub(account1TxFee); + const pureRewardAccount2 = web3.utils.toBN(newAccount2Balance).sub(web3.utils.toBN(initialAccount2Balance)).sub(account2TxFee); + const pureRewardAccount3 = web3.utils.toBN(newAccount3Balance).sub(web3.utils.toBN(initialAccount3Balance)).sub(account3TxFee); + const pureRewardAccount4 = web3.utils.toBN(newAccount4Balance).sub(web3.utils.toBN(initialAccount4Balance)).sub(account4TxFee); + const pureRewardAccount5 = web3.utils.toBN(newAccount5Balance).sub(web3.utils.toBN(initialAccount5Balance)).sub(account5TxFee); + const pureRewardAccount6 = web3.utils.toBN(newAccount6Balance).sub(web3.utils.toBN(initialAccount6Balance)).sub(account6TxFee); + const pureRewardAccount7 = web3.utils.toBN(newAccount7Balance).sub(web3.utils.toBN(initialAccount7Balance)).sub(account7TxFee); + const pureRewardAccount8 = web3.utils.toBN(newAccount8Balance).sub(web3.utils.toBN(initialAccount8Balance)).sub(account8TxFee); + + assert.equal(pureRewardAccount1.lt(pureRewardAccount2), true, "wrong reward"); + assert.equal(pureRewardAccount2.lt(pureRewardAccount3), true, "wrong reward"); + assert.equal(pureRewardAccount3.gt(pureRewardAccount4), true, "wrong reward"); + assert.equal(pureRewardAccount4.gt(pureRewardAccount5), true, "wrong reward"); + assert.equal(pureRewardAccount5.gt(pureRewardAccount6), true, "wrong reward"); + assert.equal(pureRewardAccount6.gt(pureRewardAccount7), true, "wrong reward"); + assert.equal(pureRewardAccount8.gt(pureRewardAccount2), true, "wrong reward"); // get extra 1/80 of total reward + assert.equal(pureRewardAccount8.lt(pureRewardAccount3), true, "wrong reward"); // get extra 1/80 of total reward + }); + it('non-payable address', async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const tendermintLightClient = await TendermintLightClient.deployed(); + + const tokenHub = accounts[9]; + const relayer = accounts[0]; - const systemReward = await SystemReward.deployed(); - const originSystemRewardBalance = await web3.eth.getBalance(systemReward.address); + for(let i=0; i<15; i++){ + await relayerIncentivize.addReward(tendermintLightClient.address, relayer, web3.utils.toBN(1e16), false, {from: tokenHub}); + } - await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), true, { - from: tokenHub, + for(let i=0; i<14; i++){ + await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), false, {from: tokenHub}); + } + + const systemReward = await SystemReward.deployed(); + const originSystemRewardBalance = await web3.eth.getBalance(systemReward.address); + + await relayerIncentivize.addReward(relayer, tendermintLightClient.address, web3.utils.toBN(1e16), true, {from: tokenHub}); + + await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); + await relayerIncentivize.claimRelayerReward(tendermintLightClient.address, {from: accounts[0]}); + + const newSystemRewardBalance = await web3.eth.getBalance(systemReward.address); + assert.equal(web3.utils.toBN(newSystemRewardBalance).sub(web3.utils.toBN(originSystemRewardBalance)).eq(web3.utils.toBN(146812500000000000)), true, "wrong amount to systemReward contract"); + + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 3, "wrong round sequence"); }); + it('dynamic extra incentive', async () => { + const relayerIncentivize = await RelayerIncentivize.deployed(); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + const relayer = accounts[2]; - await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); - await relayerIncentivize.claimRelayerReward(tendermintLightClient.address, { from: accounts[0] }); - - const newSystemRewardBalance = await web3.eth.getBalance(systemReward.address); - assert.equal( - web3.utils - .toBN(newSystemRewardBalance) - .sub(web3.utils.toBN(originSystemRewardBalance)) - .eq(web3.utils.toBN(146812500000000000)), - true, - "wrong amount to systemReward contract" - ); - - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 3, "wrong round sequence"); - }); - it("dynamic extra incentive", async () => { - const relayerIncentivize = await RelayerIncentivize.deployed(); - const crossChain = await CrossChain.deployed(); - const govHub = await GovHub.deployed(); - const relayer = accounts[2]; - - const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); - - const initialAccount1Balance = await web3.eth.getBalance(relayer); - - const roundSize = await relayerIncentivize.ROUND_SIZE.call(); - assert.equal(roundSize.toNumber(), 30, "wrong round size"); - const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); - assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); - - for (let i = 0; i < 30; i++) { - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({from: relayer, value: 1e20}); - await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); + const initialAccount1Balance = await web3.eth.getBalance(relayer); - let roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 4, "wrong round sequence"); + const roundSize = await relayerIncentivize.ROUND_SIZE.call(); + assert.equal(roundSize.toNumber(), 30, "wrong round size"); + const maximumWeight = await relayerIncentivize.MAXIMUM_WEIGHT.call(); + assert.equal(maximumWeight.toNumber(), 3, "wrong maximum weight"); - const newRelayerBalance1 = await web3.eth.getBalance(relayer); + for(let i=0; i<30; i++){ + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } - const relayerReward1 = web3.utils.toBN(newRelayerBalance1).sub(web3.utils.toBN(initialAccount1Balance)); + await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); - for (let i = 0; i < 30; i++) { - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(2e16), false, { - from: accounts[0], - }); - } + let roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 4, "wrong round sequence"); - await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); - - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 5, "wrong round sequence"); - - const newRelayerBalance2 = await web3.eth.getBalance(relayer); - - const relayerReward2 = web3.utils.toBN(newRelayerBalance2).sub(web3.utils.toBN(newRelayerBalance1)); - assert.equal(relayerReward2.gt(relayerReward1), true, "relayerReward2 should be larger than relayerReward1"); - - let dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); - assert.equal( - web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(0)), - true, - "wrong dynamicExtraIncentiveAmount" - ); - - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - MockLightClient.address, - TokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - CrossChain.address - ); - - await web3.eth.sendTransaction({ - to: SystemReward.address, - from: accounts[3], - value: web3.utils.toWei("10", "ether"), - }); + const newRelayerBalance1 = await web3.eth.getBalance(relayer); - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x000000000000000000000000000000000000000000000000002386F26FC10000"; // 1e16; - let govPackageBytes = serialize("dynamicExtraIncentiveAmount", govValue, RelayerIncentivize.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - MockLightClient.address, - TokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - accounts[8] - ); - - dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); - assert.equal( - web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(1e16)), - true, - "wrong dynamicExtraIncentiveAmount" - ); - - for (let i = 0; i < 29; i++) { - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } + const relayerReward1 = web3.utils.toBN(newRelayerBalance1).sub(web3.utils.toBN(initialAccount1Balance)); - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 6, "wrong round sequence"); - await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); + for(let i=0; i<30; i++){ + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(2e16), false, {from: accounts[0]}); + } - const relayerBalanceBeforeReward3 = await web3.eth.getBalance(relayer); + await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); - for (let i = 0; i < 30; i++) { - await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, { - from: accounts[0], - }); - } + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 5, "wrong round sequence"); + + const newRelayerBalance2 = await web3.eth.getBalance(relayer); + + const relayerReward2 = web3.utils.toBN(newRelayerBalance2).sub(web3.utils.toBN(newRelayerBalance1)); + assert.equal(relayerReward2.gt(relayerReward1), true, "relayerReward2 should be larger than relayerReward1"); - await relayerIncentivize.claimRelayerReward(relayer, { from: accounts[0] }); + let dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); + assert.equal(web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(0)), true, "wrong dynamicExtraIncentiveAmount"); - roundSequence = await relayerIncentivize.roundSequence.call(); - assert.equal(roundSequence.toNumber(), 7, "wrong round sequence"); + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, CrossChain.address); - const newRelayerBalance3 = await web3.eth.getBalance(relayer); + await web3.eth.sendTransaction({to:SystemReward.address, from:accounts[3], value: web3.utils.toWei("10", "ether")}); - const relayerReward3 = web3.utils.toBN(newRelayerBalance3).sub(web3.utils.toBN(relayerBalanceBeforeReward3)); - assert.equal(relayerReward3.eq(relayerReward2), true, "relayerReward3 should equal to relayerReward2"); - }); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x000000000000000000000000000000000000000000000000002386F26FC10000";// 1e16; + let govPackageBytes = serialize("dynamicExtraIncentiveAmount", govValue, RelayerIncentivize.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, accounts[8]); + + dynamicExtraIncentiveAmount = await relayerIncentivize.dynamicExtraIncentiveAmount.call(); + assert.equal(web3.utils.toBN(dynamicExtraIncentiveAmount).eq(web3.utils.toBN(1e16)), true, "wrong dynamicExtraIncentiveAmount"); + + for(let i=0; i<29; i++){ + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 6, "wrong round sequence"); + + await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); + + const relayerBalanceBeforeReward3 = await web3.eth.getBalance(relayer); + + for(let i=0; i<30; i++){ + await relayerIncentivize.addReward(relayer, accounts[0], web3.utils.toBN(1e16), false, {from: accounts[0]}); + } + + await relayerIncentivize.claimRelayerReward(relayer, {from: accounts[0]}); + + roundSequence = await relayerIncentivize.roundSequence.call(); + assert.equal(roundSequence.toNumber(), 7, "wrong round sequence"); + + const newRelayerBalance3 = await web3.eth.getBalance(relayer); + + const relayerReward3 = web3.utils.toBN(newRelayerBalance3).sub(web3.utils.toBN(relayerBalanceBeforeReward3)); + assert.equal(relayerReward3.eq(relayerReward2), true, "relayerReward3 should equal to relayerReward2"); + }); }); diff --git a/test/TestTendermintLightClient.js b/test/TestTendermintLightClient.js index e18cd605..04648b34 100644 --- a/test/TestTendermintLightClient.js +++ b/test/TestTendermintLightClient.js @@ -1,18 +1,25 @@ +const SystemReward = artifacts.require("SystemReward"); +const RelayerIncentivize = artifacts.require("RelayerIncentivize"); const TendermintLightClient = artifacts.require("TendermintLightClient"); +const MockRelayerHub = artifacts.require("mock/MockRelayerHub"); -const Web3 = require("web3"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const crypto = require('crypto'); +const Web3 = require('web3'); +const truffleAssert = require('truffle-assertions'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); -contract("TendermintLightClient", (accounts) => { - it("Init consensus state", async () => { - const lightClient = await TendermintLightClient.deployed(); +contract('TendermintLightClient', (accounts) => { + it('Init consensus state', async () => { + const lightClient = await TendermintLightClient.deployed(); - let initialHeight = await lightClient.initialHeight.call(); - assert.equal(initialHeight.toNumber(), 2, "mismatched initial consensus height"); - const chainID = await lightClient.getChainID.call(); - assert.equal(chainID, "Binance-Chain-Nile", "mismatched chainID"); + let uselessAddr = web3.eth.accounts.create().address; - const isHeaderSynced = await lightClient.isHeaderSynced.call(2); - assert.equal(isHeaderSynced, true, "height already synced"); - }); + let initialHeight = await lightClient.initialHeight.call(); + assert.equal(initialHeight.toNumber(), 2, "mismatched initial consensus height"); + const chainID = await lightClient.getChainID.call(); + assert.equal(chainID, "Binance-Chain-Nile", "mismatched chainID"); + + const isHeaderSynced = await lightClient.isHeaderSynced.call(2); + assert.equal(isHeaderSynced, true, "height already synced"); + }); }); diff --git a/test/TestTokenHub.js b/test/TestTokenHub.js index ea134106..8fe454e6 100644 --- a/test/TestTokenHub.js +++ b/test/TestTokenHub.js @@ -1,6 +1,6 @@ -const BN = require("bn.js"); +const BN = require('bn.js'); const sleep = require("await-sleep"); -const RLP = require("rlp"); +const RLP = require('rlp'); const SystemReward = artifacts.require("SystemReward"); const RelayerIncentivize = artifacts.require("RelayerIncentivize"); @@ -19,9 +19,10 @@ const GovHub = artifacts.require("GovHub"); const BSCValidatorSet = artifacts.require("BSCValidatorSet"); const SlashIndicator = artifacts.require("SlashIndicator"); -const Web3 = require("web3"); -const truffleAssert = require("truffle-assertions"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const crypto = require('crypto'); +const Web3 = require('web3'); +const truffleAssert = require('truffle-assertions'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); const BIND_CHANNEL_ID = 0x01; const TRANSFER_IN_CHANNELID = 0x02; @@ -34,1687 +35,1273 @@ const proof = Buffer.from(web3.utils.hexToBytes("0x00")); const merkleHeight = 100; function toBytes32String(input) { - let initialInputHexStr = web3.utils.toBN(input).toString(16); - const initialInputHexStrLength = initialInputHexStr.length; - - let inputHexStr = initialInputHexStr; - for (let i = 0; i < 64 - initialInputHexStrLength; i++) { - inputHexStr = "0" + inputHexStr; - } - return inputHexStr; + let initialInputHexStr = web3.utils.toBN(input).toString(16); + const initialInputHexStrLength = initialInputHexStr.length; + + let inputHexStr = initialInputHexStr; + for (var i = 0; i < 64 - initialInputHexStrLength; i++) { + inputHexStr = '0' + inputHexStr; + } + return inputHexStr; } function stringToBytes32(symbol) { - let initialSymbolHexStr = ""; - for (let i = 0; i < symbol.length; i++) { - initialSymbolHexStr += symbol.charCodeAt(i).toString(16); - } - - const initialSymbolHexStrLength = initialSymbolHexStr.length; - - let bep2Bytes32Symbol = initialSymbolHexStr; - for (let i = 0; i < 64 - initialSymbolHexStrLength; i++) { - bep2Bytes32Symbol = bep2Bytes32Symbol + "0"; - } - return "0x" + bep2Bytes32Symbol; + var initialSymbolHexStr = ''; + for (var i=0; i= 33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - let mirrorSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - - const mirrorSender = web3.utils.bytesToHex(mirrorSynPackage[0]); - const bep20Addr = web3.utils.bytesToHex(mirrorSynPackage[1]); - const bep20Name = web3.utils.bytesToHex(mirrorSynPackage[2]); - const bep20Symbol = web3.utils.bytesToHex(mirrorSynPackage[3]); - const bep20Supply = web3.utils.bytesToHex(mirrorSynPackage[4]); - const bep20Decimals = web3.utils.bytesToHex(mirrorSynPackage[5]); - const mirrorFee = web3.utils.bytesToHex(mirrorSynPackage[6]); - const expireTime = web3.utils.bytesToHex(mirrorSynPackage[7]); - - return { mirrorSender, bep20Addr, bep20Name, bep20Symbol, bep20Supply, bep20Decimals, mirrorFee, expireTime }; + eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); + assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + mirrorSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + + const mirrorSender = web3.utils.bytesToHex(mirrorSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(mirrorSynPackage[1]); + const bep20Name = web3.utils.bytesToHex(mirrorSynPackage[2]); + const bep20Symbol = web3.utils.bytesToHex(mirrorSynPackage[3]); + const bep20Supply = web3.utils.bytesToHex(mirrorSynPackage[4]); + const bep20Decimals = web3.utils.bytesToHex(mirrorSynPackage[5]); + const mirrorFee = web3.utils.bytesToHex(mirrorSynPackage[6]); + const expireTime = web3.utils.bytesToHex(mirrorSynPackage[7]); + + return {mirrorSender, bep20Addr, bep20Name, bep20Symbol, bep20Supply, bep20Decimals, mirrorFee, expireTime}; } function buildMirrorAckPackage(mirrorSender, bep20Addr, bep20Decimals, bep2Symbol, refundAmount, errorCode) { - const packageBytesPrefix = buildAckPackagePrefix(); - const packageBytes = RLP.encode([ - mirrorSender, - bep20Addr, - bep20Decimals, - stringToBytes32(bep2Symbol), - refundAmount, - errorCode, - ]); - return Buffer.concat([packageBytesPrefix, packageBytes]); + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([ + mirrorSender, + bep20Addr, + bep20Decimals, + stringToBytes32(bep2Symbol), + refundAmount, + errorCode]); + return Buffer.concat([packageBytesPrefix, packageBytes]); } function decodeSyncSynPackage(packageBytes) { - let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); - assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - let syncSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - const syncSender = web3.utils.bytesToHex(syncSynPackage[0]); - const bep20Addr = web3.utils.bytesToHex(syncSynPackage[1]); - const bep2Symbol = web3.utils.bytesToHex(syncSynPackage[2]); - const bep20Supply = web3.utils.bytesToHex(syncSynPackage[3]); - const syncFee = web3.utils.bytesToHex(syncSynPackage[4]); - const expireTime = web3.utils.bytesToHex(syncSynPackage[5]); - return { syncSender, bep20Addr, bep2Symbol, bep20Supply, syncFee, expireTime }; + eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(packageBytes)); + assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + syncSynPackage = RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); + const syncSender = web3.utils.bytesToHex(syncSynPackage[0]); + const bep20Addr = web3.utils.bytesToHex(syncSynPackage[1]); + const bep2Symbol = web3.utils.bytesToHex(syncSynPackage[2]); + const bep20Supply = web3.utils.bytesToHex(syncSynPackage[3]); + const syncFee = web3.utils.bytesToHex(syncSynPackage[4]); + const expireTime = web3.utils.bytesToHex(syncSynPackage[5]); + return {syncSender, bep20Addr, bep2Symbol, bep20Supply, syncFee, expireTime}; } function buildSyncAckPackage(syncSender, bep20Addr, refundAmount, errorCode) { - const packageBytesPrefix = buildAckPackagePrefix(); - const packageBytes = RLP.encode([syncSender, bep20Addr, refundAmount, errorCode]); - return Buffer.concat([packageBytesPrefix, packageBytes]); + const packageBytesPrefix = buildAckPackagePrefix(); + const packageBytes = RLP.encode([ + syncSender, + bep20Addr, + refundAmount, + errorCode + ]); + return Buffer.concat([packageBytesPrefix, packageBytes]); } function serialize(key, value, target, extra) { - let pkg = []; - pkg.push(key); - pkg.push(value); - pkg.push(target); - if (extra != null) { - pkg.push(extra); - } - return RLP.encode(pkg); + let pkg = []; + pkg.push(key); + pkg.push(value); + pkg.push(target); + if(extra != null){ + pkg.push(extra); + } + return RLP.encode(pkg); } function verifyPrefixAndExtractSyncPackage(payload, expectedRelayFee) { - let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); - assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); - assert.ok( - web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(expectedRelayFee)), - "wrong relay fee" - ); - return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); -} - -function verifyPrefixAndExtractAckPackage(payload) { - let eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); - assert.ok(eventPayloadBytes.length >= 33, "wrong bind ack package"); - assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x01", "wrong package type"); - assert.ok( - web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(0)), - "wrong relay fee" - ); - if (eventPayloadBytes.length > 33) { + eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); + assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x00", "wrong package type"); + assert.ok(web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(expectedRelayFee)), "wrong relay fee"); return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); - } - return []; } -contract("TokenHub", (accounts) => { - it("Init TokenHub", async () => { - const mockLightClient = await MockLightClient.deployed(); - await mockLightClient.setBlockNotSynced(false); - - const tokenHub = await TokenHub.deployed(); - let balance_wei = await web3.eth.getBalance(tokenHub.address); - assert.equal(balance_wei, 50e18, "wrong balance"); - - const relayer = accounts[1]; - const relayerInstance = await RelayerHub.deployed(); - await relayerInstance.register({ from: relayer, value: 1e20 }); - let res = await relayerInstance.isRelayer.call(relayer); - assert.equal(res, true); - }); - it("Relay expired bind package", async () => { - const abcToken = await ABCToken.deployed(); - const tokenManager = await TokenManager.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, - }); - - let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal(bindRequenst.bep2TokenSymbol.toString(), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - assert.equal(bindRequenst.totalSupply.eq(new BN("52b7d2dcc80cd2e4000000", 16)), true, "wrong total supply"); // 1e26 - assert.equal(bindRequenst.peggyAmount.eq(new BN("51e410c0f93fe543000000", 16)), true, "wrong peggy amount"); // 99e24 - assert.equal(bindRequenst.contractAddr.toString(), abcToken.address.toString(), "wrong contract address"); - - let lockAmount = await tokenManager.queryRequiredLockAmountForBind("ABC-9C7"); - assert.equal(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)).eq(lockAmount), true, "wrong lock amount"); - try { - await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: relayer }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("only bep20 owner can approve this bind request")); +function verifyPrefixAndExtractAckPackage(payload) { + eventPayloadBytes = Buffer.from(web3.utils.hexToBytes(payload)); + assert.ok(eventPayloadBytes.length>=33, "wrong bind ack package"); + assert.equal(web3.utils.bytesToHex(eventPayloadBytes.subarray(0, 1)), "0x01", "wrong package type"); + assert.ok(web3.utils.toBN(web3.utils.bytesToHex(eventPayloadBytes.subarray(1, 33))).eq(web3.utils.toBN(0)), "wrong relay fee"); + if (eventPayloadBytes.length>33) { + return RLP.decode(eventPayloadBytes.subarray(33, eventPayloadBytes.length)); } + return [] +} - try { - await tokenManager.approveBind("0x0000000000000000000000000000000000000000", "ABC-9C7", { from: relayer }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("contact address doesn't equal to the contract address in bind request")); - } +contract('TokenHub', (accounts) => { + it('Init TokenHub', async () => { + const mockLightClient = await MockLightClient.deployed(); + await mockLightClient.setBlockNotSynced(false); - try { - await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("allowance is not enough")); - } + const tokenHub = await TokenHub.deployed(); + let balance_wei = await web3.eth.getBalance(tokenHub.address); + assert.equal(balance_wei, 50e18, "wrong balance"); - await abcToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)), { from: owner }); - await sleep(5 * 1000); - // approve expired bind request - let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - - bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal( - bindRequenst.bep2TokenSymbol.toString(), - "0x0000000000000000000000000000000000000000000000000000000000000000", - "wrong bep2TokenSymbol" - ); - }); - it("Reject bind", async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); //expire time - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, + const relayer = accounts[1]; + const relayerInstance = await RelayerHub.deployed(); + await relayerInstance.register({from: relayer, value: 1e20}); + let res = await relayerInstance.isRelayer.call(relayer); + assert.equal(res,true); }); + it('Relay expired bind package', async () => { + const abcToken = await ABCToken.deployed(); + const tokenManager = await TokenManager.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + + let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + assert.equal(bindRequenst.totalSupply.eq(new BN('52b7d2dcc80cd2e4000000', 16)), true, "wrong total supply"); // 1e26 + assert.equal(bindRequenst.peggyAmount.eq(new BN('51e410c0f93fe543000000', 16)), true, "wrong peggy amount"); // 99e24 + assert.equal(bindRequenst.contractAddr.toString(), abcToken.address.toString(), "wrong contract address"); + + let lockAmount = await tokenManager.queryRequiredLockAmountForBind( "ABC-9C7"); + assert.equal(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)).eq(lockAmount), true, "wrong lock amount"); + try { + await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: relayer}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("only bep20 owner can approve this bind request")); + } + + try { + await tokenManager.approveBind("0x0000000000000000000000000000000000000000", "ABC-9C7", {from: relayer}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("contact address doesn't equal to the contract address in bind request")); + } + + try { + await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("allowance is not enough")); + } + + await abcToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(1e6)), {from: owner}); + await sleep(5 * 1000); + // approve expired bind request + let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); + }); + it('Reject bind', async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - try { - await tokenManager.rejectBind(abcToken.address, "ABC-9C7", { from: relayer, value: 1e16 }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("only bep20 owner can reject")); - } + const owner = accounts[0]; + const relayer = accounts[1]; - let tx = await tokenManager.rejectBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); //expire time + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x07", "bind status should be rejected"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + try { + await tokenManager.rejectBind(abcToken.address, "ABC-9C7", {from: relayer, value: 1e16}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("only bep20 owner can reject")); + } - const bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal( - bindRequenst.bep2TokenSymbol.toString(), - "0x0000000000000000000000000000000000000000000000000000000000000000", - "wrong bep2TokenSymbol" - ); - }); - it("Expire bind", async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); + let tx = await tokenManager.rejectBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); - const relayer = accounts[1]; + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x07", "bind status should be rejected"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, + const bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); + it('Expire bind', async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - try { - await tokenManager.expireBind("ABC-9C7", { from: accounts[2], value: 1e16 }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("bind request is not expired")); - } - - await sleep(5 * 1000); - - let tx = await tokenManager.expireBind("ABC-9C7", { from: accounts[2], value: 1e16 }); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + const owner = accounts[0]; + const relayer = accounts[1]; - let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 - assert.equal( - bindRequenst.bep2TokenSymbol.toString(), - "0x0000000000000000000000000000000000000000000000000000000000000000", - "wrong bep2TokenSymbol" - ); - }); - it("Mismatched token symbol", async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - const owner = accounts[0]; - const relayer = accounts[1]; + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - const bindPackage = buildBindPackage(0, "DEF-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + try { + await tokenManager.expireBind("ABC-9C7", {from: accounts[2], value: 1e16}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("bind request is not expired")); + } - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, - }); + await sleep(5 * 1000); - let tx = await tokenManager.approveBind(abcToken.address, "DEF-9C7", { from: owner, value: 1e16 }); - - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x02", "bind status should be symbol mismatch"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("DEF-9C7"), "wrong bep2TokenSymbol"); - - let bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("DEF-9C7")); // symbol: ABC-9C7 - assert.equal( - bindRequenst.bep2TokenSymbol.toString(), - "0x0000000000000000000000000000000000000000000000000000000000000000", - "wrong bep2TokenSymbol" - ); - }); - it("Success bind", async () => { - const tokenManager = await TokenManager.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, - }); + tx = await tokenManager.expireBind("ABC-9C7", {from: accounts[2], value: 1e16}); - let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", { from: owner, value: 1e16 }); - truffleAssert.eventEmitted(tx, "bindSuccess", (ev) => { - return ev.contractAddr.toLowerCase() === abcToken.address.toLowerCase() && ev.bep2Symbol === "ABC-9C7"; - }); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - - const tokenHub = await TokenHub.deployed(); - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); - assert.equal(bep2Symbol, "ABC-9C7", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); - assert.equal(contractAddr, abcToken.address, "wrong contract addr"); - - let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(tokenManagerBalance, "0", "tokenManager balance should be zero"); - }); - it("Relayer transfer from BC to BSC", async () => { - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - - const transferInPackage = buildTransferInPackage( - "ABC-9C7", - abcToken.address, - 155e17, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.toNumber(), 0, "wrong balance"); - - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, { - from: relayer, - }); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x01", "bind status should be timeout"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); - balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); - }); - it("Expired transfer from BC to BSC", async () => { - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - - const transferInPackage = buildTransferInPackage( - "ABC-9C7", - abcToken.address, - 155e17, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - await sleep(5 * 1000); - - let tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - let event; - truffleAssert.eventEmitted(tx, "crossChainPackage", (ev) => { - let matched = false; - if (ev.packageSequence.toString() === "0") { - event = ev; - matched = true; - } - return matched; + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("ABC-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); - let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "response should be empty"); - assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(155e7).toString(16), "response should be empty"); - assert.equal( - web3.utils.bytesToHex(decoded[2]), - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", - "response should be empty" - ); - assert.equal(web3.utils.bytesToHex(decoded[3]), "0x01", "refund status should be timeout"); - - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); - }); - it("Relayer BNB transfer from BC to BSC", async () => { - const tokenHub = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - let transferInPackage = buildTransferInPackage( - "BNB", - "0x0000000000000000000000000000000000000000", - 1e18, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - let initBalance = await web3.eth.getBalance(accounts[2]); - let tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - let nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; - assert.equal(nestedEvents.length, 2, "wrong event number"); - assert.equal(nestedEvents[1].args.amount.eq(web3.utils.toBN(1e16)), true, "wrong relayer amount"); - let newBalance = await web3.eth.getBalance(accounts[2]); - assert.equal( - web3.utils.toBN(newBalance).sub(web3.utils.toBN(initBalance)).eq(web3.utils.toBN(1e18)), - true, - "wrong balance" - ); - - //try a very large relayer fee: 2e18 - transferInPackage = buildTransferInPackageWithRelayFee( - "BNB", - "0x0000000000000000000000000000000000000000", - 1e18, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", - 2e18 - ); - transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; - assert.equal(nestedEvents.length, 1, "wrong event number"); - }); - it("BNB transfer to non-payable address", async () => { - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - const tendermintLightClient = await TendermintLightClient.deployed(); - const transferInPackage = buildTransferInPackage( - "BNB", - "0x0000000000000000000000000000000000000000", - 1e18, - tendermintLightClient.address, - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - const transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - const tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - let event; - truffleAssert.eventEmitted(tx, "crossChainPackage", (ev) => { - let matched = false; - if (ev.packageSequence.toString() === "1") { - event = ev; - matched = true; - } - return matched; - }); - let decoded = verifyPrefixAndExtractAckPackage(event.payload); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "response should be empty"); - assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(1e8).toString(16), "response should be empty"); - assert.equal( - web3.utils.bytesToHex(decoded[2]), - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", - "response should be empty" - ); - assert.equal(web3.utils.bytesToHex(decoded[3]), "0x04", "refund status should be non-payable recipient address"); - }); - it("Transfer from BSC to BC", async () => { - const crossChain = await CrossChain.deployed(); - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const defToken = await DEFToken.deployed(); - - const sender = accounts[2]; + it('Mismatched token symbol', async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - let amount = web3.utils.toBN(1e18); - let relayFee = web3.utils.toBN(1e16); - - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("BEP20: transfer amount exceeds allowance")); - } + const owner = accounts[0]; + const relayer = accounts[1]; - try { - const amount = web3.utils.toBN(1e8); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount")); - } - - try { - relayFee = web3.utils.toBN(1e16).add(web3.utils.toBN(1)); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid received BNB amount: precision loss in amount conversion")); - } + const bindPackage = buildBindPackage(0, "DEF-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - try { - relayFee = web3.utils.toBN(1e14); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); - } + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); - relayFee = web3.utils.toBN(1e16); - try { - await tokenHub.transferOut(defToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); - } + tx = await tokenManager.approveBind(abcToken.address, "DEF-9C7", {from: owner, value: 1e16}); - try { - amount = web3.utils.toBN(1e8); - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); - } + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x02", "bind status should be symbol mismatch"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("DEF-9C7"), "wrong bep2TokenSymbol"); - amount = web3.utils.toBN(1e18); - await abcToken.approve(tokenHub.address, amount, { from: sender }); - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { from: sender }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); - } - let tx = await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, + bindRequenst = await tokenManager.bindPackageRecord.call(stringToBytes32("DEF-9C7")); // symbol: ABC-9C7 + assert.equal(bindRequenst.bep2TokenSymbol.toString(), "0x0000000000000000000000000000000000000000000000000000000000000000", "wrong bep2TokenSymbol"); }); - truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { - return ( - ev.amount.eq(web3.utils.toBN(amount)) && - ev.bep20Addr.toString().toLowerCase() === abcToken.address.toLowerCase() - ); + it('Success bind', async () => { + const tokenManager = await TokenManager.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "ABC-9C7", abcToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + + let tx = await tokenManager.approveBind(abcToken.address, "ABC-9C7", {from: owner, value: 1e16}); + truffleAssert.eventEmitted(tx, "bindSuccess",(ev) => { + return ev.contractAddr.toLowerCase() === abcToken.address.toLowerCase() && ev.bep2Symbol === "ABC-9C7"; + }); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("ABC-9C7"), "wrong bep2TokenSymbol"); + + const tokenHub = await TokenHub.deployed(); + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); + assert.equal(bep2Symbol, "ABC-9C7", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); + assert.equal(contractAddr, abcToken.address, "wrong contract addr"); + + let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(tokenManagerBalance, "0", "tokenManager balance should be zero"); }); + it('Relayer transfer from BC to BSC', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "wrong symbol"); - assert.equal(web3.utils.bytesToHex(decoded[1]), abcToken.address.toLowerCase(), "wrong contract address"); - assert.ok( - web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e8)), - "wrong transferOut amount" - ); - assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipient.toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[4][0]), sender.toLowerCase(), "wrong refund address"); - - let balance = await abcToken.balanceOf.call(accounts[2]); - assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); - }); - it("Relay refund package", async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - const refundAddr = accounts[2]; - - const packageBytesPrefix = buildAckPackagePrefix(1e16); + const relayer = accounts[1]; - const packageBytes = RLP.encode([ - abcToken.address, //bep20 contract address - [1e18], //amount - [refundAddr], //refund address - 1, - ]); //status - - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - const amount = web3.utils.toBN(1e18); - let balance = await abcToken.balanceOf.call(refundAddr); - assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); - - let tx = await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - proof, - merkleHeight, - refundSequence, - TRANSFER_OUT_CHANNELID, - { from: relayer } - ); - let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; - assert.equal( - nestedEventValues[0].toString().toLowerCase(), - abcToken.address.toLowerCase(), - "wrong refund contract address" - ); - - balance = await abcToken.balanceOf.call(refundAddr); - assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); - }); - it("Batch transfer out", async () => { - const tokenHub = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); - - const sender = accounts[0]; - - const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - let amounts = [web3.utils.toBN(5e9), web3.utils.toBN(5e9)]; - const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - - let timestamp = Math.floor(Date.now() / 1000); - let expireTime = timestamp + 150; - - try { - await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { - from: sender, - value: web3.utils.toBN(2000002e10), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); - } + const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.toNumber(), 0, "wrong balance"); - amounts = [web3.utils.toBN(1e16), web3.utils.toBN(2e16)]; - let tx = await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { - from: sender, - value: web3.utils.toBN(5e16), + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + + balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); }); - truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { - return ( - ev.amount.eq(web3.utils.toBN(3e16)) && - ev.bep20Addr.toString().toLowerCase() === "0x0000000000000000000000000000000000000000" - ); + it('Expired transfer from BC to BSC', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + + const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + await sleep(5 * 1000); + + let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + let event; + truffleAssert.eventEmitted(tx, "crossChainPackage",(ev) => { + let matched = false; + if (ev.packageSequence.toString() === "0") { + event = ev; + matched = true; + } + return matched; + }); + let decoded = verifyPrefixAndExtractAckPackage(event.payload); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "response should be empty"); + assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(155e7).toString(16), "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[3]), "0x01", "refund status should be timeout"); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); }); - assert.equal(tx.receipt.status, true, "failed transaction"); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 2e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "wrong symbol"); - assert.equal( - web3.utils.bytesToHex(decoded[1]), - "0x0000000000000000000000000000000000000000", - "wrong contract address" - ); - assert.ok( - web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e6)), - "wrong transferOut amount" - ); - assert.ok( - web3.utils.toBN(web3.utils.bytesToHex(decoded[2][1])).eq(web3.utils.toBN(2e6)), - "wrong transferOut amount" - ); - assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipientAddrs[0].toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[3][1]), recipientAddrs[1].toLowerCase(), "wrong recipient address"); - assert.equal(web3.utils.bytesToHex(decoded[4][0]), refundAddrs[0].toLowerCase(), "wrong refund address"); - assert.equal(web3.utils.bytesToHex(decoded[4][1]), refundAddrs[1].toLowerCase(), "wrong refund address"); - }); - it("Bind malicious BEP20 token", async () => { - const maliciousToken = await MaliciousToken.deployed(); - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const crossChain = await CrossChain.deployed(); - - const owner = accounts[0]; - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(0, "MALICIOU-A09", maliciousToken.address, 1e8, 99e6, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, + it('Relayer BNB transfer from BC to BSC', async () => { + const tokenHub = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + let transferInPackage = buildTransferInPackage("BNB", "0x0000000000000000000000000000000000000000", 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + let initBalance = await web3.eth.getBalance(accounts[2]); + let tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + let nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; + assert.equal(nestedEvents.length, 2, "wrong event number"); + assert.equal(nestedEvents[1].args.amount.eq(web3.utils.toBN(1e16)), true, "wrong relayer amount"); + let newBalance = await web3.eth.getBalance(accounts[2]); + assert.equal(web3.utils.toBN(newBalance).sub(web3.utils.toBN(initBalance)).eq(web3.utils.toBN(1e18)), true, "wrong balance"); + + //try a very large relayer fee: 2e18 + transferInPackage = buildTransferInPackageWithRelayFee("BNB", "0x0000000000000000000000000000000000000000", 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", 2e18); + transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + nestedEvents = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs; + assert.equal(nestedEvents.length, 1, "wrong event number"); }); - assert.equal(tx.receipt.status, true, "failed transaction"); - - await maliciousToken.approve(tokenManager.address, web3.utils.toBN("1000000000000000000000000"), { - from: owner, + it('BNB transfer to non-payable address', async () => { + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + const tendermintLightClient = await TendermintLightClient.deployed(); + const transferInPackage = buildTransferInPackage("BNB", "0x0000000000000000000000000000000000000000", 1e18, tendermintLightClient.address, "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + const transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + const tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + let event; + truffleAssert.eventEmitted(tx, "crossChainPackage",(ev) => { + let matched = false; + if (ev.packageSequence.toString() === "1") { + event = ev; + matched = true; + } + return matched; + }); + let decoded = verifyPrefixAndExtractAckPackage(event.payload); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "response should be empty"); + assert.ok(web3.utils.bytesToHex(decoded[1]), web3.utils.toBN(1e8).toString(16), "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[2]), "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48", "response should be empty"); + assert.equal(web3.utils.bytesToHex(decoded[3]), "0x04", "refund status should be non-payable recipient address"); }); - await tokenManager.approveBind(maliciousToken.address, "MALICIOU-A09", { from: owner, value: 1e16 }); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(maliciousToken.address); - assert.equal(bep2Symbol, "MALICIOU-A09", "wrong symbol"); - - const transferInPackage = buildTransferInPackage( - "MALICIOU-A09", - maliciousToken.address, - 155e17, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - let balance = await maliciousToken.balanceOf.call(accounts[2]); - assert.equal(balance.toNumber(), 0, "wrong balance"); - - tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - assert.equal(tx.receipt.status, true, "failed transaction"); - - let newTransferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - assert.equal(newTransferInSequence.toNumber(), transferInSequence.toNumber() + 1, "wrong transferIn sequence"); - - let packageBytesPrefix = Buffer.from( - web3.utils.hexToBytes("0x01" + "0000000000000000000000000000000000000000000000000000000000000000") - ); - - let packageBytes = RLP.encode([ - maliciousToken.address, //bep2TokenSymbol - ["0x000000000000000000000000000000000000000000000000000000174876E800"], //amount - ["0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"], //refund address - 1, - ]); //refund address - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - tx = await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - proof, - merkleHeight, - refundSequence, - TRANSFER_OUT_CHANNELID, - { from: relayer } - ); - assert.equal(tx.receipt.status, true, "failed transaction"); - - let newRefundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - assert.equal(newRefundSequence.toNumber(), refundSequence.toNumber() + 1, "wrong transferIn sequence"); - }); - it("Uint256 overflow in transferOut and batchTransferOutBNB", async () => { - const tokenHub = await TokenHub.deployed(); - - const sender = accounts[2]; - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - let recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - let amount = web3.utils.toBN("115792089237316195423570985008687907853269984665640564039457584007903129639936"); - - try { - await tokenHub.transferOut("0x0000000000000000000000000000000000000000", recipient, amount, expireTime, { - from: sender, - value: web3.utils.toBN("9999990000000000"), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("SafeMath: addition overflow")); - } - - const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - let amounts = [ - web3.utils.toBN("100000000000000000000000000000000000000000000000000000000000000000000000000000"), - web3.utils.toBN("15792089237316195423570985008687907853269984665640564039457584007910000000000"), - ]; - const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; - - timestamp = Math.floor(Date.now() / 1000); - expireTime = timestamp + 150; - - try { - await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, { - from: sender, - value: web3.utils.toBN("9999990000000000"), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("SafeMath: addition overflow")); - } - }); - it("fail ack for transfer out", async () => { - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - const relayer = accounts[1]; - - let initBalance3 = await abcToken.balanceOf.call(accounts[3]); - let initBalance4 = await abcToken.balanceOf.call(accounts[4]); - - let packageBytesPrefix = Buffer.from( - web3.utils.hexToBytes("0x02" + "0000000000000000000000000000000000000000000000000000000000000000") - ); - - let packageBytes = RLP.encode([ - stringToBytes32("ABC-9C7"), - abcToken.address, - [1e6, 2e6], - ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], - [accounts[3], accounts[4]], - Math.floor(Date.now() / 1000), - ]); - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - proof, - merkleHeight, - refundSequence, - TRANSFER_OUT_CHANNELID, - { from: relayer } - ); - - let newBalance3 = await abcToken.balanceOf.call(accounts[3]); - let newBalance4 = await abcToken.balanceOf.call(accounts[4]); - - assert.equal(newBalance3.sub(initBalance3).eq(web3.utils.toBN(1e16)), true, "wrong balance"); - assert.equal(newBalance4.sub(initBalance4).eq(web3.utils.toBN(2e16)), true, "wrong balance"); - }); - it("Unbind Token", async () => { - const tokenHub = await TokenHub.deployed(); - const abcToken = await ABCToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const relayer = accounts[1]; - - const bindPackage = buildBindPackage(1, "ABC-9C7", abcToken.address, 0, 0, 0); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - - let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, + it('Transfer from BSC to BC', async () => { + const crossChain = await CrossChain.deployed(); + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const defToken = await DEFToken.deployed(); + + const sender = accounts[2]; + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + let amount = web3.utils.toBN(1e18); + let relayFee = web3.utils.toBN(1e16); + + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("BEP20: transfer amount exceeds allowance")); + } + + try { + const amount = web3.utils.toBN(1e8); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount")); + } + + try { + relayFee = web3.utils.toBN(1e16).add(web3.utils.toBN(1)); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid received BNB amount: precision loss in amount conversion")); + } + + try { + relayFee = web3.utils.toBN(1e14); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); + } + + relayFee = web3.utils.toBN(1e16); + try { + await tokenHub.transferOut(defToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); + } + + try { + amount = web3.utils.toBN(1e8); + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); + } + + amount = web3.utils.toBN(1e18); + await abcToken.approve(tokenHub.address, amount, {from: sender}); + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("received BNB amount should be no less than the minimum relayFee")); + } + let tx = await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { + return ev.amount.eq(web3.utils.toBN(amount)) && ev.bep20Addr.toString().toLowerCase() === abcToken.address.toLowerCase(); + }); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("ABC-9C7"), "wrong symbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), abcToken.address.toLowerCase(), "wrong contract address"); + assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e8)), "wrong transferOut amount"); + assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipient.toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[4][0]), sender.toLowerCase(), "wrong refund address"); + + let balance = await abcToken.balanceOf.call(accounts[2]); + assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); }); - assert.equal(tx.receipt.status, true, "failed transaction"); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); - assert.equal(bep2Symbol, "", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); - assert.equal(contractAddr, "0x0000000000000000000000000000000000000000", "wrong contract addr"); - - const transferInPackage = buildTransferInPackage( - "ABC-9C7", - abcToken.address, - 1e18, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - tx = await crossChain.handlePackage( - transferInPackage, - proof, - merkleHeight, - transferInSequence, - TRANSFER_IN_CHANNELID, - { from: relayer } - ); - assert.equal(tx.receipt.status, true, "failed transaction"); - - // refund should be successful - const refundAddr = accounts[2]; - let packageBytesPrefix = Buffer.from( - web3.utils.hexToBytes("0x01" + "0000000000000000000000000000000000000000000000000000000000000000") - ); - let packageBytes = RLP.encode([ - abcToken.address, //bep2TokenSymbol - ["0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000"], //amount - [refundAddr], //refund address - 1, - ]); //refund address - - let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - - let beforeRefundBalance = await abcToken.balanceOf.call(refundAddr); - - tx = await crossChain.handlePackage( - Buffer.concat([packageBytesPrefix, packageBytes]), - proof, - merkleHeight, - refundSequence, - TRANSFER_OUT_CHANNELID, - { from: relayer } - ); - assert.equal(tx.receipt.status, true, "failed transaction"); - let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; - assert.equal( - nestedEventValues[0].toString().toLowerCase(), - abcToken.address.toLowerCase(), - "wrong refund contract address" - ); - assert.equal(nestedEventValues[1].toString().toLowerCase(), refundAddr.toLowerCase(), "wrong refund address"); - - let afterRefundBalance = await abcToken.balanceOf.call(refundAddr); - assert.equal(afterRefundBalance.sub(beforeRefundBalance).eq(web3.utils.toBN(1e18)), true, "wrong balance"); - - // transferOut should be failed - const sender = accounts[2]; - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 150; // expire at two minutes later - const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; - const amount = web3.utils.toBN(1e11); - const relayFee = web3.utils.toBN(2e16); - await abcToken.approve(tokenHub.address, amount, { from: sender }); - try { - await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, { - from: sender, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); - } - }); - it("bind and transfer miniToken", async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const crossChain = await CrossChain.deployed(); + it('Relay refund package', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); - const owner = accounts[0]; - const relayer = accounts[1]; + const relayer = accounts[1]; + const refundAddr = accounts[2]; - const bindPackage = buildBindPackage(0, "XYZ-9C7M", miniToken.address, 1e4, 5e3, 18); - let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + const packageBytesPrefix = buildAckPackagePrefix(1e16); - await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, { - from: relayer, - }); + const packageBytes = RLP.encode([ + abcToken.address, //bep20 contract address + [1e18], //amount + [refundAddr], //refund address + 1]); //status - await miniToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(5e3)), { from: owner }); - let tx = await tokenManager.approveBind(miniToken.address, "XYZ-9C7M", { from: owner, value: 1e16 }); + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); - assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); - assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("XYZ-9C7M"), "wrong bep2TokenSymbol"); + const amount = web3.utils.toBN(1e18); + let balance = await abcToken.balanceOf.call(refundAddr); + assert.equal(balance.eq(web3.utils.toBN(155e17).sub(amount)), true, "wrong balance"); - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); - assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); - const contractAddr = await tokenHub.getBoundContract.call("XYZ-9C7M"); - assert.equal(contractAddr, miniToken.address, "wrong contract addr"); + tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; + assert.equal(nestedEventValues[0].toString().toLowerCase(), abcToken.address.toLowerCase(), "wrong refund contract address"); - let amount = web3.utils.toBN(1e18); - let recipient = accounts[3]; - await miniToken.approve(tokenHub.address, amount, { from: owner }); - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; - const relayFee = web3.utils.toBN(1e16); - tx = await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, { - from: owner, - value: relayFee, + balance = await abcToken.balanceOf.call(refundAddr); + assert.equal(balance.eq(web3.utils.toBN(155e17)), true, "wrong balance"); }); - truffleAssert.eventEmitted(tx, "transferOutSuccess", (ev) => { - return ( - ev.amount.eq(web3.utils.toBN(amount)) && - ev.bep20Addr.toString().toLowerCase() === miniToken.address.toLowerCase() - ); + it('Batch transfer out', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const sender = accounts[0]; + + const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + let amounts = [web3.utils.toBN(5e9), web3.utils.toBN(5e9)]; + const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + + let timestamp = Math.floor(Date.now() / 1000); + let expireTime = (timestamp + 150); + + try { + await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN(2000002e10)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("invalid transfer amount: precision loss in amount conversion")); + } + + amounts = [web3.utils.toBN(1e16), web3.utils.toBN(2e16)]; + let tx = await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN(5e16)}); + truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { + return ev.amount.eq(web3.utils.toBN(3e16)) && ev.bep20Addr.toString().toLowerCase() === "0x0000000000000000000000000000000000000000"; + }); + assert.equal(tx.receipt.status, true, "failed transaction"); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 2e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), stringToBytes32("BNB"), "wrong symbol"); + assert.equal(web3.utils.bytesToHex(decoded[1]), "0x0000000000000000000000000000000000000000", "wrong contract address"); + assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][0])).eq(web3.utils.toBN(1e6)), "wrong transferOut amount"); + assert.ok(web3.utils.toBN(web3.utils.bytesToHex(decoded[2][1])).eq(web3.utils.toBN(2e6)), "wrong transferOut amount"); + assert.equal(web3.utils.bytesToHex(decoded[3][0]), recipientAddrs[0].toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[3][1]), recipientAddrs[1].toLowerCase(), "wrong recipient address"); + assert.equal(web3.utils.bytesToHex(decoded[4][0]), refundAddrs[0].toLowerCase(), "wrong refund address"); + assert.equal(web3.utils.bytesToHex(decoded[4][1]), refundAddrs[1].toLowerCase(), "wrong refund address"); }); - amount = web3.utils.toBN(5e17); - await miniToken.approve(tokenHub.address, amount, { from: owner }); - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; - try { - await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, { - from: owner, - value: relayFee, - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("For miniToken, the transfer amount must not be less than 1")); - } + it('Bind malicious BEP20 token', async () => { + const maliciousToken = await MaliciousToken.deployed(); + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const crossChain = await CrossChain.deployed(); - amount = web3.utils.toBN(1e18); - const transferInPackage = buildTransferInPackage( - "XYZ-9C7M", - miniToken.address, - amount, - accounts[2], - "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48" - ); - let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - - const initBalance = await miniToken.balanceOf.call(accounts[2]); - await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, { - from: relayer, - }); - const newBalance = await miniToken.balanceOf.call(accounts[2]); - assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); - }); - it("enable mirror and sync channel", async () => { - const tokenManager = await TokenManager.deployed(); - const crossChain = await CrossChain.deployed(); - const govHub = await GovHub.deployed(); - - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - MockLightClient.address, - TokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - CrossChain.address - ); - - const relayer = accounts[1]; - - const tokenMgrAddrStr = TokenManager.address.toString().replace("0x", ""); - let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - let govValue = "0x04" + "01" + tokenMgrAddrStr; - let govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x05" + "01" + tokenMgrAddrStr; - govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000056bc75e2d63100000"; // 1e20; - govPackageBytes = serialize("mirrorFee", govValue, TokenManager.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - - govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); - govValue = "0x0000000000000000000000000000000000000000000000008ac7230489e80000"; // 1e19 - govPackageBytes = serialize("syncFee", govValue, TokenManager.address); - await crossChain.handlePackage( - Buffer.concat([buildSyncPackagePrefix(2e16), govPackageBytes]), - proof, - merkleHeight, - govChannelSeq, - GOV_CHANNEL_ID, - { from: relayer } - ); - - const mirrorFee = await tokenManager.mirrorFee(); - assert.equal(web3.utils.toBN(1e20).eq(mirrorFee), true, "Wrong mirrorFee"); - const syncFee = await tokenManager.syncFee(); - assert.equal(web3.utils.toBN(1e19).eq(syncFee), true, "Wrong syncFee"); - - await govHub.updateContractAddr( - BSCValidatorSet.address, - SlashIndicator.address, - SystemReward.address, - MockLightClient.address, - TokenHub.address, - RelayerIncentivize.address, - RelayerHub.address, - GovHub.address, - TokenManager.address, - accounts[8] - ); - }); - it("iterate mirror failures", async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const mirrorFee = await tokenManager.mirrorFee(); - const xyzTokenOwner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(miniToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("already bound")); - } + const owner = accounts[0]; + const relayer = accounts[1]; - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 100; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); - } + const bindPackage = buildBindPackage(0, "MALICIOU-A09", maliciousToken.address, 1e8, 99e6, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); - try { - await xyzToken.setName("", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("name length must be in [1,32]")); - } - - try { - await xyzToken.setName("XYZ TokenXYZ TokenXYZ TokenXYZ Token", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("name length must be in [1,32]")); - } + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("X", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol length must be in [2,8]")); - } - - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZXYZXYZ", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol length must be in [2,8]")); - } + await maliciousToken.approve(tokenManager.address, web3.utils.toBN('1000000000000000000000000'), {from: owner}); + await tokenManager.approveBind(maliciousToken.address, "MALICIOU-A09", {from: owner, value: 1e16}); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("X-Z", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol should only contain alphabet and number")); - } + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(maliciousToken.address); + assert.equal(bep2Symbol, "MALICIOU-A09", "wrong symbol"); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XY_Z", { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("symbol should only contain alphabet and number")); - } + const transferInPackage = buildTransferInPackage("MALICIOU-A09", maliciousToken.address, 155e17, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(1, { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } + let balance = await maliciousToken.balanceOf.call(accounts[2]); + assert.equal(balance.toNumber(), 0, "wrong balance"); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(86, { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large decimals")); - } + tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(18, { from: xyzTokenOwner }); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } + let newTransferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + assert.equal(newTransferInSequence.toNumber(), transferInSequence.toNumber()+1, "wrong transferIn sequence"); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(18, { from: xyzTokenOwner }); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee).add(web3.utils.toBN(1e9)), - }); - assert.fail(); - } catch (error) { - assert.ok( - error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee") - ); - } + packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( + "0x01" + + "0000000000000000000000000000000000000000000000000000000000000000" + )); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(18, { from: xyzTokenOwner }); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee).sub(web3.utils.toBN(1e9)), - }); - assert.fail(); - } catch (error) { - assert.ok( - error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee") - ); - } + packageBytes = RLP.encode([ + maliciousToken.address, //bep2TokenSymbol + ["0x000000000000000000000000000000000000000000000000000000174876E800"], //amount + ["0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"], //refund address + 1]); //refund address + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); - try { - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(18, { from: xyzTokenOwner }); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("mirror pending")); - const mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "", mirrorFee, 1); - await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, { - from: relayer, - }); - const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - } - }); - it("successful mirror", async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - - const xyzTokenOwner = accounts[0]; - const relayer = accounts[1]; - const player = accounts[2]; - - await xyzToken.setName("XYZ Token", { from: xyzTokenOwner }); - await xyzToken.setSymbol("XYZ", { from: xyzTokenOwner }); - await xyzToken.setDecimals(18, { from: xyzTokenOwner }); - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const xyzTokenTotalSupply = await xyzToken.totalSupply(); - const xyzTokenDecimals = await xyzToken.decimals(); - const xyzTokenName = await xyzToken.name(); - const xyzTokenSymbol = await xyzToken.symbol(); - - const mirrorFee = await tokenManager.mirrorFee(); - const syncFee = await tokenManager.syncFee(); + tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - let tx = await tokenManager.mirror(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(mirrorFee), + let newRefundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + assert.equal(newRefundSequence.toNumber(), refundSequence.toNumber()+1, "wrong transferIn sequence"); }); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedMirrorSynPackage = decodeMirrorSynPackage(nestedEventValues.payload); - assert.equal( - decodedMirrorSynPackage.mirrorSender.toLowerCase(), - player.toLowerCase(), - "Wrong mirror sender in mirror sync package" - ); - assert.equal( - decodedMirrorSynPackage.bep20Addr.toLowerCase(), - XYZToken.address.toLowerCase(), - "Wrong bep20 address in mirror sync package" - ); - assert.equal( - decodedMirrorSynPackage.bep20Name, - stringToBytes32(xyzTokenName), - "Wrong bep20 name in mirror sync package" - ); // name: XYZ Token - assert.equal( - decodedMirrorSynPackage.bep20Symbol, - stringToBytes32(xyzTokenSymbol), - "Wrong bep20 symbol in mirror sync package" - ); // symbol: XYZ - assert.equal( - web3.utils.toBN(decodedMirrorSynPackage.mirrorFee).mul(web3.utils.toBN(1e10)).eq(mirrorFee), - true, - "Wrong mirrorFee in mirror sync package" - ); - assert.equal( - web3.utils.hexToNumber(decodedMirrorSynPackage.bep20Decimals), - xyzTokenDecimals, - "Wrong decimals in mirror sync package" - ); - assert.equal( - web3.utils.toBN(decodedMirrorSynPackage.bep20Supply).eq(xyzTokenTotalSupply), - true, - "Wrong total supply in mirror sync package" - ); - let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - - // mirror fail ack - let mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); - await crossChain.handlePackage( - Buffer.concat([ - buildFailAckPackagePrefix(), - mirrorFailAckPackageBytes.subarray(33, mirrorFailAckPackageBytes.length), - ]), - proof, - merkleHeight, - mirrorChannelSeq, - MIRROR_CHANNELID, - { from: relayer } - ); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - // success mirror - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.mirror(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(mirrorFee) }); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); - - mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); - const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "XYZ-123", mirrorFee, 0); - await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, { - from: relayer, + it('Uint256 overflow in transferOut and batchTransferOutBNB', async () => { + const tokenHub = await TokenHub.deployed(); + + const sender = accounts[2]; + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + let recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + let amount = web3.utils.toBN("115792089237316195423570985008687907853269984665640564039457584007903129639936"); + + try { + await tokenHub.transferOut("0x0000000000000000000000000000000000000000", recipient, amount, expireTime, {from: sender, value: web3.utils.toBN("9999990000000000")}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("SafeMath: addition overflow")); + } + + const recipientAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + let amounts = [web3.utils.toBN("100000000000000000000000000000000000000000000000000000000000000000000000000000"), web3.utils.toBN("15792089237316195423570985008687907853269984665640564039457584007910000000000")]; + const refundAddrs = ["0x37b8516a0f88e65d677229b402ec6c1e0e333004", "0xfa5e36a04eef3152092099f352ddbe88953bb540"]; + + timestamp = Math.floor(Date.now() / 1000); + expireTime = (timestamp + 150); + + try { + await tokenHub.batchTransferOutBNB(recipientAddrs, amounts, refundAddrs, expireTime, {from: sender, value: web3.utils.toBN("9999990000000000")}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("SafeMath: addition overflow")); + } }); + it('fail ack for transfer out', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + const relayer = accounts[1]; + + let initBalance3 = await abcToken.balanceOf.call(accounts[3]); + let initBalance4 = await abcToken.balanceOf.call(accounts[4]); + + packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( + "0x02" + + "0000000000000000000000000000000000000000000000000000000000000000" + )); + + packageBytes = RLP.encode([ + stringToBytes32("ABC-9C7"), + abcToken.address, + [1e6, 2e6], + ["0x37B8516a0F88E65D677229b402ec6C1e0E333004", "0xfA5E36a04EeF3152092099F352DDbe88953bB540"], + [accounts[3], accounts[4]], + Math.floor(Date.now() / 1000) + ]); + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + + let newBalance3 = await abcToken.balanceOf.call(accounts[3]); + let newBalance4 = await abcToken.balanceOf.call(accounts[4]); + + assert.equal(newBalance3.sub(initBalance3).eq(web3.utils.toBN(1e16)), true, "wrong balance"); + assert.equal(newBalance4.sub(initBalance4).eq(web3.utils.toBN(2e16)), true, "wrong balance"); + }); + it('Unbind Token', async () => { + const tokenHub = await TokenHub.deployed(); + const abcToken = await ABCToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(1, "ABC-9C7", abcToken.address, 0, 0, 0); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + let tx = await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(abcToken.address); + assert.equal(bep2Symbol, "", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("ABC-9C7"); + assert.equal(contractAddr, "0x0000000000000000000000000000000000000000", "wrong contract addr"); + + + const transferInPackage = buildTransferInPackage("ABC-9C7", abcToken.address, 1e18, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + tx = await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); + + // refund should be successful + const refundAddr = accounts[2]; + packageBytesPrefix = Buffer.from(web3.utils.hexToBytes( + "0x01" + + "0000000000000000000000000000000000000000000000000000000000000000" + )); + packageBytes = RLP.encode([ + abcToken.address, //bep2TokenSymbol + ["0x0000000000000000000000000000000000000000000000000DE0B6B3A7640000"], //amount + [refundAddr], //refund address + 1]); //refund address + + let refundSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_OUT_CHANNELID); + + let beforeRefundBalance = await abcToken.balanceOf.call(refundAddr); + + tx = await crossChain.handlePackage(Buffer.concat([packageBytesPrefix, packageBytes]), proof, merkleHeight, refundSequence, TRANSFER_OUT_CHANNELID, {from: relayer}); + assert.equal(tx.receipt.status, true, "failed transaction"); + let nestedEventValues = (await truffleAssert.createTransactionResult(tokenHub, tx.tx)).logs[0].args; + assert.equal(nestedEventValues[0].toString().toLowerCase(), abcToken.address.toLowerCase(), "wrong refund contract address"); + assert.equal(nestedEventValues[1].toString().toLowerCase(), refundAddr.toLowerCase(), "wrong refund address"); + + let afterRefundBalance = await abcToken.balanceOf.call(refundAddr); + assert.equal(afterRefundBalance.sub(beforeRefundBalance).eq(web3.utils.toBN(1e18)), true, "wrong balance"); + + // transferOut should be failed + const sender = accounts[2]; + timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 150; // expire at two minutes later + const recipient = "0xd719dDfA57bb1489A08DF33BDE4D5BA0A9998C60"; + const amount = web3.utils.toBN(1e11); + const relayFee = web3.utils.toBN(2e16); + await abcToken.approve(tokenHub.address, amount, {from: sender}); + try { + await tokenHub.transferOut(abcToken.address, recipient, amount, expireTime, {from: sender, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("the contract has not been bound to any bep2 token")); + } + }); + it('bind and transfer miniToken', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const owner = accounts[0]; + const relayer = accounts[1]; + + const bindPackage = buildBindPackage(0, "XYZ-9C7M", miniToken.address, 1e4, 5e3, 18); + let bindSequence = await crossChain.channelReceiveSequenceMap.call(BIND_CHANNEL_ID); + + await crossChain.handlePackage(bindPackage, proof, merkleHeight, bindSequence, BIND_CHANNEL_ID, {from: relayer}); + + await miniToken.approve(tokenManager.address, web3.utils.toBN(1e18).mul(web3.utils.toBN(5e3)), {from: owner}); + let tx = await tokenManager.approveBind(miniToken.address, "XYZ-9C7M", {from: owner, value: 1e16}); + + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + decoded = verifyPrefixAndExtractSyncPackage(nestedEventValues.payload, 1e6); + assert.equal(web3.utils.bytesToHex(decoded[0]), "0x", "bind status should be successful"); + assert.equal(web3.utils.bytesToHex(decoded[1]), stringToBytes32("XYZ-9C7M"), "wrong bep2TokenSymbol"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(miniToken.address); + assert.equal(bep2Symbol, "XYZ-9C7M", "wrong symbol"); + const contractAddr = await tokenHub.getBoundContract.call("XYZ-9C7M"); + assert.equal(contractAddr, miniToken.address, "wrong contract addr"); + + let amount = web3.utils.toBN(1e18); + let recipient = accounts[3]; + await miniToken.approve(tokenHub.address, amount, {from: owner}); + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = (timestamp + 300); + const relayFee = web3.utils.toBN(1e16); + tx = await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); + truffleAssert.eventEmitted(tx, "transferOutSuccess",(ev) => { + return ev.amount.eq(web3.utils.toBN(amount)) && ev.bep20Addr.toString().toLowerCase() === miniToken.address.toLowerCase(); + }); + amount = web3.utils.toBN(5e17); + await miniToken.approve(tokenHub.address, amount, {from: owner}); + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = (timestamp + 300); + try { + await tokenHub.transferOut(miniToken.address, recipient, amount, expireTime, {from: owner, value: relayFee}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("For miniToken, the transfer amount must not be less than 1")); + } + + amount = web3.utils.toBN(1e18); + const transferInPackage = buildTransferInPackage("XYZ-9C7M", miniToken.address, amount, accounts[2], "0x35d9d41a13d6c2e01c9b1e242baf2df98e7e8c48"); + let transferInSequence = await crossChain.channelReceiveSequenceMap.call(TRANSFER_IN_CHANNELID); + + const initBalance = await miniToken.balanceOf.call(accounts[2]); + await crossChain.handlePackage(transferInPackage, proof, merkleHeight, transferInSequence, TRANSFER_IN_CHANNELID, {from: relayer}); + const newBalance = await miniToken.balanceOf.call(accounts[2]); + assert.equal(newBalance.sub(initBalance).eq(amount), true, "wrong balance"); + }); + it('enable mirror and sync channel', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const govHub = await GovHub.deployed(); + + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, CrossChain.address); + + const owner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + const tokenMgrAddrStr = TokenManager.address.toString().replace("0x", ""); + let govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + let govValue = "0x04" + "01" + tokenMgrAddrStr; + let govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x05" + "01" + tokenMgrAddrStr; + govPackageBytes = serialize("addOrUpdateChannel", govValue, CrossChain.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000056bc75e2d63100000";// 1e20; + govPackageBytes = serialize("mirrorFee", govValue, TokenManager.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + govChannelSeq = await crossChain.channelReceiveSequenceMap(GOV_CHANNEL_ID); + govValue = "0x0000000000000000000000000000000000000000000000008ac7230489e80000"; // 1e19 + govPackageBytes = serialize("syncFee", govValue, TokenManager.address); + await crossChain.handlePackage(Buffer.concat([buildSyncPackagePrefix(2e16), (govPackageBytes)]), proof, merkleHeight, govChannelSeq, GOV_CHANNEL_ID, {from: relayer}); + + const mirrorFee = await tokenManager.mirrorFee(); + assert.equal(web3.utils.toBN(1e20).eq(mirrorFee), true, "Wrong mirrorFee"); + const syncFee = await tokenManager.syncFee(); + assert.equal(web3.utils.toBN(1e19).eq(syncFee), true, "Wrong syncFee"); + + await govHub.updateContractAddr(BSCValidatorSet.address, SlashIndicator.address, SystemReward.address, MockLightClient.address, TokenHub.address, RelayerIncentivize.address, RelayerHub.address, GovHub.address, TokenManager.address, accounts[8]); + }); + it('iterate mirror failures', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(miniToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("already bound")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } + + try { + await xyzToken.setName("", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } + + try { + await xyzToken.setName("XYZ TokenXYZ TokenXYZ TokenXYZ Token", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("name length must be in [1,32]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("X", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [2,8]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZXYZXYZ", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol length must be in [2,8]")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("X-Z", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol should only contain alphabet and number")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XY_Z", {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("symbol should only contain alphabet and number")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(1, {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(86, {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large decimals")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).add(web3.utils.toBN(1e9))}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee).sub(web3.utils.toBN(1e9))}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("msg.value must be N * 1e10 and greater than sum of miniRelayFee and mirrorFee")); + } + + try { + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("mirror pending")); + const mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "", mirrorFee, 1); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + const tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + } - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(xyzToken.address); - assert.equal(bep2Symbol, "XYZ-123", "wrong symbol"); - - await xyzToken.mint(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); - - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - tx = await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(syncFee) }); - nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); - assert.equal( - decodedSyncSynPackage.syncSender.toLowerCase(), - player.toLowerCase(), - "Wrong mirror sender in sync syn package" - ); - assert.equal( - decodedSyncSynPackage.bep20Addr.toLowerCase(), - XYZToken.address.toLowerCase(), - "Wrong bep20 address in sync syn package" - ); - assert.equal( - web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), - true, - "Wrong total supply in sync syn package" - ); - assert.equal( - web3.utils.toBN(decodedSyncSynPackage.syncFee).mul(web3.utils.toBN(1e10)).eq(syncFee), - true, - "Wrong mirrorFee in sync syn package" - ); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); - - // sync fail ack package - let syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); - const syncFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); - await crossChain.handlePackage( - Buffer.concat([ - buildFailAckPackagePrefix(), - syncFailAckPackageBytes.subarray(33, syncFailAckPackageBytes.length), - ]), - proof, - merkleHeight, - syncChannelSeq, - SYNC_CHANNELID, - { from: relayer } - ); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - - // success sync and sync ack - timestamp = Math.floor(Date.now() / 1000); // counted by second - expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(syncFee) }); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); - - syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); - await crossChain.handlePackage( - buildSyncAckPackage(player, xyzToken.address, syncFee, 0), - proof, - merkleHeight, - syncChannelSeq, - SYNC_CHANNELID, - { from: relayer } - ); - tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); - assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); - }); - it("iterate sync failures", async () => { - const tokenManager = await TokenManager.deployed(); - const tokenHub = await TokenHub.deployed(); - const miniToken = await MiniToken.deployed(); - const defToken = await DEFToken.deployed(); - const xyzToken = await XYZToken.deployed(); - const crossChain = await CrossChain.deployed(); - const miniRelayFee = await tokenHub.getMiniRelayFee(); - const mirrorFee = await tokenManager.mirrorFee(); - const xyzTokenOwner = accounts[0]; - const player = accounts[2]; - - const syncFee = await tokenManager.syncFee(); - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(defToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("not bound")); - } - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(miniToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("not bound by mirror")); - } - - try { - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 100; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee), - }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); - } - - try { - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), { from: xyzTokenOwner }); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - await tokenManager.sync(xyzToken.address, expireTime, { from: player, value: miniRelayFee.add(mirrorFee) }); - assert.fail(); - } catch (error) { - assert.ok(error.toString().includes("too large total supply")); - } - - await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), { from: xyzTokenOwner }); - const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); - - let timestamp = Math.floor(Date.now() / 1000); // counted by second - let expireTime = timestamp + 300; // expire at five minutes later - let tx = await tokenManager.sync(xyzToken.address, expireTime, { - from: player, - value: miniRelayFee.add(syncFee), }); - let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; - let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); - assert.equal( - web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), - true, - "Wrong total supply in sync syn package" - ); - }); + it('successful mirror', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + await xyzToken.setName("XYZ Token", {from: xyzTokenOwner}); + await xyzToken.setSymbol("XYZ", {from: xyzTokenOwner}); + await xyzToken.setDecimals(18, {from: xyzTokenOwner}); + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const xyzTokenTotalSupply = await xyzToken.totalSupply(); + const xyzTokenDecimals = await xyzToken.decimals(); + const xyzTokenName = await xyzToken.name(); + const xyzTokenSymbol = await xyzToken.symbol(); + + const mirrorFee = await tokenManager.mirrorFee(); + const syncFee = await tokenManager.syncFee(); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + let tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + let nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedMirrorSynPackage = decodeMirrorSynPackage(nestedEventValues.payload); + assert.equal(decodedMirrorSynPackage.mirrorSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in mirror sync package"); + assert.equal(decodedMirrorSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in mirror sync package"); + assert.equal(decodedMirrorSynPackage.bep20Name, stringToBytes32(xyzTokenName), "Wrong bep20 name in mirror sync package"); // name: XYZ Token + assert.equal(decodedMirrorSynPackage.bep20Symbol, stringToBytes32(xyzTokenSymbol), "Wrong bep20 symbol in mirror sync package"); // symbol: XYZ + assert.equal(web3.utils.toBN(decodedMirrorSynPackage.mirrorFee).mul(web3.utils.toBN(1e10)).eq(mirrorFee), true, "Wrong mirrorFee in mirror sync package"); + assert.equal(web3.utils.hexToNumber(decodedMirrorSynPackage.bep20Decimals), xyzTokenDecimals, "Wrong decimals in mirror sync package"); + assert.equal(web3.utils.toBN(decodedMirrorSynPackage.bep20Supply).eq(xyzTokenTotalSupply), true, "Wrong total supply in mirror sync package"); + let tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + // mirror fail ack + let mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), mirrorFailAckPackageBytes.subarray(33, mirrorFailAckPackageBytes.length)]), proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success mirror + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.mirror(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(mirrorFee), true, "wrong tokenManager balance"); + + mirrorChannelSeq = await crossChain.channelReceiveSequenceMap(MIRROR_CHANNELID); + const mirrorAckPackageBytes = buildMirrorAckPackage(player, xyzToken.address, 18, "XYZ-123", mirrorFee, 0); + await crossChain.handlePackage(mirrorAckPackageBytes, proof, merkleHeight, mirrorChannelSeq, MIRROR_CHANNELID, {from: relayer}); + + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + const bep2Symbol = await tokenHub.getBoundBep2Symbol.call(xyzToken.address); + assert.equal(bep2Symbol, "XYZ-123", "wrong symbol"); + + + await xyzToken.mint(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal(decodedSyncSynPackage.syncSender.toLowerCase(), player.toLowerCase(), "Wrong mirror sender in sync syn package"); + assert.equal(decodedSyncSynPackage.bep20Addr.toLowerCase(), XYZToken.address.toLowerCase(), "Wrong bep20 address in sync syn package"); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.syncFee).mul(web3.utils.toBN(1e10)).eq(syncFee), true, "Wrong mirrorFee in sync syn package"); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + // sync fail ack package + let syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + const syncFailAckPackageBytes = Buffer.from(web3.utils.hexToBytes(nestedEventValues.payload)); + await crossChain.handlePackage(Buffer.concat([buildFailAckPackagePrefix(), syncFailAckPackageBytes.subarray(33, syncFailAckPackageBytes.length)]), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + + // success sync and sync ack + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(syncFee), true, "wrong tokenManager balance"); + + syncChannelSeq = await crossChain.channelReceiveSequenceMap(SYNC_CHANNELID); + await crossChain.handlePackage(buildSyncAckPackage(player, xyzToken.address, syncFee, 0), proof, merkleHeight, syncChannelSeq, SYNC_CHANNELID, {from: relayer}); + tokenManagerBalance = await web3.eth.getBalance(tokenManager.address); + assert.equal(web3.utils.toBN(tokenManagerBalance).eq(web3.utils.toBN(0)), true, "wrong tokenManager balance"); + }); + it('iterate sync failures', async () => { + const tokenManager = await TokenManager.deployed(); + const tokenHub = await TokenHub.deployed(); + const miniToken = await MiniToken.deployed(); + const defToken = await DEFToken.deployed(); + const xyzToken = await XYZToken.deployed(); + const crossChain = await CrossChain.deployed(); + const miniRelayFee = await tokenHub.getMiniRelayFee(); + const mirrorFee = await tokenManager.mirrorFee(); + const xyzTokenOwner = accounts[0]; + const relayer = accounts[1]; + const player = accounts[2]; + + const syncFee = await tokenManager.syncFee(); + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(defToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(miniToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("not bound by mirror")); + } + + try { + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 100; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, { + from: player, + value: miniRelayFee.add(syncFee) + }); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("expireTime must be two minutes later and one day earlier")); + } + + try { + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e18)), {from: xyzTokenOwner}); + + let timestamp = Math.floor(Date.now() / 1000); // counted by second + let expireTime = timestamp + 300; // expire at five minutes later + await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(mirrorFee)}); + assert.fail(); + } catch (error) { + assert.ok(error.toString().includes("too large total supply")); + } + + await xyzToken.setTotalSupply(web3.utils.toBN(1e18).mul(web3.utils.toBN(1e8)), {from: xyzTokenOwner}); + const xyzTokenNewTotalSupply = await xyzToken.totalSupply(); + + timestamp = Math.floor(Date.now() / 1000); // counted by second + expireTime = timestamp + 300; // expire at five minutes later + tx = await tokenManager.sync(xyzToken.address, expireTime, {from: player, value: miniRelayFee.add(syncFee)}); + nestedEventValues = (await truffleAssert.createTransactionResult(crossChain, tx.tx)).logs[0].args; + let decodedSyncSynPackage = decodeSyncSynPackage(nestedEventValues.payload); + assert.equal(web3.utils.toBN(decodedSyncSynPackage.bep20Supply).eq(xyzTokenNewTotalSupply), true, "Wrong total supply in sync syn package"); + }); }); diff --git a/test/ToolTest.js b/test/ToolTest.js index 674ad3c4..9bcd161e 100644 --- a/test/ToolTest.js +++ b/test/ToolTest.js @@ -1,18 +1,19 @@ const BSCValidatorSetTool = artifacts.require("tool/BSCValidatorSetTool"); -const Web3 = require("web3"); -const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); +const Web3 = require('web3'); +const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); -contract("Tool", (accounts) => { - it("tool test", async () => { +contract('Tool', (accounts) => { + it('tool test', async () => { const toolInstance = await BSCValidatorSetTool.deployed(); await toolInstance.init(); }); - - it("decode payload header", async () => { - let payload = - "0x00000000000000000000000000000000000000000000000000002386f26fc10000f85580a04142432d304237000000000000000000000000000000000000000000000000009450ee0de39df3b9c2bc8f8e33d9e4cd03dba9210c8b52b7d2dcc80cd2e40000008b31a17e847807b1bc00000012845f5efcc1"; + + it('decode payload header', async () => { + let payload = "0x00000000000000000000000000000000000000000000000000002386f26fc10000f85580a04142432d304237000000000000000000000000000000000000000000000000009450ee0de39df3b9c2bc8f8e33d9e4cd03dba9210c8b52b7d2dcc80cd2e40000008b31a17e847807b1bc00000012845f5efcc1" const toolInstance = await BSCValidatorSetTool.deployed(); let x = await toolInstance.decodePayloadHeader.call(web3.utils.hexToBytes(payload)); assert.equal(x[2].toString(), "10000000000000000"); }); + }); + diff --git a/truffle-config.js b/truffle-config.js index e2cf168c..8c5be080 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -45,8 +45,8 @@ module.exports = { development: { host: "127.0.0.1", // Localhost (default: none) port: 8545, // Standard Ethereum port (default: none) - network_id: "*" // Any network (default: none) - } + network_id: "*", // Any network (default: none) + }, // Another network with more advanced options... // advanced: { diff --git a/validators.js b/validators.js index 9573a57d..2e8e6cdc 100644 --- a/validators.js +++ b/validators.js @@ -25,7 +25,7 @@ function generateExtradata(validators, bLSPublicKeys) { function extraDataSerialize(validators, bLSPublicKeys) { let n = validators.length; let arr = []; - for (let i = 0; i < n; i++) { + for(let i = 0;i Date: Tue, 26 Apr 2022 18:00:28 +0800 Subject: [PATCH 06/48] Update BLS verify codes --- contracts/SlashIndicator.sol | 39 ++++++++++++++++++++----------- contracts/SlashIndicator.template | 39 ++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index e9b6325b..13ce44db 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -218,7 +218,8 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } require(exist, "validator not exist"); - bytes memory input; + bytes memory inputA; + bytes memory inputB; bytes memory output; // to avoid too deep stack @@ -227,29 +228,39 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumA, pre); TypesToBytes.uintToBytes(32, tarNumA, cur); - input = abi.encodePacked(pre, cur); + inputA = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); - input = abi.encodePacked(input, cur); + inputA = abi.encodePacked(inputA, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); - input = abi.encodePacked(input, cur); - input = abi.encodePacked(input, _evidence.voteA.sig); - TypesToBytes.uintToBytes(32, srcNumB, cur); - input = abi.encodePacked(input, cur); + inputA = abi.encodePacked(inputA, cur); + inputA = abi.encodePacked(inputA, _evidence.voteA.sig); + inputA = abi.encodePacked(inputA, voteAddress); + } + { + bytes memory pre = new bytes(32); + bytes memory cur = new bytes(32); + TypesToBytes.uintToBytes(32, srcNumB, pre); TypesToBytes.uintToBytes(32, tarNumB, cur); - input = abi.encodePacked(input, cur); + inputB = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); - input = abi.encodePacked(input, cur); + inputB = abi.encodePacked(inputB, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); - input = abi.encodePacked(input, cur); - input = abi.encodePacked(input, _evidence.voteB.sig); - input = abi.encodePacked(input, voteAddress); + inputB = abi.encodePacked(inputB, cur); + inputB = abi.encodePacked(inputB, _evidence.voteB.sig); + inputB = abi.encodePacked(inputB, voteAddress); } // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 assembly { - let len := mload(input) - if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { + let len := mload(inputA) + if iszero(call(not(0), 0x64, 0, inputA, len, output, 0x20)) { + revert(0, 0) + } + } + assembly { + let len := mload(inputB) + if iszero(call(not(0), 0x64, 0, inputB, len, output, 0x20)) { revert(0, 0) } } diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index c30011e1..5ad5444d 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -223,7 +223,8 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } require(exist, "validator not exist"); {% if mock %}{% else %} - bytes memory input; + bytes memory inputA; + bytes memory inputB; bytes memory output; // to avoid too deep stack @@ -232,29 +233,39 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumA, pre); TypesToBytes.uintToBytes(32, tarNumA, cur); - input = abi.encodePacked(pre, cur); + inputA = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); - input = abi.encodePacked(input, cur); + inputA = abi.encodePacked(inputA, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); - input = abi.encodePacked(input, cur); - input = abi.encodePacked(input, _evidence.voteA.sig); - TypesToBytes.uintToBytes(32, srcNumB, cur); - input = abi.encodePacked(input, cur); + inputA = abi.encodePacked(inputA, cur); + inputA = abi.encodePacked(inputA, _evidence.voteA.sig); + inputA = abi.encodePacked(inputA, voteAddress); + } + { + bytes memory pre = new bytes(32); + bytes memory cur = new bytes(32); + TypesToBytes.uintToBytes(32, srcNumB, pre); TypesToBytes.uintToBytes(32, tarNumB, cur); - input = abi.encodePacked(input, cur); + inputB = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); - input = abi.encodePacked(input, cur); + inputB = abi.encodePacked(inputB, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); - input = abi.encodePacked(input, cur); - input = abi.encodePacked(input, _evidence.voteB.sig); - input = abi.encodePacked(input, voteAddress); + inputB = abi.encodePacked(inputB, cur); + inputB = abi.encodePacked(inputB, _evidence.voteB.sig); + inputB = abi.encodePacked(inputB, voteAddress); } // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 assembly { - let len := mload(input) - if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { + let len := mload(inputA) + if iszero(call(not(0), 0x64, 0, inputA, len, output, 0x20)) { + revert(0, 0) + } + } + assembly { + let len := mload(inputB) + if iszero(call(not(0), 0x64, 0, inputB, len, output, 0x20)) { revert(0, 0) } } From c4aec0101e05627f845a717c50b2790dd520db96 Mon Sep 17 00:00:00 2001 From: Loverush Date: Thu, 28 Apr 2022 23:25:23 +0800 Subject: [PATCH 07/48] Resolve conflict --- contracts/BSCValidatorSet.sol | 135 ++++++++++++++++------------- contracts/BSCValidatorSet.template | 45 ++++++---- contracts/SlashIndicator.sol | 2 +- contracts/SlashIndicator.template | 2 +- package.json | 2 +- test/BSCValidatorSet.js | 4 +- test/Slash.js | 1 + validators.js | 6 +- 8 files changed, 112 insertions(+), 85 deletions(-) diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index e28eb662..4e09ffaf 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -33,8 +33,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint256 public constant EXPIRE_TIME_SECOND_GAP = 1000; uint256 public constant MAX_NUM_OF_VALIDATORS = 41; - bytes public constant INIT_VALIDATORSET_BYTES = hex"f87680f873f871949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164b085e6972fc98cd3c81d64d40e325acfed44365b97a7567a27939c14dbc7512ddcf54cb1284eb637cfa308ae4e00cb5588"; - + bytes public constant INIT_VALIDATORSET_BYTES = hex"f84580f842f840949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d791949fb29aac15b9a4b7f17c3385939b007540f4d79164"; uint32 public constant ERROR_UNKNOWN_PACKAGE_TYPE = 101; uint32 public constant ERROR_FAIL_CHECK_VALIDATORS = 102; uint32 public constant ERROR_LEN_OF_VAL_MISMATCH = 103; @@ -50,7 +49,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // key is the `consensusAddress` of `Validator`, // value is the index of the element in `currentValidatorSet`. - mapping(address => uint256) public currentValidatorSetMap; + mapping(address =>uint256) public currentValidatorSetMap; uint256 public numOfJailed; uint256 public constant BURN_RATIO_SCALE = 10000; @@ -70,7 +69,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica // Corresponds strictly to currentValidatorSet // validatorExtraSet[index] = the `ValidatorExtra` info of currentValidatorSet[index] ValidatorExtra[] public validatorExtraSet; - // BEP-131 candidate validator uint256 public numOfCabinets; uint256 public maxNumOfCandidates; @@ -86,7 +84,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica address consensusAddress; address payable feeAddress; address BBCFeeAddress; - uint64 votingPower; + uint64 votingPower; // only in state bool jailed; @@ -107,7 +105,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica /*********************** cross chain package **************************/ struct IbcValidatorSetPackage { - uint8 packageType; + uint8 packageType; Validator[] validatorSet; bytes[] voteAddrs; } @@ -127,7 +125,9 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica validatorExtraSet.push(validatorExtra); } } + _; + } modifier oncePerBlock() { @@ -158,12 +158,12 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event validatorExitMaintenance(address indexed validator); /*********************** init **************************/ - function init() external onlyNotInit { - (IbcValidatorSetPackage memory validatorSetPkg, bool valid) = decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); + function init() external onlyNotInit{ + (IbcValidatorSetPackage memory validatorSetPkg, bool valid)= decodeValidatorSetSynPackage(INIT_VALIDATORSET_BYTES); require(valid, "failed to parse init validatorSet"); - for (uint i = 0;i 0) { - Validator storage validator = currentValidatorSet[index - 1]; + if (index>0) { + Validator storage validator = currentValidatorSet[index-1]; if (validator.jailed) { - emit deprecatedDeposit(valAddr, value); + emit deprecatedDeposit(valAddr,value); } else { totalInComing = totalInComing.add(value); validator.incoming = validator.incoming.add(value); - emit validatorDeposit(valAddr, value); + emit validatorDeposit(valAddr,value); } } else { // get incoming from deprecated validator; - emit deprecatedDeposit(valAddr, value); + emit deprecatedDeposit(valAddr,value); } } function jailValidator(Validator memory v) internal returns (uint32) { uint256 index = currentValidatorSetMap[v.consensusAddress]; - if (index == 0 || currentValidatorSet[index - 1].jailed) { + if (index==0 || currentValidatorSet[index-1].jailed) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } uint n = currentValidatorSet.length; - bool shouldKeep = (numOfJailed >= n - 1); + bool shouldKeep = (numOfJailed >= n-1); // will not jail if it is the last valid validator if (shouldKeep) { emit validatorEmptyJailed(v.consensusAddress); return CODE_OK; } numOfJailed ++; - currentValidatorSet[index - 1].jailed = true; + currentValidatorSet[index-1].jailed = true; emit validatorJailed(v.consensusAddress); return CODE_OK; } @@ -268,8 +268,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica emit failReasonWithStr("the number of validators exceed the limit"); return ERROR_FAIL_CHECK_VALIDATORS; } - for (uint i; i < validatorSet.length; ++i) { - for (uint j; j < i; j++) { + for (uint i = 0; i < validatorSet.length; i++) { + for (uint j = 0; j < i; j++) { if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) { emit failReasonWithStr("duplicate consensus address of validatorSet"); return ERROR_FAIL_CHECK_VALIDATORS; @@ -348,7 +348,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } if (failCross) { - for (uint i; i < crossIndexes.length; ++i) { + for (uint i; i< crossIndexes.length;++i) { uint idx = crossIndexes[i]; bool success = currentValidatorSet[idx].feeAddress.send(currentValidatorSet[idx].incoming); if (success) { @@ -360,8 +360,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } // step 3: direct transfer - if (directAddrs.length > 0) { - for (uint i; i < directAddrs.length; ++i) { + if (directAddrs.length>0) { + for (uint i;i 0) { + if (address(this).balance>0) { emit systemTransfer(address(this).balance); address(uint160(SYSTEM_REWARD_ADDR)).transfer(address(this).balance); } // step 5: do update validator set state totalInComing = 0; numOfJailed = 0; - if (validatorSetTemp.length > 0) { + if (validatorSetTemp.length>0) { doUpdateState(validatorSetTemp, voteAddrsTemp); } @@ -391,15 +391,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } function shuffle(address[] memory validators, bytes[] memory voteAddrs, uint256 epochNumber, uint startIdx, uint offset, uint limit, uint modNumber) internal pure { - for (uint i; i < limit; ++i) { - uint random = uint(keccak256(abi.encodePacked(epochNumber, startIdx + i))) % modNumber; - if ((startIdx + i) != (offset + random)) { - address tmpAddr = validators[startIdx + i]; - bytes memory tmpBLS = voteAddrs[startIdx + i]; - validators[startIdx + i] = validators[offset + random]; - validators[offset + random] = tmpAddr; - voteAddrs[startIdx + i] = voteAddrs[offset + random]; - voteAddrs[offset + random] = tmpBLS; + for (uint i; i 0) { uint256 epochNumber = block.number / EPOCH; - shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); - shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, _numOfCabinets - _maxNumOfWorkingCandidates, - _maxNumOfWorkingCandidates, validators.length - _numOfCabinets + _maxNumOfWorkingCandidates); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length - _numOfCabinets+_maxNumOfWorkingCandidates); } address[] memory miningValidators = new address[](_numOfCabinets); bytes[] memory miningVoteAddrs = new bytes[](_numOfCabinets); - for (uint i; i < _numOfCabinets; ++i) { + for (uint i; i<_numOfCabinets; ++i) { miningValidators[i] = validators[i]; miningVoteAddrs[i] = voteAddrs[i]; } return (miningValidators, miningVoteAddrs); } - function getValidators() public view returns (address[] memory) { + function getValidators() public view returns(address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; for (uint i; i 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; + if (workingValidatorCount > _numOfCabinets) { + workingValidatorCount = _numOfCabinets; + } + if (workingValidatorCount == 0) { + workingValidatorCount = 1; + } + } /*********************** For slash **************************/ function misdemeanor(address validator) external onlySlash initValidatorExtraSet override { uint256 validatorIndex = _misdemeanor(validator); @@ -570,7 +580,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - function felony(address validator) external onlySlash initValidatorExtraSet override { + function felony(address validator)external onlySlash initValidatorExtraSet override{ uint256 index = currentValidatorSetMap[validator]; if (index <= 0) { return; @@ -638,7 +648,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } /*********************** Param update ********************************/ - function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov { + function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov{ if (Memory.compareStrings(key, "expireTimeSecondGap")) { require(value.length == 32, "length of expireTimeSecondGap mismatch"); uint256 newExpireTimeSecondGap = BytesToTypes.bytesToUint256(32, value); @@ -704,14 +714,14 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } if (n>m) { - for (uint i = m; i < n; i++) { + for (uint i = m; i < n; ++i) { currentValidatorSet.pop(); validatorExtraSet.pop(); } } - uint k = n < m ? n : m; + uint k = n < m ? n:m; for (uint i; i < k; ++i) { - currentValidatorSetMap[validatorSet[i].consensusAddress] = i + 1; + currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; currentValidatorSet[i] = validatorSet[i]; validatorExtraSet[i].voteAddress = voteAddrs[i]; validatorExtraSet[i].isMaintaining = false; @@ -719,27 +729,32 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } if (m>n) { ValidatorExtra memory _validatorExtra; - for (uint i = n; i < m; ++i) { + for (uint i = n; i < m; i++) { _validatorExtra.voteAddress = voteAddrs[i]; currentValidatorSet.push(validatorSet[i]); validatorExtraSet.push(_validatorExtra); - currentValidatorSetMap[validatorSet[i].consensusAddress] = i + 1; + currentValidatorSetMap[validatorSet[i].consensusAddress] = i+1; } } // make sure all new validators are cleared maintainInfo // should not happen, still protect numOfMaintaining = 0; + n = currentValidatorSet.length; + for (uint i; i < n; ++i) { + validatorExtraSet[i].isMaintaining = false; + validatorExtraSet[i].enterMaintenanceHeight = 0; + } } - function getVoteAddresses(uint length) internal view returns (bytes[] memory) { + function getVoteAddresses(uint length) internal view returns(bytes[] memory) { uint n = currentValidatorSet.length; bytes[] memory voteAddrs = new bytes[](length); if (validatorExtraSet.length != n) { return voteAddrs; } uint index = 0; - for (uint i = 0; i < n; i++) { + for (uint i; i 0) { uint256 epochNumber = block.number / EPOCH; - shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); - shuffle(validators, voteAddrs, epochNumber, _numOfCabinets - _maxNumOfWorkingCandidates, _numOfCabinets - _maxNumOfWorkingCandidates, - _maxNumOfWorkingCandidates, validators.length - _numOfCabinets + _maxNumOfWorkingCandidates); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, 0, _maxNumOfWorkingCandidates, _numOfCabinets); + shuffle(validators, voteAddrs, epochNumber, _numOfCabinets-_maxNumOfWorkingCandidates, _numOfCabinets-_maxNumOfWorkingCandidates, + _maxNumOfWorkingCandidates, validators.length - _numOfCabinets+_maxNumOfWorkingCandidates); } address[] memory miningValidators = new address[](_numOfCabinets); bytes[] memory miningVoteAddrs = new bytes[](_numOfCabinets); @@ -465,7 +467,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica return (miningValidators, miningVoteAddrs); } - function getValidators() public view returns (address[] memory) { + function getValidators() public view returns(address[] memory) { uint n = currentValidatorSet.length; uint valid = 0; for (uint i; i 0 ? numOfCabinets : INIT_NUM_OF_CABINETS; + if (workingValidatorCount > _numOfCabinets) { + workingValidatorCount = _numOfCabinets; + } + if (workingValidatorCount == 0) { + workingValidatorCount = 1; + } + } /*********************** For slash **************************/ function misdemeanor(address validator) external onlySlash initValidatorExtraSet override { uint256 validatorIndex = _misdemeanor(validator); @@ -698,7 +710,6 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica uint m = validatorSet.length; for (uint i; i { } miningValidators = (await validatorSetInstance.getMiningValidators.call())["0"]; - let exceptValues = validators.slice(0, numOfCabinets); - let outValidator = miningValidators.filter((addr) => { + let exceptValues = validators.slice(0,numOfCabinets); + let outValidator = miningValidators.filter((addr)=>{ return !exceptValues.includes(addr); }); // TODO, this is not always true, but as the epoch number is fixed during UT, the result is fixed. diff --git a/test/Slash.js b/test/Slash.js index ade40d71..1c17d434 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -333,6 +333,7 @@ contract('Clean SlashIndicator', (accounts) => { assert.equal(count, 1); } } + }); }); diff --git a/validators.js b/validators.js index 2e8e6cdc..cfe30890 100644 --- a/validators.js +++ b/validators.js @@ -16,10 +16,10 @@ const bLSPublicKeys = [ // =============== Do not edit below ==== function generateExtradata(validators, bLSPublicKeys) { - let extraVanity = Buffer.alloc(32); + let extraVanity =Buffer.alloc(32); let validatorsBytes = extraDataSerialize(validators, bLSPublicKeys); - let extraSeal = Buffer.alloc(65); - return Buffer.concat([extraVanity, validatorsBytes, extraSeal]); + let extraSeal =Buffer.alloc(65); + return Buffer.concat([extraVanity,validatorsBytes,extraSeal]); } function extraDataSerialize(validators, bLSPublicKeys) { From dd58d05e1ec83c3496a6ca6e299eb63e66fa81b8 Mon Sep 17 00:00:00 2001 From: Loverush Date: Fri, 29 Apr 2022 10:49:29 +0800 Subject: [PATCH 08/48] Fix too deep stack issue --- contracts/SlashIndicator.sol | 31 +++++++++++++++---------------- contracts/SlashIndicator.template | 31 +++++++++++++++---------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 6579641b..0d23d5e3 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -218,8 +218,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } require(exist, "validator not exist"); - bytes memory inputA; - bytes memory inputB; + bytes memory input; bytes memory output; // to avoid too deep stack @@ -228,39 +227,39 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumA, pre); TypesToBytes.uintToBytes(32, tarNumA, cur); - inputA = abi.encodePacked(pre, cur); + input = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); - inputA = abi.encodePacked(inputA, cur); + input = abi.encodePacked(input, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); - inputA = abi.encodePacked(inputA, cur); - inputA = abi.encodePacked(inputA, _evidence.voteA.sig); - inputA = abi.encodePacked(inputA, voteAddress); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteA.sig); + input = abi.encodePacked(input, voteAddress); } { bytes memory pre = new bytes(32); bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumB, pre); TypesToBytes.uintToBytes(32, tarNumB, cur); - inputB = abi.encodePacked(pre, cur); + input = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); - inputB = abi.encodePacked(inputB, cur); + input = abi.encodePacked(input, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); - inputB = abi.encodePacked(inputB, cur); - inputB = abi.encodePacked(inputB, _evidence.voteB.sig); - inputB = abi.encodePacked(inputB, voteAddress); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteB.sig); + input = abi.encodePacked(input, voteAddress); } // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 assembly { - let len := mload(inputA) - if iszero(call(not(0), 0x64, 0, inputA, len, output, 0x20)) { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { revert(0, 0) } } assembly { - let len := mload(inputB) - if iszero(call(not(0), 0x64, 0, inputB, len, output, 0x20)) { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { revert(0, 0) } } diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index 31114b95..0ab57f34 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -223,8 +223,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } require(exist, "validator not exist"); {% if mock %}{% else %} - bytes memory inputA; - bytes memory inputB; + bytes memory input; bytes memory output; // to avoid too deep stack @@ -233,39 +232,39 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumA, pre); TypesToBytes.uintToBytes(32, tarNumA, cur); - inputA = abi.encodePacked(pre, cur); + input = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.srcHash, cur); - inputA = abi.encodePacked(inputA, cur); + input = abi.encodePacked(input, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); - inputA = abi.encodePacked(inputA, cur); - inputA = abi.encodePacked(inputA, _evidence.voteA.sig); - inputA = abi.encodePacked(inputA, voteAddress); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteA.sig); + input = abi.encodePacked(input, voteAddress); } { bytes memory pre = new bytes(32); bytes memory cur = new bytes(32); TypesToBytes.uintToBytes(32, srcNumB, pre); TypesToBytes.uintToBytes(32, tarNumB, cur); - inputB = abi.encodePacked(pre, cur); + input = abi.encodePacked(pre, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.srcHash, cur); - inputB = abi.encodePacked(inputB, cur); + input = abi.encodePacked(input, cur); TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); - inputB = abi.encodePacked(inputB, cur); - inputB = abi.encodePacked(inputB, _evidence.voteB.sig); - inputB = abi.encodePacked(inputB, voteAddress); + input = abi.encodePacked(input, cur); + input = abi.encodePacked(input, _evidence.voteB.sig); + input = abi.encodePacked(input, voteAddress); } // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 assembly { - let len := mload(inputA) - if iszero(call(not(0), 0x64, 0, inputA, len, output, 0x20)) { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { revert(0, 0) } } assembly { - let len := mload(inputB) - if iszero(call(not(0), 0x64, 0, inputB, len, output, 0x20)) { + let len := mload(input) + if iszero(call(not(0), 0x64, 0, input, len, output, 0x20)) { revert(0, 0) } } From 6da864d61656a69b573c74a62c9f872f6d1c14fd Mon Sep 17 00:00:00 2001 From: Loverush Date: Fri, 29 Apr 2022 11:43:59 +0800 Subject: [PATCH 09/48] Fix review comments --- contracts/SlashIndicator.sol | 6 ++--- contracts/SlashIndicator.template | 6 ++--- test/GovHub.js | 1 - test/Slash.js | 45 ++++++++++++++++++++----------- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 0d23d5e3..3cb34cbf 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -194,14 +194,14 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication uint256 srcNumB = _evidence.voteB.srcNum; uint256 tarNumB = _evidence.voteB.tarNum; + // Basic check + require(srcNumA+256 > block.number && srcNumB+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); // Vote rules check - if (!((srcNumA < srcNumB && srcNumB < tarNumB && tarNumB < tarNumA) || - (srcNumB < srcNumA && srcNumA < tarNumA && tarNumA < tarNumB)) && - !(tarNumA == tarNumB)) { + if (!((srcNumA block.number && srcNumB+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); // Vote rules check - if (!((srcNumA < srcNumB && srcNumB < tarNumB && tarNumB < tarNumA) || - (srcNumB < srcNumA && srcNumA < tarNumA && tarNumA < tarNumB)) && - !(tarNumA == tarNumB)) { + if (!((srcNumA { assert.equal(batchSizeForOracle, 100, "value not equal"); }); - it('Gov SlashIndicator', async () => { const govHubInstance = await GovHub.deployed(); const slashIndicator =await SlashIndicator.deployed(); diff --git a/test/Slash.js b/test/Slash.js index 1c17d434..a21eb443 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -62,7 +62,6 @@ contract('SlashIndicator: isOperator works', (accounts) => { }); }); - contract('SlashIndicator: catch emit event', (accounts) => { it('catch emit event', async () => { const slashInstance = await SlashIndicator.deployed(); @@ -80,7 +79,6 @@ contract('SlashIndicator: catch emit event', (accounts) => { }); }); - contract('SlashIndicator', (accounts) => { it('trigger misdemeanor', async () => { const slashInstance = await SlashIndicator.deployed(); @@ -482,10 +480,33 @@ contract("finality slash SlashIndicator", (accounts) => { valAddr: accounts[0], }; + evidence.voteA.srcNum = currentNumber - 257; + try { + await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("too old block involved in the evidence"), + "the vote must happen recently" + ); + } + + evidence.voteA.srcNum = currentNumber - 20; + evidence.voteB = voteDataA; + try { + await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); + assert.fail(); + } catch (error) { + assert.ok( + error.toString().includes("two identical votes"), + "two votes must be different" + ); + } + + evidence.voteB = voteDataB; evidence.voteA.tarNum = evidence.voteA.srcNum - 1; - let evidence1 = evidence; try { - await slashInstance.submitFinalityViolationEvidence(evidence1, { from: relayerAccount }); + await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); } catch (error) { assert.ok( @@ -496,28 +517,20 @@ contract("finality slash SlashIndicator", (accounts) => { evidence.voteA.tarNum = currentNumber - 10; evidence.voteB.tarNum = currentNumber - 8; - let evidence2 = evidence; try { - await slashInstance.submitFinalityViolationEvidence(evidence2, { from: relayerAccount }); + await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); } catch (error) { - assert.ok( - error.toString().includes("no violation of vote rules"), - "no violation of vote rules" - ); + assert.ok(error.toString().includes("no violation of vote rules"), "no violation of vote rules"); } evidence.voteB.tarNum = currentNumber - 12; evidence.valAddr = accounts[1]; - let evidence3 = evidence; try { - await slashInstance.submitFinalityViolationEvidence(evidence3, { from: relayerAccount }); + await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); } catch (error) { - assert.ok( - error.toString().includes("validator not exist"), - "validator not exist" - ); + assert.ok(error.toString().includes("validator not exist"), "validator not exist"); } }); }); From ce0bde1098fc57e7fe4179cac8540b37e22ad8d3 Mon Sep 17 00:00:00 2001 From: Loverush Date: Sun, 8 May 2022 11:16:38 +0800 Subject: [PATCH 10/48] Update slash evidence vote addr field --- contracts/SlashIndicator.sol | 22 ++++++++++-------- contracts/SlashIndicator.template | 22 ++++++++++-------- test/Slash.js | 38 +++++++++++++++++++++++++++---- 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 3cb34cbf..85e80d3c 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2; import "./System.sol"; import "./lib/BytesToTypes.sol"; import "./lib/TypesToBytes.sol"; +import "./lib/BytesLib.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; import "./interface/IApplication.sol"; @@ -63,7 +64,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication struct FinalityEvidence { VoteData voteA; VoteData voteB; - address valAddr; + bytes voteAddr; } modifier oncePerBlock() { @@ -207,12 +208,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); - bytes memory voteAddress; + address valAddr; + bytes memory voteAddr = _evidence.voteAddr; bool exist; - for (uint i = 0; i < vals.length; i++) { - if (vals[i] == _evidence.valAddr) { + for (uint i; i < voteAddrs.length; ++i) { + if (BytesLib.equal(voteAddrs[i], voteAddr)) { exist = true; - voteAddress = voteAddrs[i]; + valAddr = vals[i]; break; } } @@ -233,7 +235,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); input = abi.encodePacked(input, cur); input = abi.encodePacked(input, _evidence.voteA.sig); - input = abi.encodePacked(input, voteAddress); + input = abi.encodePacked(input, voteAddr); } { bytes memory pre = new bytes(32); @@ -246,7 +248,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); input = abi.encodePacked(input, cur); input = abi.encodePacked(input, _evidence.voteB.sig); - input = abi.encodePacked(input, voteAddress); + input = abi.encodePacked(input, voteAddr); } // call the precompiled contract to verify the BLS signature @@ -266,9 +268,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication uint256 amount = (address(SYSTEM_REWARD_ADDR).balance * finalitySlashRewardRatio) / 100; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, amount); - IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); - ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); - emit validatorSlashed(_evidence.valAddr); + IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(valAddr); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(valAddr), 0); + emit validatorSlashed(valAddr); } function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index fea5ff7a..268df593 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2; import "./System.sol"; import "./lib/BytesToTypes.sol"; import "./lib/TypesToBytes.sol"; +import "./lib/BytesLib.sol"; import "./lib/Memory.sol"; import "./interface/ISlashIndicator.sol"; import "./interface/IApplication.sol"; @@ -63,7 +64,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication struct FinalityEvidence { VoteData voteA; VoteData voteB; - address valAddr; + bytes voteAddr; } modifier oncePerBlock() { @@ -212,12 +213,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); - bytes memory voteAddress; + address valAddr; + bytes memory voteAddr = _evidence.voteAddr; bool exist; - for (uint i = 0; i < vals.length; i++) { - if (vals[i] == _evidence.valAddr) { + for (uint i; i < voteAddrs.length; ++i) { + if (BytesLib.equal(voteAddrs[i], voteAddr)) { exist = true; - voteAddress = voteAddrs[i]; + valAddr = vals[i]; break; } } @@ -238,7 +240,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication TypesToBytes.bytes32ToBytes(32, _evidence.voteA.tarHash, cur); input = abi.encodePacked(input, cur); input = abi.encodePacked(input, _evidence.voteA.sig); - input = abi.encodePacked(input, voteAddress); + input = abi.encodePacked(input, voteAddr); } { bytes memory pre = new bytes(32); @@ -251,7 +253,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication TypesToBytes.bytes32ToBytes(32, _evidence.voteB.tarHash, cur); input = abi.encodePacked(input, cur); input = abi.encodePacked(input, _evidence.voteB.sig); - input = abi.encodePacked(input, voteAddress); + input = abi.encodePacked(input, voteAddr); } // call the precompiled contract to verify the BLS signature @@ -271,9 +273,9 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication {% endif %} uint256 amount = (address(SYSTEM_REWARD_ADDR).balance * finalitySlashRewardRatio) / 100; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, amount); - IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(_evidence.valAddr); - ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(_evidence.valAddr), 0); - emit validatorSlashed(_evidence.valAddr); + IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).felony(valAddr); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(valAddr), 0); + emit validatorSlashed(valAddr); } function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { diff --git a/test/Slash.js b/test/Slash.js index a21eb443..186f68aa 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -339,11 +339,23 @@ contract("finality slash SlashIndicator", (accounts) => { it("valid finality evidence: same target block", async () => { const slashInstance = await SlashIndicator.deployed(); const systemRewardInstance = await SystemReward.deployed(); + const validatorSetInstance = await BSCValidatorSet.deployed(); let relayerAccount = accounts[8]; await systemRewardInstance.send(web3.utils.toBN(1e18), { from: accounts[1] }); await systemRewardInstance.addOperator(slashInstance.address); + // add vote address + let packageBytes = newValidatorUpdateRlpEncode( + [accounts[0]], + [accounts[0]], + [accounts[0]], + [Buffer.from("voteAddr")] + ); + await validatorSetInstance.handleSynPackage(STAKE_CHANNEL_ID, packageBytes, { + from: relayerAccount, + }); + let currentNumber = await web3.eth.getBlockNumber(); let srcNumA = currentNumber - 20; let tarNumA = currentNumber - 10; @@ -377,7 +389,7 @@ contract("finality slash SlashIndicator", (accounts) => { let evidence = { voteA: voteDataA, voteB: voteDataB, - valAddr: accounts[0], + voteAddr: Buffer.from("voteAddr"), }; let tx = await slashInstance.submitFinalityViolationEvidence(evidence, { @@ -427,7 +439,7 @@ contract("finality slash SlashIndicator", (accounts) => { let evidence = { voteA: voteDataA, voteB: voteDataB, - valAddr: accounts[0], + voteAddr: Buffer.from("voteAddr"), }; let tx = await slashInstance.submitFinalityViolationEvidence(evidence, { @@ -477,7 +489,7 @@ contract("finality slash SlashIndicator", (accounts) => { let evidence = { voteA: voteDataA, voteB: voteDataB, - valAddr: accounts[0], + voteAddr: Buffer.from("voteAddr"), }; evidence.voteA.srcNum = currentNumber - 257; @@ -525,7 +537,7 @@ contract("finality slash SlashIndicator", (accounts) => { } evidence.voteB.tarNum = currentNumber - 12; - evidence.valAddr = accounts[1]; + evidence.voteAddr = Buffer.from("wrongVoteAddr"); try { await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); @@ -550,4 +562,22 @@ function validatorUpdateRlpEncode(consensusAddrList,feeAddrList, bscFeeAddrList) } pkg.push(vals); return RLP.encode(pkg) +} + +function newValidatorUpdateRlpEncode(consensusAddrList, feeAddrList, bscFeeAddrList, voteAddrList) { + let pkg = []; + pkg.push(0x00); + let n = consensusAddrList.length; + let vals = []; + for (let i = 0; i < n; i++) { + vals.push([ + consensusAddrList[i].toString(), + feeAddrList[i].toString(), + bscFeeAddrList[i].toString(), + 0x0000000000000064, + voteAddrList[i], + ]); + } + pkg.push(vals); + return RLP.encode(pkg); } \ No newline at end of file From 4b503fd4d49d1e1eee669721a32cc52a27c73b58 Mon Sep 17 00:00:00 2001 From: Loverush Date: Thu, 19 May 2022 16:43:36 +0800 Subject: [PATCH 11/48] Update contracts' abi --- abi/bscvalidatorset.abi | 13 +++++++++++++ abi/slashindicator.abi | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/abi/bscvalidatorset.abi b/abi/bscvalidatorset.abi index e1be421e..1558f9ec 100644 --- a/abi/bscvalidatorset.abi +++ b/abi/bscvalidatorset.abi @@ -1275,6 +1275,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "getWorkingValidatorCount", + "outputs": [ + { + "internalType": "uint256", + "name": "workingValidatorCount", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { diff --git a/abi/slashindicator.abi b/abi/slashindicator.abi index 01450fad..9c2f4e6a 100644 --- a/abi/slashindicator.abi +++ b/abi/slashindicator.abi @@ -650,9 +650,9 @@ "type": "tuple" }, { - "internalType": "address", - "name": "valAddr", - "type": "address" + "internalType": "bytes", + "name": "voteAddr", + "type": "bytes" } ], "internalType": "struct SlashIndicator.FinalityEvidence", From 4762d8c3003a7f179063a9e81d4c29b09daa4dcc Mon Sep 17 00:00:00 2001 From: Loverush Date: Thu, 19 May 2022 21:22:26 +0800 Subject: [PATCH 12/48] Update finality reward related events --- abi/bscvalidatorset.abi | 38 ++++++++++++++++++++++++++++++ contracts/BSCValidatorSet.sol | 8 ++++--- contracts/BSCValidatorSet.template | 8 ++++--- test/BSCValidatorSet.js | 6 ++--- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/abi/bscvalidatorset.abi b/abi/bscvalidatorset.abi index 1558f9ec..e4696e46 100644 --- a/abi/bscvalidatorset.abi +++ b/abi/bscvalidatorset.abi @@ -69,6 +69,25 @@ "name": "deprecatedDeposit", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "deprecatedFinalityRewardDeposit", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -133,6 +152,25 @@ "name": "feeBurned", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "finalityRewardDeposit", + "type": "event" + }, { "anonymous": false, "inputs": [ diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index 4e09ffaf..ee5fc977 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -156,6 +156,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event feeBurned(uint256 amount); event validatorEnterMaintenance(address indexed validator); event validatorExitMaintenance(address indexed validator); + event finalityRewardDeposit(address indexed validator, uint256 amount); + event deprecatedFinalityRewardDeposit(address indexed validator, uint256 amount); /*********************** init **************************/ function init() external onlyNotInit{ @@ -548,15 +550,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (index > 0) { Validator storage validator = currentValidatorSet[index - 1]; if (validator.jailed) { - emit deprecatedDeposit(valAddr, value); + emit deprecatedFinalityRewardDeposit(valAddr, value); } else { totalInComing = totalInComing.add(value); validator.incoming = validator.incoming.add(value); - emit validatorDeposit(valAddr, value); + emit finalityRewardDeposit(valAddr, value); } } else { // get incoming from deprecated validator; - emit deprecatedDeposit(valAddr, value); + emit deprecatedFinalityRewardDeposit(valAddr, value); } } diff --git a/contracts/BSCValidatorSet.template b/contracts/BSCValidatorSet.template index e3830a05..6c94978f 100644 --- a/contracts/BSCValidatorSet.template +++ b/contracts/BSCValidatorSet.template @@ -157,6 +157,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica event feeBurned(uint256 amount); event validatorEnterMaintenance(address indexed validator); event validatorExitMaintenance(address indexed validator); + event finalityRewardDeposit(address indexed validator, uint256 amount); + event deprecatedFinalityRewardDeposit(address indexed validator, uint256 amount); /*********************** init **************************/ function init() external onlyNotInit{ @@ -549,15 +551,15 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica if (index > 0) { Validator storage validator = currentValidatorSet[index - 1]; if (validator.jailed) { - emit deprecatedDeposit(valAddr, value); + emit deprecatedFinalityRewardDeposit(valAddr, value); } else { totalInComing = totalInComing.add(value); validator.incoming = validator.incoming.add(value); - emit validatorDeposit(valAddr, value); + emit finalityRewardDeposit(valAddr, value); } } else { // get incoming from deprecated validator; - emit deprecatedDeposit(valAddr, value); + emit deprecatedFinalityRewardDeposit(valAddr, value); } } diff --git a/test/BSCValidatorSet.js b/test/BSCValidatorSet.js index ca437990..93aa1149 100644 --- a/test/BSCValidatorSet.js +++ b/test/BSCValidatorSet.js @@ -145,12 +145,12 @@ contract("BSCValidatorSet", (accounts) => { }); for (let i = 0; i < 10; i++) { - truffleAssert.eventEmitted(tx, "validatorDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "finalityRewardDeposit", (ev) => { return ev.validator === valAddrs[i] && ev.amount.toNumber() === 5e7; }); } for (let i = 0; i < 10; i++) { - truffleAssert.eventEmitted(tx, "deprecatedDeposit", (ev) => { + truffleAssert.eventEmitted(tx, "deprecatedFinalityRewardDeposit", (ev) => { return ev.validator === valAddrs[i + 10] && ev.amount.toNumber() === 5e7; }); } @@ -319,7 +319,6 @@ contract('BSCValidatorSet', (accounts) => { }); }); - contract('BSCValidatorSet', (accounts) => { it('failed to update', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); @@ -442,7 +441,6 @@ contract('BSCValidatorSet', (accounts) => { }); }); - contract('BSCValidatorSet', (accounts) => { it('complicate distribute when one validar fee addr is contract', async () => { const validatorSetInstance = await BSCValidatorSet.deployed(); From 7148821e5b5d9fa74f156976acaa85d9f2aad74d Mon Sep 17 00:00:00 2001 From: Loverush Date: Fri, 10 Jun 2022 00:59:24 +0800 Subject: [PATCH 13/48] Update precompile contract related codes in SlashIndicator.sol --- contracts/BSCValidatorSet.sol | 2 +- contracts/BSCValidatorSet.template | 2 +- contracts/SlashIndicator.sol | 80 ++++++++++++------------------ contracts/SlashIndicator.template | 80 ++++++++++++------------------ 4 files changed, 66 insertions(+), 98 deletions(-) diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index ee5fc977..4578881e 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -697,7 +697,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (Memory.compareStrings(key, "finalityRewardRatio")) { require(value.length == 32, "length of finalityRewardRatio mismatch"); uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); - require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finalityRewardRatio is out of range"); finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); diff --git a/contracts/BSCValidatorSet.template b/contracts/BSCValidatorSet.template index 6c94978f..9380d517 100644 --- a/contracts/BSCValidatorSet.template +++ b/contracts/BSCValidatorSet.template @@ -698,7 +698,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } else if (Memory.compareStrings(key, "finalityRewardRatio")) { require(value.length == 32, "length of finalityRewardRatio mismatch"); uint256 newFinalityRewardRatio = BytesToTypes.bytesToUint256(32, value); - require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finality reward ratio out of range!"); + require(newFinalityRewardRatio >= 1 && newFinalityRewardRatio < 100, "the finalityRewardRatio is out of range"); finalityRewardRatio = newFinalityRewardRatio; } else { require(false, "unknown param"); diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 85e80d3c..46b72db3 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -190,19 +190,15 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication if (finalitySlashRewardRatio == 0) { finalitySlashRewardRatio = INIT_FINALITY_SLASH_REWARD_RATIO; } - uint256 srcNumA = _evidence.voteA.srcNum; - uint256 tarNumA = _evidence.voteA.tarNum; - uint256 srcNumB = _evidence.voteB.srcNum; - uint256 tarNumB = _evidence.voteB.tarNum; // Basic check - require(srcNumA+256 > block.number && srcNumB+256 > block.number, "too old block involved in the evidence"); + require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); - require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); + require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check - if (!((srcNumA block.number && srcNumB+256 > block.number, "too old block involved in the evidence"); + require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); - require(srcNumA < tarNumA && srcNumB < tarNumB, "source number bigger than target number"); + require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check - if (!((srcNumA Date: Fri, 10 Jun 2022 15:18:55 +0800 Subject: [PATCH 14/48] Fix review comments --- contracts/SlashIndicator.sol | 32 ++++++++++++++++--------------- contracts/SlashIndicator.template | 32 ++++++++++++++++--------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 46b72db3..54d1c379 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -192,15 +192,17 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } // Basic check - require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); + require(_evidence.voteA.srcNum+256 > block.number && + _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); - require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); + require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && + _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check - if (!((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum)) && _evidence.voteA.tarNum != _evidence.voteB.tarNum) { - revert(string(abi.encodePacked("no violation of vote rules"))); - } + require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || + (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || + _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); @@ -229,22 +231,22 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication function verifyBLSSignature(uint256 srcNum, bytes32 srcHash, uint256 tarNum, bytes32 tarHash, bytes memory sig, bytes memory voteAddr) internal view returns(bool) { bytes memory input; - bytes memory output = new bytes(1); - bytes memory pre = new bytes(32); - bytes memory cur = new bytes(32); - TypesToBytes.uintToBytes(32, srcNum, pre); - TypesToBytes.uintToBytes(32, tarNum, cur); - input = abi.encodePacked(pre, cur); - TypesToBytes.bytes32ToBytes(32, srcHash, cur); - input = abi.encodePacked(input, cur); - TypesToBytes.bytes32ToBytes(32, tarHash, cur); - input = abi.encodePacked(input, cur); + bytes memory _preBytes = new bytes(32); + bytes memory _postBytes = new bytes(32); + TypesToBytes.uintToBytes(32, srcNum, _preBytes); + TypesToBytes.uintToBytes(32, tarNum, _postBytes); + input = abi.encodePacked(_preBytes, _postBytes); + TypesToBytes.bytes32ToBytes(32, srcHash, _postBytes); + input = abi.encodePacked(input, _postBytes); + TypesToBytes.bytes32ToBytes(32, tarHash, _postBytes); + input = abi.encodePacked(input, _postBytes); input = abi.encodePacked(input, sig); input = abi.encodePacked(input, voteAddr); // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 + bytes memory output = new bytes(1); assembly { let len := mload(input) if iszero(staticcall(not(0), 0x64, add(input, 0x20), len, add(output, 0x20), 0x01)) { diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index 7410eaad..ce2d4bed 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -197,15 +197,17 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } // Basic check - require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); + require(_evidence.voteA.srcNum+256 > block.number && + _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); - require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); + require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && + _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check - if (!((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum)) && _evidence.voteA.tarNum != _evidence.voteB.tarNum) { - revert(string(abi.encodePacked("no violation of vote rules"))); - } + require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || + (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || + _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); @@ -234,22 +236,22 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication function verifyBLSSignature(uint256 srcNum, bytes32 srcHash, uint256 tarNum, bytes32 tarHash, bytes memory sig, bytes memory voteAddr) internal view returns(bool) { bytes memory input; - bytes memory output = new bytes(1); - bytes memory pre = new bytes(32); - bytes memory cur = new bytes(32); - TypesToBytes.uintToBytes(32, srcNum, pre); - TypesToBytes.uintToBytes(32, tarNum, cur); - input = abi.encodePacked(pre, cur); - TypesToBytes.bytes32ToBytes(32, srcHash, cur); - input = abi.encodePacked(input, cur); - TypesToBytes.bytes32ToBytes(32, tarHash, cur); - input = abi.encodePacked(input, cur); + bytes memory _preBytes = new bytes(32); + bytes memory _postBytes = new bytes(32); + TypesToBytes.uintToBytes(32, srcNum, _preBytes); + TypesToBytes.uintToBytes(32, tarNum, _postBytes); + input = abi.encodePacked(_preBytes, _postBytes); + TypesToBytes.bytes32ToBytes(32, srcHash, _postBytes); + input = abi.encodePacked(input, _postBytes); + TypesToBytes.bytes32ToBytes(32, tarHash, _postBytes); + input = abi.encodePacked(input, _postBytes); input = abi.encodePacked(input, sig); input = abi.encodePacked(input, voteAddr); // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 + bytes memory output = new bytes(1); assembly { let len := mload(input) if iszero(staticcall(not(0), 0x64, add(input, 0x20), len, add(output, 0x20), 0x01)) { From 8704b59f425911a90f3e484defc109c5a4606582 Mon Sep 17 00:00:00 2001 From: Loverush Date: Fri, 10 Jun 2022 16:56:46 +0800 Subject: [PATCH 15/48] Fix format issues --- contracts/SlashIndicator.sol | 6 +++--- contracts/SlashIndicator.template | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 54d1c379..598d1601 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -195,14 +195,14 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && - _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); + _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || - (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || - _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); + (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || + _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); diff --git a/contracts/SlashIndicator.template b/contracts/SlashIndicator.template index ce2d4bed..05b9ea14 100644 --- a/contracts/SlashIndicator.template +++ b/contracts/SlashIndicator.template @@ -200,14 +200,14 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication require(_evidence.voteA.srcNum+256 > block.number && _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && - _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); + _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); // Vote rules check require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || - (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || - _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); + (_evidence.voteB.srcNum<_evidence.voteA.srcNum && _evidence.voteA.tarNum<_evidence.voteB.tarNum) || + _evidence.voteA.tarNum == _evidence.voteB.tarNum, "no violation of vote rules"); // BLS verification (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); From e2b895b8a25e39465b1ef47deee39c912556ed1d Mon Sep 17 00:00:00 2001 From: Loverush Date: Fri, 10 Jun 2022 22:02:02 +0800 Subject: [PATCH 16/48] Update for bytes concat --- contracts/SlashIndicator.sol | 46 +++++++++++++++++-------------- contracts/SlashIndicator.template | 46 +++++++++++++++++-------------- 2 files changed, 52 insertions(+), 40 deletions(-) diff --git a/contracts/SlashIndicator.sol b/contracts/SlashIndicator.sol index 598d1601..a9bf3aea 100644 --- a/contracts/SlashIndicator.sol +++ b/contracts/SlashIndicator.sol @@ -186,7 +186,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit indicatorCleaned(); } - function submitFinalityViolationEvidence(FinalityEvidence calldata _evidence) external onlyInit onlyRelayer { + function submitFinalityViolationEvidence(FinalityEvidence memory _evidence) public onlyInit onlyRelayer { if (finalitySlashRewardRatio == 0) { finalitySlashRewardRatio = INIT_FINALITY_SLASH_REWARD_RATIO; } @@ -218,9 +218,8 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication } require(exist, "validator not exist"); - require(verifyBLSSignature(_evidence.voteA.srcNum, _evidence.voteA.srcHash, _evidence.voteA.tarNum, _evidence.voteA.tarHash, _evidence.voteA.sig, _evidence.voteAddr) && - verifyBLSSignature(_evidence.voteB.srcNum, _evidence.voteB.srcHash, _evidence.voteB.tarNum, _evidence.voteB.tarHash, _evidence.voteB.sig, _evidence.voteAddr), - "verify signature failed"); + require(verifyBLSSignature(_evidence.voteA, _evidence.voteAddr) && + verifyBLSSignature(_evidence.voteB, _evidence.voteAddr), "verify signature failed"); uint256 amount = (address(SYSTEM_REWARD_ADDR).balance * finalitySlashRewardRatio) / 100; ISystemReward(SYSTEM_REWARD_ADDR).claimRewards(msg.sender, amount); @@ -229,20 +228,25 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication emit validatorSlashed(valAddr); } - function verifyBLSSignature(uint256 srcNum, bytes32 srcHash, uint256 tarNum, bytes32 tarHash, bytes memory sig, bytes memory voteAddr) internal view returns(bool) { - bytes memory input; - - bytes memory _preBytes = new bytes(32); - bytes memory _postBytes = new bytes(32); - TypesToBytes.uintToBytes(32, srcNum, _preBytes); - TypesToBytes.uintToBytes(32, tarNum, _postBytes); - input = abi.encodePacked(_preBytes, _postBytes); - TypesToBytes.bytes32ToBytes(32, srcHash, _postBytes); - input = abi.encodePacked(input, _postBytes); - TypesToBytes.bytes32ToBytes(32, tarHash, _postBytes); - input = abi.encodePacked(input, _postBytes); - input = abi.encodePacked(input, sig); - input = abi.encodePacked(input, voteAddr); + function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); + } + + function verifyBLSSignature(VoteData memory vote, bytes memory voteAddr) internal returns(bool) { + + // assemble input data + bytes memory input = new bytes(272); + bytes memory _bytes = new bytes(32); + TypesToBytes.uintToBytes(32, vote.srcNum, _bytes); + bytesConcat(input, _bytes, 0, 32); + TypesToBytes.uintToBytes(32, vote.tarNum, _bytes); + bytesConcat(input, _bytes, 32, 32); + TypesToBytes.bytes32ToBytes(32, vote.srcHash, _bytes); + bytesConcat(input, _bytes, 64, 32); + TypesToBytes.bytes32ToBytes(32, vote.tarHash, _bytes); + bytesConcat(input, _bytes, 96, 32); + bytesConcat(input, vote.sig, 128, 96); + bytesConcat(input, voteAddr, 224, 48); // call the precompiled contract to verify the BLS signature // the precompiled contract's address is 0x64 @@ -259,8 +263,10 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication return true; } - function sendFelonyPackage(address validator) external override(ISlashIndicator) onlyValidatorContract onlyInit { - ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(SLASH_CHANNELID, encodeSlashPackage(validator), 0); + function bytesConcat(bytes memory data, bytes memory _bytes, uint256 index, uint256 len) internal { + for (uint i; i Date: Mon, 13 Jun 2022 08:26:30 +0500 Subject: [PATCH 17/48] Updated Links to docs.bnbchain.org (#147) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dfe2f3ca..2b20e935 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # bsc-genesis-contracts -This repo hold all the genesis contracts on Binance Smart chain. More details in [doc-site](https://github.com/binance-chain/docs-site/blob/add-bsc/docs/smart-chain/guides/concepts/system-contract.md). +This repo hold all the genesis contracts on Binance Smart chain. More details in [doc-site](https://docs.bnbchain.org/docs/learn/system-contract). ## Prepare From 19adacca288b6a4f3161659b49ad4abd5b7bfd59 Mon Sep 17 00:00:00 2001 From: Loverush Date: Wed, 27 Jul 2022 17:14:11 +0800 Subject: [PATCH 18/48] Fix some audit comments --- contracts/BSCValidatorSet.sol | 23 +++++++++++++---------- contracts/BSCValidatorSet.template | 23 +++++++++++++---------- contracts/SlashIndicator.sol | 10 ++++------ contracts/SlashIndicator.template | 10 ++++------ contracts/SystemReward.sol | 2 +- contracts/SystemReward.template | 2 +- test/Slash.js | 13 +++++-------- 7 files changed, 41 insertions(+), 42 deletions(-) diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index 4578881e..c3dd8a76 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -270,8 +270,8 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica emit failReasonWithStr("the number of validators exceed the limit"); return ERROR_FAIL_CHECK_VALIDATORS; } - for (uint i = 0; i < validatorSet.length; i++) { - for (uint j = 0; j < i; j++) { + for (uint i; i < validatorSet.length; ++i) { + for (uint j; j < i; ++j) { if (validatorSet[i].consensusAddress == validatorSet[j].consensusAddress) { emit failReasonWithStr("duplicate consensus address of validatorSet"); return ERROR_FAIL_CHECK_VALIDATORS; @@ -444,7 +444,7 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } address[] memory validators = getValidators(); - bytes[] memory voteAddrs = getVoteAddresses(validators.length); + bytes[] memory voteAddrs = getVoteAddresses(validators); if (validators.length <= _numOfCabinets) { return (validators, voteAddrs); @@ -749,17 +749,20 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica } } - function getVoteAddresses(uint length) internal view returns(bytes[] memory) { + function getVoteAddresses(address[] memory validators) internal view returns(bytes[] memory) { + // check if validatorExtraSet has been initialized uint n = currentValidatorSet.length; - bytes[] memory voteAddrs = new bytes[](length); if (validatorExtraSet.length != n) { return voteAddrs; } - uint index = 0; - for (uint i; i block.number && - _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); + _evidence.voteB.srcNum+256 > block.number, "too old block involved"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && - _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); + _evidence.voteB.srcNum < _evidence.voteB.tarNum, "srcNum bigger than tarNum"); // Vote rules check require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || @@ -208,15 +208,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); address valAddr; bytes memory voteAddr = _evidence.voteAddr; - bool exist; for (uint i; i < voteAddrs.length; ++i) { if (BytesLib.equal(voteAddrs[i], voteAddr)) { - exist = true; valAddr = vals[i]; break; } } - require(exist, "validator not exist"); + require(valAddr != address(0), "validator not exist"); require(verifyBLSSignature(_evidence.voteA, _evidence.voteAddr) && verifyBLSSignature(_evidence.voteB, _evidence.voteAddr), "verify signature failed"); @@ -263,7 +261,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication return true; } - function bytesConcat(bytes memory data, bytes memory _bytes, uint256 index, uint256 len) internal { + function bytesConcat(bytes memory data, bytes memory _bytes, uint256 index, uint256 len) internal pure { for (uint i; i block.number && - _evidence.voteB.srcNum+256 > block.number, "too old block involved in the evidence"); + _evidence.voteB.srcNum+256 > block.number, "too old block involved"); require(!(_evidence.voteA.srcHash == _evidence.voteB.srcHash && _evidence.voteA.tarHash == _evidence.voteB.tarHash), "two identical votes"); require(_evidence.voteA.srcNum < _evidence.voteA.tarNum && - _evidence.voteB.srcNum < _evidence.voteB.tarNum, "source number bigger than target number"); + _evidence.voteB.srcNum < _evidence.voteB.tarNum, "srcNum bigger than tarNum"); // Vote rules check require((_evidence.voteA.srcNum<_evidence.voteB.srcNum && _evidence.voteB.tarNum<_evidence.voteA.tarNum) || @@ -213,15 +213,13 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication (address[] memory vals, bytes[] memory voteAddrs) = IBSCValidatorSet(VALIDATOR_CONTRACT_ADDR).getLivingValidators(); address valAddr; bytes memory voteAddr = _evidence.voteAddr; - bool exist; for (uint i; i < voteAddrs.length; ++i) { if (BytesLib.equal(voteAddrs[i], voteAddr)) { - exist = true; valAddr = vals[i]; break; } } - require(exist, "validator not exist"); + require(valAddr != address(0), "validator not exist"); {% if mock %}{% else %} require(verifyBLSSignature(_evidence.voteA, _evidence.voteAddr) && verifyBLSSignature(_evidence.voteB, _evidence.voteAddr), "verify signature failed"); @@ -268,7 +266,7 @@ contract SlashIndicator is ISlashIndicator,System,IParamSubscriber, IApplication return true; } - function bytesConcat(bytes memory data, bytes memory _bytes, uint256 index, uint256 len) internal { + function bytesConcat(bytes memory data, bytes memory _bytes, uint256 index, uint256 len) internal pure { for (uint i; i MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount>0) { + if (actualAmount != 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { diff --git a/contracts/SystemReward.template b/contracts/SystemReward.template index c62a74e6..9d67109c 100644 --- a/contracts/SystemReward.template +++ b/contracts/SystemReward.template @@ -70,7 +70,7 @@ contract SystemReward is System, IParamSubscriber, ISystemReward { if (actualAmount > MAX_REWARDS) { actualAmount = MAX_REWARDS; } - if (actualAmount>0) { + if (actualAmount != 0) { to.transfer(actualAmount); emit rewardTo(to, actualAmount); } else { diff --git a/test/Slash.js b/test/Slash.js index 186f68aa..01f607db 100644 --- a/test/Slash.js +++ b/test/Slash.js @@ -498,8 +498,7 @@ contract("finality slash SlashIndicator", (accounts) => { assert.fail(); } catch (error) { assert.ok( - error.toString().includes("too old block involved in the evidence"), - "the vote must happen recently" + error.toString().includes("too old block involved") ); } @@ -510,8 +509,7 @@ contract("finality slash SlashIndicator", (accounts) => { assert.fail(); } catch (error) { assert.ok( - error.toString().includes("two identical votes"), - "two votes must be different" + error.toString().includes("two identical votes") ); } @@ -522,8 +520,7 @@ contract("finality slash SlashIndicator", (accounts) => { assert.fail(); } catch (error) { assert.ok( - error.toString().includes("source number bigger than target number"), - "source number must smaller than target number" + error.toString().includes("srcNum bigger than tarNum") ); } @@ -533,7 +530,7 @@ contract("finality slash SlashIndicator", (accounts) => { await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); } catch (error) { - assert.ok(error.toString().includes("no violation of vote rules"), "no violation of vote rules"); + assert.ok(error.toString().includes("no violation of vote rules")); } evidence.voteB.tarNum = currentNumber - 12; @@ -542,7 +539,7 @@ contract("finality slash SlashIndicator", (accounts) => { await slashInstance.submitFinalityViolationEvidence(evidence, { from: relayerAccount }); assert.fail(); } catch (error) { - assert.ok(error.toString().includes("validator not exist"), "validator not exist"); + assert.ok(error.toString().includes("validator not exist")); } }); }); From 2008b6e6cf549f6106cefaa4a2f601065c79bad0 Mon Sep 17 00:00:00 2001 From: Loverush Date: Mon, 15 Aug 2022 17:39:32 +0800 Subject: [PATCH 19/48] Minor issue fixed --- contracts/BSCValidatorSet.sol | 10 +++------- contracts/BSCValidatorSet.template | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/contracts/BSCValidatorSet.sol b/contracts/BSCValidatorSet.sol index c3dd8a76..1345a193 100644 --- a/contracts/BSCValidatorSet.sol +++ b/contracts/BSCValidatorSet.sol @@ -752,18 +752,14 @@ contract BSCValidatorSet is IBSCValidatorSet, System, IParamSubscriber, IApplica function getVoteAddresses(address[] memory validators) internal view returns(bytes[] memory) { // check if validatorExtraSet has been initialized uint n = currentValidatorSet.length; + uint length = validators.length; + bytes[] memory voteAddrs = new bytes[](length); if (validatorExtraSet.length != n) { return voteAddrs; } - uint index; - uint length = validators.length; - bytes[] memory voteAddrs = new bytes[](length); for (uint i; i Date: Thu, 5 May 2022 18:55:04 +0800 Subject: [PATCH 20/48] add brunoBlock and eulerBlock --- genesis-template.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/genesis-template.json b/genesis-template.json index ad3fd015..13ec1570 100644 --- a/genesis-template.json +++ b/genesis-template.json @@ -13,6 +13,9 @@ "muirGlacierBlock": 0, "ramanujanBlock": 0, "nielsBlock": 0, + "mirrorSyncBlock":1, + "brunoBlock": 1, + "eulerBlock": 2, "parlia": { "period": 3, "epoch": 200 From ca34b4720abe7aceeeff5c78afd4f44a00f54460 Mon Sep 17 00:00:00 2001 From: realuncle Date: Sat, 7 May 2022 20:19:00 +0800 Subject: [PATCH 21/48] add rebot address and relayer address --- genesis-template.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/genesis-template.json b/genesis-template.json index 13ec1570..208f5ae2 100644 --- a/genesis-template.json +++ b/genesis-template.json @@ -71,6 +71,12 @@ "0x0000000000000000000000000000000000002000": { "balance": "0x0", "code": "0x{{crossChain}}" + }, + "0x88cb4D8F77742c24d647BEf8049D3f3C56067cDD": { + "balance": "0x100000000000000000000" + }, + "0x42D596440775C90db8d9187b47650986E1063493": { + "balance": "0x1000000000000000000000" }{% for v in initHolders %}, "{{ v.address.replace('0x', '') }}": { "balance": "0x{{ v.balance }}" From dd9bd8495c94069a9173f1855afd68b94ee0476f Mon Sep 17 00:00:00 2001 From: Roshan <48975233+Loverush@users.noreply.github.com> Date: Wed, 17 Aug 2022 13:52:51 +0800 Subject: [PATCH 22/48] BEP153: Native Staking Implementation (#163) --- abi/README.md | 25 +- abi/crosschain.abi | 106 +-- abi/staking.abi | 1035 +++++++++++++++++++++++++++ abi/tokenhub.abi | 161 ++--- contracts/CrossChain.sol | 2 +- contracts/CrossChain.template | 2 +- contracts/Staking.sol | 578 +++++++++++++++ contracts/Staking.template | 585 +++++++++++++++ contracts/System.sol | 3 +- contracts/System.template | 6 +- contracts/TokenHub.sol | 6 + contracts/TokenHub.template | 6 + contracts/interface/ICrossChain.sol | 2 +- contracts/interface/IStaking.sol | 30 + contracts/interface/ITokenHub.sol | 3 +- contracts/mock/MockTokenHub.sol | 8 + generate-genesis.js | 6 + generate-staking.js | 31 + genesis-template.json | 3 + migrations/2_deploy_contracts.js | 25 +- test/BSCValidatorSet.js | 8 +- test/GovHub.js | 32 + test/Staking.js | 472 ++++++++++++ test/TestRelayerIncentivize.js | 4 +- test/TestTokenHub.js | 4 +- 25 files changed, 2915 insertions(+), 228 deletions(-) create mode 100644 abi/staking.abi create mode 100644 contracts/Staking.sol create mode 100644 contracts/Staking.template create mode 100644 contracts/interface/IStaking.sol create mode 100644 generate-staking.js create mode 100644 test/Staking.js diff --git a/abi/README.md b/abi/README.md index e41b9d7d..dbbf341d 100644 --- a/abi/README.md +++ b/abi/README.md @@ -1,14 +1,15 @@ # ABI Files for Build-In System Contracts -| Contract Name | Address | ABI file name | -| ----------------------|-------------------------------------------|--------------------------------------------------- | -| BSCValidatorSet |0x0000000000000000000000000000000000001000 | [bscvalidatorset](bscvalidatorset.abi) | -| SlashIndicator |0x0000000000000000000000000000000000001001 | [slashindicator](slashindicator.abi) | -| SystemReward |0x0000000000000000000000000000000000001002 | [systemreward](systemreward.abi) | -| TendermintLightClient |0x0000000000000000000000000000000000001003 | [tendermintlightclient](tendermintlightclient.abi) | -| TokenHub |0x0000000000000000000000000000000000001004 | [tokenhub](tokenhub.abi) | -| RelayerIncentivize |0x0000000000000000000000000000000000001005 | [relayerincentivize](relayerincentivize.abi) | -| RelayerHub |0x0000000000000000000000000000000000001006 | [relayerhub](relayerhub.abi) | -| GovHub |0x0000000000000000000000000000000000001007 | [govhub](govhub.abi) | -| TokenManager |0x0000000000000000000000000000000000001008 | [tokenmanager](tokenmanager.abi) | -| CrossChain |0x0000000000000000000000000000000000002000 | [crosschain](crosschain.abi) | \ No newline at end of file +| Contract Name | Address | ABI file name | +|-----------------------|--------------------------------------------|----------------------------------------------------| +| BSCValidatorSet | 0x0000000000000000000000000000000000001000 | [bscvalidatorset](bscvalidatorset.abi) | +| SlashIndicator | 0x0000000000000000000000000000000000001001 | [slashindicator](slashindicator.abi) | +| SystemReward | 0x0000000000000000000000000000000000001002 | [systemreward](systemreward.abi) | +| TendermintLightClient | 0x0000000000000000000000000000000000001003 | [tendermintlightclient](tendermintlightclient.abi) | +| TokenHub | 0x0000000000000000000000000000000000001004 | [tokenhub](tokenhub.abi) | +| RelayerIncentivize | 0x0000000000000000000000000000000000001005 | [relayerincentivize](relayerincentivize.abi) | +| RelayerHub | 0x0000000000000000000000000000000000001006 | [relayerhub](relayerhub.abi) | +| GovHub | 0x0000000000000000000000000000000000001007 | [govhub](govhub.abi) | +| TokenManager | 0x0000000000000000000000000000000000001008 | [tokenmanager](tokenmanager.abi) | +| CrossChain | 0x0000000000000000000000000000000000002000 | [crosschain](crosschain.abi) | +| Staking | 0x0000000000000000000000000000000000002001 | [staking](staking.abi) | \ No newline at end of file diff --git a/abi/crosschain.abi b/abi/crosschain.abi index 815d0054..e84fcd2d 100644 --- a/abi/crosschain.abi +++ b/abi/crosschain.abi @@ -182,7 +182,6 @@ "type": "event" }, { - "constant": true, "inputs": [], "name": "ACK_PACKAGE", "outputs": [ @@ -192,12 +191,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "BIND_CHANNELID", "outputs": [ @@ -207,12 +204,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "CODE_OK", "outputs": [ @@ -222,12 +217,10 @@ "type": "uint32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "CROSS_CHAIN_CONTRACT_ADDR", "outputs": [ @@ -237,12 +230,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "CROSS_CHAIN_KEY_PREFIX", "outputs": [ @@ -252,12 +243,23 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "CROSS_STAKE_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "ERROR_FAIL_DECODE", "outputs": [ @@ -267,12 +269,10 @@ "type": "uint32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "FAIL_ACK_PACKAGE", "outputs": [ @@ -282,12 +282,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "GOV_CHANNELID", "outputs": [ @@ -297,12 +295,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "GOV_HUB_ADDR", "outputs": [ @@ -312,12 +308,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "INCENTIVIZE_ADDR", "outputs": [ @@ -327,12 +321,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "INIT_BATCH_SIZE", "outputs": [ @@ -342,12 +334,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "LIGHT_CLIENT_ADDR", "outputs": [ @@ -357,12 +347,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "RELAYERHUB_CONTRACT_ADDR", "outputs": [ @@ -372,12 +360,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SLASH_CHANNELID", "outputs": [ @@ -387,12 +373,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SLASH_CONTRACT_ADDR", "outputs": [ @@ -402,12 +386,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "STAKING_CHANNELID", "outputs": [ @@ -417,12 +399,23 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "STAKING_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "STORE_NAME", "outputs": [ @@ -432,12 +425,10 @@ "type": "string" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SYN_PACKAGE", "outputs": [ @@ -447,12 +438,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SYSTEM_REWARD_ADDR", "outputs": [ @@ -462,12 +451,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TOKEN_HUB_ADDR", "outputs": [ @@ -477,12 +464,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TOKEN_MANAGER_ADDR", "outputs": [ @@ -492,12 +477,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_CHANNELID", "outputs": [ @@ -507,12 +490,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_OUT_CHANNELID", "outputs": [ @@ -522,12 +503,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "VALIDATOR_CONTRACT_ADDR", "outputs": [ @@ -537,12 +516,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "alreadyInit", "outputs": [ @@ -552,12 +529,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "batchSizeForOracle", "outputs": [ @@ -567,12 +542,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "bscChainID", "outputs": [ @@ -582,12 +555,10 @@ "type": "uint16" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "uint8", @@ -603,12 +574,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "uint8", @@ -624,12 +593,10 @@ "type": "uint64" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "uint8", @@ -645,12 +612,10 @@ "type": "uint64" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "uint8", @@ -666,12 +631,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "oracleSequence", "outputs": [ @@ -681,12 +644,10 @@ "type": "int64" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "previousTxHeight", "outputs": [ @@ -696,12 +657,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -722,12 +681,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "txCounter", "outputs": [ @@ -737,21 +694,17 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [], "name": "init", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "uint8", @@ -777,12 +730,10 @@ "type": "bytes" } ], - "payable": false, "stateMutability": "pure", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "bytes", @@ -812,12 +763,10 @@ ], "name": "handlePackage", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "uint8", @@ -837,12 +786,10 @@ ], "name": "sendSynPackage", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "string", @@ -857,7 +804,6 @@ ], "name": "updateParam", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" } diff --git a/abi/staking.abi b/abi/staking.abi new file mode 100644 index 00000000..e6e623aa --- /dev/null +++ b/abi/staking.abi @@ -0,0 +1,1035 @@ +[ + { + "anonymous": false, + "inputs": [], + "name": "crashResponse", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oracleRelayerFee", + "type": "uint256" + } + ], + "name": "delegateSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "errCode", + "type": "uint8" + } + ], + "name": "failedDelegate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "valSrc", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "valDst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "errCode", + "type": "uint8" + } + ], + "name": "failedRedelegate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "errCode", + "type": "uint256" + } + ], + "name": "failedSynPackage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint8", + "name": "errCode", + "type": "uint8" + } + ], + "name": "failedUndelegate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "paramChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorSrc", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validatorDst", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oracleRelayerFee", + "type": "uint256" + } + ], + "name": "redelegateSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rewardClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "rewardReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oracleRelayerFee", + "type": "uint256" + } + ], + "name": "undelegateSubmitted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegatedClaimed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegatedReceived", + "type": "event" + }, + { + "inputs": [], + "name": "BIND_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CODE_OK", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_CHAIN_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "CROSS_STAKE_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_FAIL_DECODE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_UNKNOWN_PACKAGE_TYPE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ERROR_WITHDRAW_BNB", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EVENT_DELEGATE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EVENT_DISTRIBUTE_REWARD", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EVENT_DISTRIBUTE_UNDELEGATED", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EVENT_REDELEGATE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "EVENT_UNDELEGATE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "GOV_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INCENTIVIZE_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_MIN_DELEGATION_CHANGE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INIT_ORACLE_RELAYER_FEE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LIGHT_CLIENT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RELAYERHUB_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SLASH_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "STAKING_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_REWARD_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TEN_DECIMALS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_HUB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TOKEN_MANAGER_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_IN_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSFER_OUT_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "VALIDATOR_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "alreadyInit", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bscChainID", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minDelegationChange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracleRelayerFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleSynPackage", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "msgBytes", + "type": "bytes" + } + ], + "name": "handleAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "handleFailAckPackage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "validatorSrc", + "type": "address" + }, + { + "internalType": "address", + "name": "validatorDst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "redelegate", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "claimReward", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "claimUndeldegated", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "getDelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDistributedReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getUndelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "address", + "name": "validator", + "type": "address" + } + ], + "name": "getPendingUndelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getOracleRelayerFee", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMinDelegationChange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "key", + "type": "string" + }, + { + "internalType": "bytes", + "name": "value", + "type": "bytes" + } + ], + "name": "updateParam", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/abi/tokenhub.abi b/abi/tokenhub.abi index b6fd77de..1faeb599 100644 --- a/abi/tokenhub.abi +++ b/abi/tokenhub.abi @@ -1,7 +1,6 @@ [ { "inputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "constructor" }, @@ -200,12 +199,6 @@ "type": "event" }, { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "constant": true, "inputs": [], "name": "BEP2_TOKEN_DECIMALS", "outputs": [ @@ -215,12 +208,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "BEP2_TOKEN_SYMBOL_FOR_BNB", "outputs": [ @@ -230,12 +221,10 @@ "type": "bytes32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "BIND_CHANNELID", "outputs": [ @@ -245,12 +234,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "CODE_OK", "outputs": [ @@ -260,12 +247,10 @@ "type": "uint32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "CROSS_CHAIN_CONTRACT_ADDR", "outputs": [ @@ -275,12 +260,23 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "CROSS_STAKE_CHANNELID", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "ERROR_FAIL_DECODE", "outputs": [ @@ -290,12 +286,10 @@ "type": "uint32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "GOV_CHANNELID", "outputs": [ @@ -305,12 +299,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "GOV_HUB_ADDR", "outputs": [ @@ -320,12 +312,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "INCENTIVIZE_ADDR", "outputs": [ @@ -335,12 +325,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "INIT_MINIMUM_RELAY_FEE", "outputs": [ @@ -350,12 +338,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "LIGHT_CLIENT_ADDR", "outputs": [ @@ -365,12 +351,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MAXIMUM_BEP20_SYMBOL_LEN", "outputs": [ @@ -380,12 +364,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MAX_BEP2_TOTAL_SUPPLY", "outputs": [ @@ -395,12 +377,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MAX_GAS_FOR_CALLING_BEP20", "outputs": [ @@ -410,12 +390,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MAX_GAS_FOR_TRANSFER_BNB", "outputs": [ @@ -425,12 +403,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "MINIMUM_BEP20_SYMBOL_LEN", "outputs": [ @@ -440,12 +416,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "RELAYERHUB_CONTRACT_ADDR", "outputs": [ @@ -455,12 +429,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "REWARD_UPPER_LIMIT", "outputs": [ @@ -470,12 +442,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SLASH_CHANNELID", "outputs": [ @@ -485,12 +455,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "SLASH_CONTRACT_ADDR", "outputs": [ @@ -500,12 +468,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "STAKING_CHANNELID", "outputs": [ @@ -515,12 +481,23 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, + "inputs": [], + "name": "STAKING_CONTRACT_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "SYSTEM_REWARD_ADDR", "outputs": [ @@ -530,12 +507,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TEN_DECIMALS", "outputs": [ @@ -545,12 +520,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TOKEN_HUB_ADDR", "outputs": [ @@ -560,12 +533,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TOKEN_MANAGER_ADDR", "outputs": [ @@ -575,12 +546,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_CHANNELID", "outputs": [ @@ -590,12 +559,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_FAILURE_INSUFFICIENT_BALANCE", "outputs": [ @@ -605,12 +572,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_FAILURE_NON_PAYABLE_RECIPIENT", "outputs": [ @@ -620,12 +585,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_FAILURE_TIMEOUT", "outputs": [ @@ -635,12 +598,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_FAILURE_UNBOUND_TOKEN", "outputs": [ @@ -650,12 +611,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_FAILURE_UNKNOWN", "outputs": [ @@ -665,12 +624,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_IN_SUCCESS", "outputs": [ @@ -680,12 +637,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "TRANSFER_OUT_CHANNELID", "outputs": [ @@ -695,12 +650,10 @@ "type": "uint8" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "VALIDATOR_CONTRACT_ADDR", "outputs": [ @@ -710,12 +663,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "alreadyInit", "outputs": [ @@ -725,12 +676,10 @@ "type": "bool" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -746,12 +695,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "bscChainID", "outputs": [ @@ -761,12 +708,10 @@ "type": "uint16" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [], "name": "relayFee", "outputs": [ @@ -776,21 +721,21 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, + "stateMutability": "payable", + "type": "receive" + }, + { "inputs": [], "name": "init", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address payable", @@ -811,12 +756,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [], "name": "getMiniRelayFee", "outputs": [ @@ -826,12 +769,10 @@ "type": "uint256" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "uint8", @@ -852,12 +793,10 @@ "type": "bytes" } ], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "uint8", @@ -872,12 +811,10 @@ ], "name": "handleAckPackage", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "uint8", @@ -892,12 +829,10 @@ ], "name": "handleFailAckPackage", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address", @@ -928,12 +863,10 @@ "type": "bool" } ], - "payable": true, "stateMutability": "payable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "address[]", @@ -964,12 +897,10 @@ "type": "bool" } ], - "payable": true, "stateMutability": "payable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "string", @@ -984,12 +915,10 @@ ], "name": "updateParam", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "bytes32", @@ -1005,12 +934,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -1026,12 +953,10 @@ "type": "bytes32" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "bytes32", @@ -1051,12 +976,10 @@ ], "name": "bindToken", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, "inputs": [ { "internalType": "bytes32", @@ -1071,12 +994,10 @@ ], "name": "unbindToken", "outputs": [], - "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "string", @@ -1092,12 +1013,10 @@ "type": "address" } ], - "payable": false, "stateMutability": "view", "type": "function" }, { - "constant": true, "inputs": [ { "internalType": "address", @@ -1113,8 +1032,26 @@ "type": "string" } ], - "payable": false, "stateMutability": "view", "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawStakingBNB", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/contracts/CrossChain.sol b/contracts/CrossChain.sol index 53ede1eb..398890d7 100644 --- a/contracts/CrossChain.sol +++ b/contracts/CrossChain.sol @@ -127,7 +127,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ alreadyInit=true; } -function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { + function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { uint256 payloadLength = msgBytes.length + 33; bytes memory payload = new bytes(payloadLength); uint256 ptr; diff --git a/contracts/CrossChain.template b/contracts/CrossChain.template index c363268a..d2a269ba 100644 --- a/contracts/CrossChain.template +++ b/contracts/CrossChain.template @@ -128,7 +128,7 @@ contract CrossChain is System, ICrossChain, IParamSubscriber{ alreadyInit=true; } -function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { + function encodePayload(uint8 packageType, uint256 relayFee, bytes memory msgBytes) public pure returns(bytes memory) { uint256 payloadLength = msgBytes.length + 33; bytes memory payload = new bytes(payloadLength); uint256 ptr; diff --git a/contracts/Staking.sol b/contracts/Staking.sol new file mode 100644 index 00000000..08118694 --- /dev/null +++ b/contracts/Staking.sol @@ -0,0 +1,578 @@ +pragma solidity 0.6.4; + +import "./System.sol"; +import "./lib/Memory.sol"; +import "./lib/BytesToTypes.sol"; +import "./interface/IApplication.sol"; +import "./interface/ICrossChain.sol"; +import "./interface/IParamSubscriber.sol"; +import "./interface/ITokenHub.sol"; +import "./lib/CmnPkg.sol"; +import "./lib/SafeMath.sol"; +import "./lib/RLPEncode.sol"; +import "./lib/RLPDecode.sol"; +import "./interface/IStaking.sol"; + +contract Staking is IStaking, System, IParamSubscriber, IApplication { + using SafeMath for uint256; + using RLPEncode for *; + using RLPDecode for *; + + // Cross Stake Event type + uint8 public constant EVENT_DELEGATE = 0x01; + uint8 public constant EVENT_UNDELEGATE = 0x02; + uint8 public constant EVENT_REDELEGATE = 0x03; + uint8 public constant EVENT_DISTRIBUTE_REWARD = 0x04; + uint8 public constant EVENT_DISTRIBUTE_UNDELEGATED = 0x05; + + // Error code + uint32 public constant ERROR_WITHDRAW_BNB = 101; + + uint256 public constant TEN_DECIMALS = 1e10; + + uint256 public constant INIT_ORACLE_RELAYER_FEE = 6e15; + uint256 public constant INIT_MIN_DELEGATION = 100 * 1e18; + + uint256 public oracleRelayerFee; + uint256 public minDelegation; + + mapping(address => uint256) delegated; // delegator => totalAmount + mapping(address => mapping(address => uint256)) delegatedOfValidator; // delegator => validator => amount + mapping(address => uint256) distributedReward; // delegator => reward + mapping(address => mapping(address => uint256)) pendingUndelegateTime; // delegator => validator => minTime + mapping(address => uint256) undelegated; // delegator => totalUndelegated + mapping(address => mapping(address => mapping(address => uint256))) pendingRedelegateTime; // delegator => srcValidator => dstValidator => minTime + + bool internal locked; + + modifier noReentrant() { + require(!locked, "No re-entrancy"); + locked = true; + _; + locked = false; + } + + modifier tenDecimalPrecision(uint256 amount) { + require(msg.value%TEN_DECIMALS==0 && amount%TEN_DECIMALS==0, "precision loss in conversion"); + _; + } + + modifier initParams() { + if (!alreadyInit) { + oracleRelayerFee = INIT_ORACLE_RELAYER_FEE; + minDelegation = INIT_MIN_DELEGATION; + alreadyInit = true; + } + _; + } + + /*********************************** Events **********************************/ + event delegateSubmitted(address indexed delegator, address indexed validator, uint256 amount, uint256 oracleRelayerFee); + event undelegateSubmitted(address indexed delegator, address indexed validator, uint256 amount, uint256 oracleRelayerFee); + event redelegateSubmitted(address indexed delegator, address indexed validatorSrc, address indexed validatorDst, uint256 amount, uint256 oracleRelayerFee); + event rewardReceived(address indexed delegator, uint256 amount); + event rewardClaimed(address indexed delegator, uint256 amount); + event undelegatedReceived(address indexed delegator, address indexed validator, uint256 amount); + event undelegatedClaimed(address indexed delegator, uint256 amount); + event failedDelegate(address indexed delegator, address indexed validator, uint256 amount, uint8 errCode); + event failedUndelegate(address indexed delegator, address indexed validator, uint256 amount, uint8 errCode); + event failedRedelegate(address indexed delegator, address indexed valSrc, address indexed valDst, uint256 amount, uint8 errCode); + event paramChange(string key, bytes value); + event failedSynPackage(uint8 indexed eventType, uint256 errCode); + event crashResponse(uint8 indexed eventType); + + receive() external payable {} + + /************************* Implement cross chain app *************************/ + function handleSynPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override returns(bytes memory) { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + uint32 resCode; + bytes memory ackPackage; + if (eventType == EVENT_DISTRIBUTE_REWARD) { + (resCode, ackPackage) = _handleDistributeRewardSynPackage(iter); + } else if (eventType == EVENT_DISTRIBUTE_UNDELEGATED) { + (resCode, ackPackage) = _handleDistributeUndelegatedSynPackage(iter); + } else { + require(false, "unknown event type"); + } + + if (resCode != CODE_OK) { + emit failedSynPackage(eventType, resCode); + } + return ackPackage; + } + + function handleAckPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + if (eventType == EVENT_DELEGATE) { + _handleDelegateAckPackage(iter); + } else if (eventType == EVENT_UNDELEGATE) { + _handleUndelegateAckPackage(iter); + } else if (eventType == EVENT_REDELEGATE) { + _handleRedelegateAckPackage(iter); + } else { + require(false, "unknown event type"); + } + return; + } + + function handleFailAckPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + if (eventType == EVENT_DELEGATE) { + _handleDelegateFailAckPackage(iter); + } else if (eventType == EVENT_UNDELEGATE) { + _handleUndelegateFailAckPackage(iter); + } else if (eventType == EVENT_REDELEGATE) { + _handleRedelegateFailAckPackage(iter); + } else { + require(false, "unknown event type"); + } + return; + } + + /***************************** External functions *****************************/ + function delegate(address validator, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(amount >= minDelegation, "invalid delegate amount"); + require(msg.value >= amount.add(oracleRelayerFee), "not enough msg value"); + require(payable(msg.sender).send(0), "invalid delegator"); // the msg sender must be payable + + uint256 convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = (msg.value).sub(amount); + + bytes[] memory elements = new bytes[](3); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validator.encodeAddress(); + elements[2] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_DELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(msg.value); + + delegated[msg.sender] = delegated[msg.sender].add(amount); + delegatedOfValidator[msg.sender][validator] = delegatedOfValidator[msg.sender][validator].add(amount); + + emit delegateSubmitted(msg.sender, validator, amount, _oracleRelayerFee); + } + + function undelegate(address validator, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(msg.value >= oracleRelayerFee, "not enough relay fee"); + if (amount < minDelegation) { + require(amount >= oracleRelayerFee, "not enough funds"); + require(amount == delegatedOfValidator[msg.sender][validator], "invalid amount"); + } + require(block.timestamp >= pendingUndelegateTime[msg.sender][validator], "pending undelegation exist"); + delegatedOfValidator[msg.sender][validator] = delegatedOfValidator[msg.sender][validator].sub(amount, "not enough funds"); + + uint256 convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = msg.value; + + bytes[] memory elements = new bytes[](3); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validator.encodeAddress(); + elements[2] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_UNDELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(_oracleRelayerFee); + + delegated[msg.sender] = delegated[msg.sender].sub(amount); + pendingUndelegateTime[msg.sender][validator] = block.timestamp.add(691200); // 8*24*3600 + + emit undelegateSubmitted(msg.sender, validator, amount, _oracleRelayerFee); + } + + function redelegate(address validatorSrc, address validatorDst, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(validatorSrc != validatorDst, "invalid redelegation"); + require(msg.value >= oracleRelayerFee, "not enough relay fee"); + require(amount >= minDelegation, "invalid amount"); + require(block.timestamp >= pendingRedelegateTime[msg.sender][validatorSrc][validatorDst] && + block.timestamp >= pendingRedelegateTime[msg.sender][validatorDst][validatorSrc], "pending redelegation exist"); + delegatedOfValidator[msg.sender][validatorSrc] = delegatedOfValidator[msg.sender][validatorSrc].sub(amount, "not enough funds"); + delegatedOfValidator[msg.sender][validatorDst] = delegatedOfValidator[msg.sender][validatorDst].add(amount); + + uint256 convertedAmount = amount.div(TEN_DECIMALS);// native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = msg.value; + + bytes[] memory elements = new bytes[](4); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validatorSrc.encodeAddress(); + elements[2] = validatorDst.encodeAddress(); + elements[3] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_REDELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(_oracleRelayerFee); + + pendingRedelegateTime[msg.sender][validatorSrc][validatorDst] = block.timestamp.add(691200); // 8*24*3600 + pendingRedelegateTime[msg.sender][validatorDst][validatorSrc] = block.timestamp.add(691200); // 8*24*3600 + + emit redelegateSubmitted(msg.sender, validatorSrc, validatorDst, amount, _oracleRelayerFee); + } + + function claimReward() override external noReentrant returns(uint256 amount) { + require(distributedReward[msg.sender] > 0, "no pending reward"); + + amount = distributedReward[msg.sender]; + distributedReward[msg.sender] = 0; + payable(msg.sender).transfer(amount); + emit rewardClaimed(msg.sender, amount); + } + + function claimUndeldegated() override external noReentrant returns(uint256 amount) { + require(undelegated[msg.sender] > 0, "no undelegated funds"); + + amount = undelegated[msg.sender]; + undelegated[msg.sender] = 0; + payable(msg.sender).transfer(amount); + emit undelegatedClaimed(msg.sender, amount); + } + + function getDelegated(address delegator, address validator) override external view returns(uint256) { + return delegatedOfValidator[delegator][validator]; + } + + function getTotalDelegated(address delegator) override external view returns(uint256) { + return delegated[delegator]; + } + + function getDistributedReward(address delegator) override external view returns(uint256) { + return distributedReward[delegator]; + } + + function getPendingRedelegateTime(address delegator, address valSrc, address valDst) override external view returns(uint256) { + return pendingRedelegateTime[delegator][valSrc][valDst]; + } + + function getUndelegated(address delegator) override external view returns(uint256) { + return undelegated[delegator]; + } + + function getPendingUndelegateTime(address delegator, address validator) override external view returns(uint256) { + return pendingUndelegateTime[delegator][validator]; + } + + function getOracleRelayerFee() override external view returns(uint256) { + return oracleRelayerFee; + } + + function getMinDelegation() override external view returns(uint256) { + return minDelegation; + } + + /***************************** Internal functions *****************************/ + function _RLPEncode(uint8 eventType, bytes memory msgBytes) internal pure returns(bytes memory output) { + bytes[] memory elements = new bytes[](2); + elements[0] = eventType.encodeUint(); + elements[1] = msgBytes.encodeBytes(); + output = elements.encodeList(); + } + + function _encodeRefundPackage(uint8 eventType, uint256 amount, address recipient, uint32 errorCode) internal pure returns(uint32, bytes memory) { + amount = amount.div(TEN_DECIMALS); + bytes[] memory elements = new bytes[](4); + elements[0] = eventType.encodeUint(); + elements[1] = amount.encodeUint(); + elements[2] = recipient.encodeAddress(); + elements[3] = errorCode.encodeUint(); + bytes memory packageBytes = elements.encodeList(); + return (errorCode, packageBytes); + } + + /******************************** Param update ********************************/ + function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov { + if (Memory.compareStrings(key, "oracleRelayerFee")) { + require(value.length == 32, "length of oracleRelayerFee mismatch"); + uint256 newOracleRelayerFee = BytesToTypes.bytesToUint256(32, value); + require(newOracleRelayerFee >0, "the oracleRelayerFee must be greater than 0"); + oracleRelayerFee = newOracleRelayerFee; + } else if (Memory.compareStrings(key, "minDelegation")) { + require(value.length == 32, "length of minDelegation mismatch"); + uint256 newMinDelegation = BytesToTypes.bytesToUint256(32, value); + require(newMinDelegation > 0, "the minDelegation must be greater than 0"); + minDelegation = newMinDelegation; + } else { + require(false, "unknown param"); + } + emit paramChange(key, value); + } + + /************************* Handle cross-chain package *************************/ + function _handleDelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + amount = uint256(iter.next().toUint()); + } else if (idx == 3) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + require(ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount), "withdraw from tokenhub failed"); + + delegated[delegator] = delegated[delegator].sub(amount); + undelegated[delegator] = undelegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].sub(amount); + + emit failedDelegate(delegator, validator, amount, errCode); + } + + function _handleDelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + require(ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount), "withdraw from tokenhub failed"); + + delegated[delegator] = delegated[delegator].sub(amount); + undelegated[delegator] = undelegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].sub(amount); + + emit crashResponse(EVENT_DELEGATE); + } + + function _handleUndelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + amount = uint256(iter.next().toUint()); + } else if (idx == 3) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + delegated[delegator] = delegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].add(amount); + pendingUndelegateTime[delegator][validator] = 0; + + emit failedUndelegate(delegator, validator, amount, errCode); + } + + function _handleUndelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + delegated[delegator] = delegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].add(amount); + pendingUndelegateTime[delegator][validator] = 0; + + emit crashResponse(EVENT_UNDELEGATE); + } + + function _handleRedelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address valSrc; + address valDst; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + valSrc = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + valDst = address(uint160(iter.next().toAddress())); + } else if (idx == 3) { + amount = uint256(iter.next().toUint()); + } else if (idx == 4) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + delegatedOfValidator[delegator][valSrc] = delegatedOfValidator[delegator][valSrc].add(amount); + delegatedOfValidator[delegator][valDst] = delegatedOfValidator[delegator][valDst].sub(amount); + pendingRedelegateTime[delegator][valSrc][valDst] = 0; + pendingRedelegateTime[delegator][valDst][valSrc] = 0; + + emit failedRedelegate(delegator, valSrc, valDst, amount, errCode); + } + + function _handleRedelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address valSrc; + address valDst; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + valSrc = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + valDst = address(uint160(iter.next().toAddress())); + } else if (idx == 3) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + delegatedOfValidator[delegator][valSrc] = delegatedOfValidator[delegator][valSrc].add(amount); + delegatedOfValidator[delegator][valDst] = delegatedOfValidator[delegator][valDst].sub(amount); + pendingRedelegateTime[delegator][valSrc][valDst] = 0; + pendingRedelegateTime[delegator][valDst][valSrc] = 0; + + emit crashResponse(EVENT_REDELEGATE); + } + + function _handleDistributeRewardSynPackage(RLPDecode.Iterator memory iter) internal returns(uint32, bytes memory) { + bool success = false; + uint256 idx = 0; + uint256 amount; + address recipient; + while (iter.hasNext()) { + if (idx == 0) { + amount = uint256(iter.next().toUint()); + } else if (idx == 1) { + recipient = address(uint160(iter.next().toAddress())); + success = true; + } else { + break; + } + idx++; + } + if (!success) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_REWARD, amount, recipient, ERROR_FAIL_DECODE); + } + + bool ok = ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount); + if (!ok) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_REWARD, amount, recipient, ERROR_WITHDRAW_BNB); + } + + distributedReward[recipient] = distributedReward[recipient].add(amount); + + emit rewardReceived(recipient, amount); + return (CODE_OK, new bytes(0)); + } + + function _handleDistributeUndelegatedSynPackage(RLPDecode.Iterator memory iter) internal returns(uint32, bytes memory) { + bool success = false; + uint256 idx = 0; + uint256 amount; + address recipient; + address validator; + while (iter.hasNext()) { + if (idx == 0) { + amount = uint256(iter.next().toUint()); + } else if (idx == 1) { + recipient = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + validator = address(uint160(iter.next().toAddress())); + success = true; + } else { + break; + } + idx++; + } + if (!success) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_UNDELEGATED, amount, recipient, ERROR_FAIL_DECODE); + } + + bool ok = ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount); + if (!ok) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_UNDELEGATED, amount, recipient, ERROR_WITHDRAW_BNB); + } + + pendingUndelegateTime[recipient][validator] = 0; + undelegated[recipient] = undelegated[recipient].add(amount); + + emit undelegatedReceived(recipient, validator, amount); + return (CODE_OK, new bytes(0)); + } +} diff --git a/contracts/Staking.template b/contracts/Staking.template new file mode 100644 index 00000000..fcf686f7 --- /dev/null +++ b/contracts/Staking.template @@ -0,0 +1,585 @@ +pragma solidity 0.6.4; + +import "./System.sol"; +import "./lib/Memory.sol"; +import "./lib/BytesToTypes.sol"; +import "./interface/IApplication.sol"; +import "./interface/ICrossChain.sol"; +import "./interface/IParamSubscriber.sol"; +import "./interface/ITokenHub.sol"; +import "./lib/CmnPkg.sol"; +import "./lib/SafeMath.sol"; +import "./lib/RLPEncode.sol"; +import "./lib/RLPDecode.sol"; +import "./interface/IStaking.sol"; + +contract Staking is IStaking, System, IParamSubscriber, IApplication { + using SafeMath for uint256; + using RLPEncode for *; + using RLPDecode for *; + + // Cross Stake Event type + uint8 public constant EVENT_DELEGATE = 0x01; + uint8 public constant EVENT_UNDELEGATE = 0x02; + uint8 public constant EVENT_REDELEGATE = 0x03; + uint8 public constant EVENT_DISTRIBUTE_REWARD = 0x04; + uint8 public constant EVENT_DISTRIBUTE_UNDELEGATED = 0x05; + + // Error code + uint32 public constant ERROR_WITHDRAW_BNB = 101; + + uint256 public constant TEN_DECIMALS = 1e10; + + uint256 public constant INIT_ORACLE_RELAYER_FEE = 6e15; + uint256 public constant INIT_MIN_DELEGATION = 100 * 1e18; + + uint256 public oracleRelayerFee; + uint256 public minDelegation; + + mapping(address => uint256) delegated; // delegator => totalAmount + mapping(address => mapping(address => uint256)) delegatedOfValidator; // delegator => validator => amount + mapping(address => uint256) distributedReward; // delegator => reward + mapping(address => mapping(address => uint256)) pendingUndelegateTime; // delegator => validator => minTime + mapping(address => uint256) undelegated; // delegator => totalUndelegated + mapping(address => mapping(address => mapping(address => uint256))) pendingRedelegateTime; // delegator => srcValidator => dstValidator => minTime + + bool internal locked; + + modifier noReentrant() { + require(!locked, "No re-entrancy"); + locked = true; + _; + locked = false; + } + + modifier tenDecimalPrecision(uint256 amount) { + require(msg.value%TEN_DECIMALS==0 && amount%TEN_DECIMALS==0, "precision loss in conversion"); + _; + } + + modifier initParams() { + if (!alreadyInit) { + oracleRelayerFee = INIT_ORACLE_RELAYER_FEE; + minDelegation = INIT_MIN_DELEGATION; + alreadyInit = true; + } + _; + } + + /*********************************** Events **********************************/ + event delegateSubmitted(address indexed delegator, address indexed validator, uint256 amount, uint256 oracleRelayerFee); + event undelegateSubmitted(address indexed delegator, address indexed validator, uint256 amount, uint256 oracleRelayerFee); + event redelegateSubmitted(address indexed delegator, address indexed validatorSrc, address indexed validatorDst, uint256 amount, uint256 oracleRelayerFee); + event rewardReceived(address indexed delegator, uint256 amount); + event rewardClaimed(address indexed delegator, uint256 amount); + event undelegatedReceived(address indexed delegator, address indexed validator, uint256 amount); + event undelegatedClaimed(address indexed delegator, uint256 amount); + event failedDelegate(address indexed delegator, address indexed validator, uint256 amount, uint8 errCode); + event failedUndelegate(address indexed delegator, address indexed validator, uint256 amount, uint8 errCode); + event failedRedelegate(address indexed delegator, address indexed valSrc, address indexed valDst, uint256 amount, uint8 errCode); + event paramChange(string key, bytes value); + event failedSynPackage(uint8 indexed eventType, uint256 errCode); + event crashResponse(uint8 indexed eventType); +{% if mock %} + /*********************** init **************************/ + function init() external onlyNotInit { + oracleRelayerFee = INIT_ORACLE_RELAYER_FEE; + minDelegation = INIT_MIN_DELEGATION; + alreadyInit = true; + } +{% endif %} + receive() external payable {} + + /************************* Implement cross chain app *************************/ + function handleSynPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override returns(bytes memory) { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + uint32 resCode; + bytes memory ackPackage; + if (eventType == EVENT_DISTRIBUTE_REWARD) { + (resCode, ackPackage) = _handleDistributeRewardSynPackage(iter); + } else if (eventType == EVENT_DISTRIBUTE_UNDELEGATED) { + (resCode, ackPackage) = _handleDistributeUndelegatedSynPackage(iter); + } else { + require(false, "unknown event type"); + } + + if (resCode != CODE_OK) { + emit failedSynPackage(eventType, resCode); + } + return ackPackage; + } + + function handleAckPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + if (eventType == EVENT_DELEGATE) { + _handleDelegateAckPackage(iter); + } else if (eventType == EVENT_UNDELEGATE) { + _handleUndelegateAckPackage(iter); + } else if (eventType == EVENT_REDELEGATE) { + _handleRedelegateAckPackage(iter); + } else { + require(false, "unknown event type"); + } + return; + } + + function handleFailAckPackage(uint8, bytes calldata msgBytes) external onlyCrossChainContract initParams override { + RLPDecode.Iterator memory iter = msgBytes.toRLPItem().iterator(); + uint8 eventType = uint8(iter.next().toUint()); + if (eventType == EVENT_DELEGATE) { + _handleDelegateFailAckPackage(iter); + } else if (eventType == EVENT_UNDELEGATE) { + _handleUndelegateFailAckPackage(iter); + } else if (eventType == EVENT_REDELEGATE) { + _handleRedelegateFailAckPackage(iter); + } else { + require(false, "unknown event type"); + } + return; + } + + /***************************** External functions *****************************/ + function delegate(address validator, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(amount >= minDelegation, "invalid delegate amount"); + require(msg.value >= amount.add(oracleRelayerFee), "not enough msg value"); + require(payable(msg.sender).send(0), "invalid delegator"); // the msg sender must be payable + + uint256 convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = (msg.value).sub(amount); + + bytes[] memory elements = new bytes[](3); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validator.encodeAddress(); + elements[2] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_DELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(msg.value); + + delegated[msg.sender] = delegated[msg.sender].add(amount); + delegatedOfValidator[msg.sender][validator] = delegatedOfValidator[msg.sender][validator].add(amount); + + emit delegateSubmitted(msg.sender, validator, amount, _oracleRelayerFee); + } + + function undelegate(address validator, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(msg.value >= oracleRelayerFee, "not enough relay fee"); + if (amount < minDelegation) { + require(amount >= oracleRelayerFee, "not enough funds"); + require(amount == delegatedOfValidator[msg.sender][validator], "invalid amount"); + } + require(block.timestamp >= pendingUndelegateTime[msg.sender][validator], "pending undelegation exist"); + delegatedOfValidator[msg.sender][validator] = delegatedOfValidator[msg.sender][validator].sub(amount, "not enough funds"); + + uint256 convertedAmount = amount.div(TEN_DECIMALS); // native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = msg.value; + + bytes[] memory elements = new bytes[](3); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validator.encodeAddress(); + elements[2] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_UNDELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(_oracleRelayerFee); + + delegated[msg.sender] = delegated[msg.sender].sub(amount); + pendingUndelegateTime[msg.sender][validator] = block.timestamp.add(691200); // 8*24*3600 + + emit undelegateSubmitted(msg.sender, validator, amount, _oracleRelayerFee); + } + + function redelegate(address validatorSrc, address validatorDst, uint256 amount) override external payable tenDecimalPrecision(amount) initParams { + require(validatorSrc != validatorDst, "invalid redelegation"); + require(msg.value >= oracleRelayerFee, "not enough relay fee"); + require(amount >= minDelegation, "invalid amount"); + require(block.timestamp >= pendingRedelegateTime[msg.sender][validatorSrc][validatorDst] && + block.timestamp >= pendingRedelegateTime[msg.sender][validatorDst][validatorSrc], "pending redelegation exist"); + delegatedOfValidator[msg.sender][validatorSrc] = delegatedOfValidator[msg.sender][validatorSrc].sub(amount, "not enough funds"); + delegatedOfValidator[msg.sender][validatorDst] = delegatedOfValidator[msg.sender][validatorDst].add(amount); + + uint256 convertedAmount = amount.div(TEN_DECIMALS);// native bnb decimals is 8 on BBC, while the native bnb decimals on BSC is 18 + uint256 _oracleRelayerFee = msg.value; + + bytes[] memory elements = new bytes[](4); + elements[0] = msg.sender.encodeAddress(); + elements[1] = validatorSrc.encodeAddress(); + elements[2] = validatorDst.encodeAddress(); + elements[3] = convertedAmount.encodeUint(); + bytes memory msgBytes = elements.encodeList(); + ICrossChain(CROSS_CHAIN_CONTRACT_ADDR).sendSynPackage(CROSS_STAKE_CHANNELID, _RLPEncode(EVENT_REDELEGATE, msgBytes), _oracleRelayerFee.div(TEN_DECIMALS)); + payable(TOKEN_HUB_ADDR).transfer(_oracleRelayerFee); + + pendingRedelegateTime[msg.sender][validatorSrc][validatorDst] = block.timestamp.add(691200); // 8*24*3600 + pendingRedelegateTime[msg.sender][validatorDst][validatorSrc] = block.timestamp.add(691200); // 8*24*3600 + + emit redelegateSubmitted(msg.sender, validatorSrc, validatorDst, amount, _oracleRelayerFee); + } + + function claimReward() override external noReentrant returns(uint256 amount) { + require(distributedReward[msg.sender] > 0, "no pending reward"); + + amount = distributedReward[msg.sender]; + distributedReward[msg.sender] = 0; + payable(msg.sender).transfer(amount); + emit rewardClaimed(msg.sender, amount); + } + + function claimUndeldegated() override external noReentrant returns(uint256 amount) { + require(undelegated[msg.sender] > 0, "no undelegated funds"); + + amount = undelegated[msg.sender]; + undelegated[msg.sender] = 0; + payable(msg.sender).transfer(amount); + emit undelegatedClaimed(msg.sender, amount); + } + + function getDelegated(address delegator, address validator) override external view returns(uint256) { + return delegatedOfValidator[delegator][validator]; + } + + function getTotalDelegated(address delegator) override external view returns(uint256) { + return delegated[delegator]; + } + + function getDistributedReward(address delegator) override external view returns(uint256) { + return distributedReward[delegator]; + } + + function getPendingRedelegateTime(address delegator, address valSrc, address valDst) override external view returns(uint256) { + return pendingRedelegateTime[delegator][valSrc][valDst]; + } + + function getUndelegated(address delegator) override external view returns(uint256) { + return undelegated[delegator]; + } + + function getPendingUndelegateTime(address delegator, address validator) override external view returns(uint256) { + return pendingUndelegateTime[delegator][validator]; + } + + function getOracleRelayerFee() override external view returns(uint256) { + return oracleRelayerFee; + } + + function getMinDelegation() override external view returns(uint256) { + return minDelegation; + } + + /***************************** Internal functions *****************************/ + function _RLPEncode(uint8 eventType, bytes memory msgBytes) internal pure returns(bytes memory output) { + bytes[] memory elements = new bytes[](2); + elements[0] = eventType.encodeUint(); + elements[1] = msgBytes.encodeBytes(); + output = elements.encodeList(); + } + + function _encodeRefundPackage(uint8 eventType, uint256 amount, address recipient, uint32 errorCode) internal pure returns(uint32, bytes memory) { + amount = amount.div(TEN_DECIMALS); + bytes[] memory elements = new bytes[](4); + elements[0] = eventType.encodeUint(); + elements[1] = amount.encodeUint(); + elements[2] = recipient.encodeAddress(); + elements[3] = errorCode.encodeUint(); + bytes memory packageBytes = elements.encodeList(); + return (errorCode, packageBytes); + } + + /******************************** Param update ********************************/ + function updateParam(string calldata key, bytes calldata value) override external onlyInit onlyGov { + if (Memory.compareStrings(key, "oracleRelayerFee")) { + require(value.length == 32, "length of oracleRelayerFee mismatch"); + uint256 newOracleRelayerFee = BytesToTypes.bytesToUint256(32, value); + require(newOracleRelayerFee >0, "the oracleRelayerFee must be greater than 0"); + oracleRelayerFee = newOracleRelayerFee; + } else if (Memory.compareStrings(key, "minDelegation")) { + require(value.length == 32, "length of minDelegation mismatch"); + uint256 newMinDelegation = BytesToTypes.bytesToUint256(32, value); + require(newMinDelegation > 0, "the minDelegation must be greater than 0"); + minDelegation = newMinDelegation; + } else { + require(false, "unknown param"); + } + emit paramChange(key, value); + } + + /************************* Handle cross-chain package *************************/ + function _handleDelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + amount = uint256(iter.next().toUint()); + } else if (idx == 3) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + require(ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount), "withdraw from tokenhub failed"); + + delegated[delegator] = delegated[delegator].sub(amount); + undelegated[delegator] = undelegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].sub(amount); + + emit failedDelegate(delegator, validator, amount, errCode); + } + + function _handleDelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + require(ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount), "withdraw from tokenhub failed"); + + delegated[delegator] = delegated[delegator].sub(amount); + undelegated[delegator] = undelegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].sub(amount); + + emit crashResponse(EVENT_DELEGATE); + } + + function _handleUndelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + amount = uint256(iter.next().toUint()); + } else if (idx == 3) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + delegated[delegator] = delegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].add(amount); + pendingUndelegateTime[delegator][validator] = 0; + + emit failedUndelegate(delegator, validator, amount, errCode); + } + + function _handleUndelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address validator; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + validator = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + delegated[delegator] = delegated[delegator].add(amount); + delegatedOfValidator[delegator][validator] = delegatedOfValidator[delegator][validator].add(amount); + pendingUndelegateTime[delegator][validator] = 0; + + emit crashResponse(EVENT_UNDELEGATE); + } + + function _handleRedelegateAckPackage(RLPDecode.Iterator memory iter) internal { + bool success = false; + uint256 idx = 0; + address delegator; + address valSrc; + address valDst; + uint256 amount; + uint8 errCode; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + valSrc = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + valDst = address(uint160(iter.next().toAddress())); + } else if (idx == 3) { + amount = uint256(iter.next().toUint()); + } else if (idx == 4) { + errCode = uint8(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + delegatedOfValidator[delegator][valSrc] = delegatedOfValidator[delegator][valSrc].add(amount); + delegatedOfValidator[delegator][valDst] = delegatedOfValidator[delegator][valDst].sub(amount); + pendingRedelegateTime[delegator][valSrc][valDst] = 0; + pendingRedelegateTime[delegator][valDst][valSrc] = 0; + + emit failedRedelegate(delegator, valSrc, valDst, amount, errCode); + } + + function _handleRedelegateFailAckPackage(RLPDecode.Iterator memory paramBytes) internal { + RLPDecode.Iterator memory iter; + if (paramBytes.hasNext()) { + iter = paramBytes.next().toBytes().toRLPItem().iterator(); + } else { + require(false, "empty fail ack package"); + } + + bool success = false; + uint256 idx = 0; + address delegator; + address valSrc; + address valDst; + uint256 bcAmount; + while (iter.hasNext()) { + if (idx == 0) { + delegator = address(uint160(iter.next().toAddress())); + } else if (idx == 1) { + valSrc = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + valDst = address(uint160(iter.next().toAddress())); + } else if (idx == 3) { + bcAmount = uint256(iter.next().toUint()); + success = true; + } else { + break; + } + idx++; + } + require(success, "rlp decode package failed"); + + uint256 amount = bcAmount.mul(TEN_DECIMALS); + delegatedOfValidator[delegator][valSrc] = delegatedOfValidator[delegator][valSrc].add(amount); + delegatedOfValidator[delegator][valDst] = delegatedOfValidator[delegator][valDst].sub(amount); + pendingRedelegateTime[delegator][valSrc][valDst] = 0; + pendingRedelegateTime[delegator][valDst][valSrc] = 0; + + emit crashResponse(EVENT_REDELEGATE); + } + + function _handleDistributeRewardSynPackage(RLPDecode.Iterator memory iter) internal returns(uint32, bytes memory) { + bool success = false; + uint256 idx = 0; + uint256 amount; + address recipient; + while (iter.hasNext()) { + if (idx == 0) { + amount = uint256(iter.next().toUint()); + } else if (idx == 1) { + recipient = address(uint160(iter.next().toAddress())); + success = true; + } else { + break; + } + idx++; + } + if (!success) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_REWARD, amount, recipient, ERROR_FAIL_DECODE); + } + + bool ok = ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount); + if (!ok) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_REWARD, amount, recipient, ERROR_WITHDRAW_BNB); + } + + distributedReward[recipient] = distributedReward[recipient].add(amount); + + emit rewardReceived(recipient, amount); + return (CODE_OK, new bytes(0)); + } + + function _handleDistributeUndelegatedSynPackage(RLPDecode.Iterator memory iter) internal returns(uint32, bytes memory) { + bool success = false; + uint256 idx = 0; + uint256 amount; + address recipient; + address validator; + while (iter.hasNext()) { + if (idx == 0) { + amount = uint256(iter.next().toUint()); + } else if (idx == 1) { + recipient = address(uint160(iter.next().toAddress())); + } else if (idx == 2) { + validator = address(uint160(iter.next().toAddress())); + success = true; + } else { + break; + } + idx++; + } + if (!success) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_UNDELEGATED, amount, recipient, ERROR_FAIL_DECODE); + } + + bool ok = ITokenHub(TOKEN_HUB_ADDR).withdrawStakingBNB(amount); + if (!ok) { + return _encodeRefundPackage(EVENT_DISTRIBUTE_UNDELEGATED, amount, recipient, ERROR_WITHDRAW_BNB); + } + + pendingUndelegateTime[recipient][validator] = 0; + undelegated[recipient] = undelegated[recipient].add(amount); + + emit undelegatedReceived(recipient, validator, amount); + return (CODE_OK, new bytes(0)); + } +} diff --git a/contracts/System.sol b/contracts/System.sol index 7d64ddc2..bbfea7cd 100644 --- a/contracts/System.sol +++ b/contracts/System.sol @@ -17,6 +17,7 @@ contract System { uint8 constant public STAKING_CHANNELID = 0x08; uint8 constant public GOV_CHANNELID = 0x09; uint8 constant public SLASH_CHANNELID = 0x0b; + uint8 constant public CROSS_STAKE_CHANNELID = 0x10; uint16 constant public bscChainID = 0x0060; address public constant VALIDATOR_CONTRACT_ADDR = 0x0000000000000000000000000000000000001000; @@ -29,7 +30,7 @@ contract System { address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; address public constant CROSS_CHAIN_CONTRACT_ADDR = 0x0000000000000000000000000000000000002000; - + address public constant STAKING_CONTRACT_ADDR = 0x0000000000000000000000000000000000002001; modifier onlyCoinbase() { require(msg.sender == block.coinbase, "the message sender must be the block producer"); diff --git a/contracts/System.template b/contracts/System.template index 4ceba2da..7daf4f7d 100644 --- a/contracts/System.template +++ b/contracts/System.template @@ -17,6 +17,7 @@ contract System { uint8 constant public STAKING_CHANNELID = 0x08; uint8 constant public GOV_CHANNELID = 0x09; uint8 constant public SLASH_CHANNELID = 0x0b; + uint8 constant public CROSS_STAKE_CHANNELID = 0x10; uint16 constant public bscChainID = 0x{{bscChainId}}; {% if mock %} address public VALIDATOR_CONTRACT_ADDR; @@ -29,9 +30,10 @@ contract System { address public GOV_HUB_ADDR; address public TOKEN_MANAGER_ADDR; address public CROSS_CHAIN_CONTRACT_ADDR; + address public STAKING_CONTRACT_ADDR; function updateContractAddr(address valAddr, address slashAddr, address rewardAddr, address lightAddr, address tokenHubAddr, - address incentivizeAddr, address relayerHubAddr, address govHub, address tokenManagerAddr, address crossChain) external { + address incentivizeAddr, address relayerHubAddr, address govHub, address tokenManagerAddr, address crossChain, address staking) external { VALIDATOR_CONTRACT_ADDR = valAddr; SLASH_CONTRACT_ADDR = slashAddr; SYSTEM_REWARD_ADDR = rewardAddr; @@ -42,6 +44,7 @@ contract System { GOV_HUB_ADDR = govHub; TOKEN_MANAGER_ADDR = tokenManagerAddr; CROSS_CHAIN_CONTRACT_ADDR = crossChain; + STAKING_CONTRACT_ADDR = staking; }{% else %} address public constant VALIDATOR_CONTRACT_ADDR = 0x0000000000000000000000000000000000001000; address public constant SLASH_CONTRACT_ADDR = 0x0000000000000000000000000000000000001001; @@ -53,6 +56,7 @@ contract System { address public constant GOV_HUB_ADDR = 0x0000000000000000000000000000000000001007; address public constant TOKEN_MANAGER_ADDR = 0x0000000000000000000000000000000000001008; address public constant CROSS_CHAIN_CONTRACT_ADDR = 0x0000000000000000000000000000000000002000; + address public constant STAKING_CONTRACT_ADDR = 0x0000000000000000000000000000000000002001; {% endif %} {% if mock %} address public constant SYSTEM_ADDRESS = 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791; diff --git a/contracts/TokenHub.sol b/contracts/TokenHub.sol index 72a93e76..cd6a19dd 100644 --- a/contracts/TokenHub.sol +++ b/contracts/TokenHub.sol @@ -561,4 +561,10 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } return string(bep2Symbol); } + + function withdrawStakingBNB(uint256 amount) external override returns(bool) { + require(msg.sender == STAKING_CONTRACT_ADDR, "only staking system contract can call this function"); + payable(STAKING_CONTRACT_ADDR).transfer(amount); + return true; + } } diff --git a/contracts/TokenHub.template b/contracts/TokenHub.template index a2979006..03b8f3fc 100644 --- a/contracts/TokenHub.template +++ b/contracts/TokenHub.template @@ -561,4 +561,10 @@ contract TokenHub is ITokenHub, System, IParamSubscriber, IApplication, ISystemR } return string(bep2Symbol); } + + function withdrawStakingBNB(uint256 amount) external override returns(bool) { + require(msg.sender == STAKING_CONTRACT_ADDR, "only staking system contract can call this function"); + payable(STAKING_CONTRACT_ADDR).transfer(amount); + return true; + } } diff --git a/contracts/interface/ICrossChain.sol b/contracts/interface/ICrossChain.sol index 893c09f8..ad887f15 100644 --- a/contracts/interface/ICrossChain.sol +++ b/contracts/interface/ICrossChain.sol @@ -5,4 +5,4 @@ interface ICrossChain { * @dev Send package to Binance Chain */ function sendSynPackage(uint8 channelId, bytes calldata msgBytes, uint256 relayFee) external; -} \ No newline at end of file +} diff --git a/contracts/interface/IStaking.sol b/contracts/interface/IStaking.sol new file mode 100644 index 00000000..5d0db93c --- /dev/null +++ b/contracts/interface/IStaking.sol @@ -0,0 +1,30 @@ +pragma solidity 0.6.4; + +interface IStaking { + + function delegate(address validator, uint256 amount) external payable; + + function undelegate(address validator, uint256 amount) external payable; + + function redelegate(address validatorSrc, address validatorDst, uint256 amount) external payable; + + function claimReward() external returns(uint256); + + function claimUndeldegated() external returns(uint256); + + function getDelegated(address delegator, address validator) external view returns(uint256); + + function getTotalDelegated(address delegator) external view returns(uint256); + + function getDistributedReward(address delegator) external view returns(uint256); + + function getPendingRedelegateTime(address delegator, address valSrc, address valDst) external view returns(uint256); + + function getUndelegated(address delegator) external view returns(uint256); + + function getPendingUndelegateTime(address delegator, address validator) external view returns(uint256); + + function getOracleRelayerFee() external view returns(uint256); + + function getMinDelegation() external view returns(uint256); +} diff --git a/contracts/interface/ITokenHub.sol b/contracts/interface/ITokenHub.sol index 429001af..ac935c74 100644 --- a/contracts/interface/ITokenHub.sol +++ b/contracts/interface/ITokenHub.sol @@ -19,6 +19,5 @@ interface ITokenHub { function batchTransferOutBNB(address[] calldata recipientAddrs, uint256[] calldata amounts, address[] calldata refundAddrs, uint64 expireTime) external payable returns (bool); + function withdrawStakingBNB(uint256 amount) external returns(bool); } - - diff --git a/contracts/mock/MockTokenHub.sol b/contracts/mock/MockTokenHub.sol index 5d569fcb..46033607 100644 --- a/contracts/mock/MockTokenHub.sol +++ b/contracts/mock/MockTokenHub.sol @@ -37,6 +37,14 @@ contract MockTokenHub is ITokenHub { function setPanicBatchTransferOut(bool doPanic)external{ panicBatchTransferOut = doPanic; } + + function withdrawStakingBNB(uint256 amount) external override returns(bool) { + address STAKING_CONTRACT_ADDR = address(0x0000000000000000000000000000000000002001); + require(msg.sender == STAKING_CONTRACT_ADDR, + "only staking system contract can call this function"); + payable(STAKING_CONTRACT_ADDR).transfer(amount); + return true; + } } diff --git a/generate-genesis.js b/generate-genesis.js index 1c4cacbc..b4f447a6 100644 --- a/generate-genesis.js +++ b/generate-genesis.js @@ -38,6 +38,7 @@ require("./generate-tendermintlightclient"); require("./generate-relayerincentivizecontract"); require("./generate-crosschain"); require("./generate-slash"); +require("./generate-staking"); program.version("0.0.1") program.option( @@ -139,6 +140,11 @@ Promise.all([ "crossChain", "contracts/CrossChain.sol", "CrossChain" + ), + compileContract( + "staking", + "contracts/Staking.sol", + "Staking" ) ]).then(result => { diff --git a/generate-staking.js b/generate-staking.js new file mode 100644 index 00000000..6ba2540c --- /dev/null +++ b/generate-staking.js @@ -0,0 +1,31 @@ +const program = require("commander"); +const fs = require("fs"); +const nunjucks = require("nunjucks"); + +program.version("0.0.1"); +program.option( + "-t, --template