├── .github ├── ring16dep.png ├── ring16with.png ├── ring2dep.png ├── ring2with.png ├── ring4dep.png ├── ring4with.png ├── ring8dep.png ├── ring8with.png ├── paymentFlow.png ├── ring2depbars.png ├── ring4depbars.png ├── ring8depbars.png ├── ring16depbars.png ├── ring16withbars.png ├── ring2withbars.png ├── ring4withbars.png ├── ring8withbars.png ├── depositsVarRings.png ├── withdrawsVarRings.png ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── CONTRIBUTING.md ├── .gitignore ├── migrations ├── 1_initial_migration.js └── 2_deploy_contracts.js ├── .travis.yml ├── package.json ├── contracts ├── Migrations.sol ├── ERC223ReceivingContract.sol ├── bn256g1_tests.sol ├── LinkableRing_tests.sol ├── bn256g1.sol ├── LinkableRing.sol └── Mixer.sol ├── truffle.js ├── CODE_OF_CONDUCT.md ├── mixerAbi.js ├── README.md ├── test ├── orbital.js └── mobius.js ├── LICENSE ├── mobiusTutorial.md └── yarn.lock /.github/ring16dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring16dep.png -------------------------------------------------------------------------------- /.github/ring16with.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring16with.png -------------------------------------------------------------------------------- /.github/ring2dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring2dep.png -------------------------------------------------------------------------------- /.github/ring2with.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring2with.png -------------------------------------------------------------------------------- /.github/ring4dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring4dep.png -------------------------------------------------------------------------------- /.github/ring4with.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring4with.png -------------------------------------------------------------------------------- /.github/ring8dep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring8dep.png -------------------------------------------------------------------------------- /.github/ring8with.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring8with.png -------------------------------------------------------------------------------- /.github/paymentFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/paymentFlow.png -------------------------------------------------------------------------------- /.github/ring2depbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring2depbars.png -------------------------------------------------------------------------------- /.github/ring4depbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring4depbars.png -------------------------------------------------------------------------------- /.github/ring8depbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring8depbars.png -------------------------------------------------------------------------------- /.github/ring16depbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring16depbars.png -------------------------------------------------------------------------------- /.github/ring16withbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring16withbars.png -------------------------------------------------------------------------------- /.github/ring2withbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring2withbars.png -------------------------------------------------------------------------------- /.github/ring4withbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring4withbars.png -------------------------------------------------------------------------------- /.github/ring8withbars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/ring8withbars.png -------------------------------------------------------------------------------- /.github/depositsVarRings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/depositsVarRings.png -------------------------------------------------------------------------------- /.github/withdrawsVarRings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clearmatics/mobius/HEAD/.github/withdrawsVarRings.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | node_modules 3 | yarn-error.log 4 | coverage 5 | coverage.json 6 | allFiredEvents 7 | 8 | 9 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8.16.2" 4 | 5 | matrix: 6 | include: 7 | - os: linux 8 | dist: trusty 9 | before_script: 10 | - yarn install 11 | script: 12 | - yarn coverage 13 | 14 | -------------------------------------------------------------------------------- /migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const Ring_tests = artifacts.require("./LinkableRing_tests.sol"); 2 | 3 | const Mixer = artifacts.require("./Mixer.sol"); 4 | 5 | const bn256g1_tests = artifacts.require("./bn256g1_tests.sol"); 6 | 7 | module.exports = (deployer) => { 8 | deployer.deploy(bn256g1_tests); 9 | 10 | deployer.deploy(Ring_tests); 11 | 12 | deployer.deploy(Mixer); 13 | }; 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### All Submissions: 2 | 3 | * [ ] Have you followed the guidelines in our [Contributing document](CONTRIBUTING.md)? 4 | * [ ] Have you checked to ensure there aren't other open [Pull Requests](../../../pulls) for the same update/change? 5 | * [ ] Does your submission pass tests? 6 | * [ ] Have you lint your code locally prior to submission? 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Prerequisites 2 | 3 | * [ ] Are you running the latest version? 4 | * [ ] Are you reporting to the correct repository? 5 | * [ ] Did you perform a cursory search? 6 | 7 | For more information, see the [`CONTRIBUTING`](CONTRIBUTING.md) guide. 8 | 9 | ### Description 10 | 11 | [Description of the bug or feature] 12 | 13 | ### Steps to Reproduce 14 | 15 | 1. [First Step] 16 | 2. [Second Step] 17 | 3. [and so on...] 18 | 19 | **Expected behavior:** [What you expected to happen] 20 | 21 | **Actual behavior:** [What actually happened] 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mobius-truffle", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "repository": "https://github.com/clearmatics/mobius.git", 6 | "author": "opensource@clearmatics.com", 7 | "license": "LGPL-3.0+", 8 | "dependencies": { 9 | "big-integer": "1.6.48", 10 | "ganache-cli": "6.7.0", 11 | "json-bigint-string": "^1.0.0", 12 | "shell-escape": "^0.2.0", 13 | "solidity-coverage": "0.5.11", 14 | "tmp": "0.1.0", 15 | "truffle": "4.1.16" 16 | }, 17 | "scripts": { 18 | "testrpc": "ganache-cli --gasLimit 0xFFFFFFF", 19 | "test": "truffle test", 20 | "coverage": "solidity-coverage" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | contract Migrations { 8 | address public owner; 9 | uint256 public last_completed_migration; 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function Migrations() public { 16 | owner = msg.sender; 17 | } 18 | 19 | function setCompleted(uint256 completed) public restricted { 20 | last_completed_migration = completed; 21 | } 22 | 23 | function upgrade(address new_address) public restricted { 24 | Migrations upgraded = Migrations(new_address); 25 | upgraded.setCompleted(last_completed_migration); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | compilers: { 3 | solc: { 4 | version: "^0.4.19" 5 | } 6 | }, 7 | networks: { 8 | development: { 9 | host: "localhost", 10 | port: 8545, 11 | network_id: "*" // Match any network id 12 | }, 13 | ci: { 14 | host: "localhost", 15 | port: 8545, 16 | network_id: "*" // Match any network id 17 | }, 18 | coverage: { 19 | host: "localhost", 20 | port: 8555, 21 | network_id: "*", // Match any network id 22 | gas: 0xFFFFFFF, 23 | gasprice: 0x1 24 | } 25 | }, 26 | mocha: { 27 | useColors: true, 28 | enableTimeouts: false 29 | }, 30 | solc: { 31 | optimizer: { 32 | enabled: true, 33 | runs: 200 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /contracts/ERC223ReceivingContract.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | /* 8 | * ERC223 token compatible contract 9 | **/ 10 | contract ERC223ReceivingContract { 11 | // See: https://github.com/Dexaran/ERC223-token-standard/blob/Recommended/Receiver_Interface.sol 12 | struct Token { 13 | address sender; 14 | uint value; 15 | bytes data; 16 | bytes4 sig; 17 | } 18 | 19 | function tokenFallback(address from, uint value, bytes data) public pure { 20 | Token memory tkn; 21 | tkn.sender = from; 22 | tkn.value = value; 23 | tkn.data = data; 24 | uint32 u = uint32(data[3]) + (uint32(data[2]) << 8) + (uint32(data[1]) << 16) + (uint32(data[0]) << 24); 25 | tkn.sig = bytes4(u); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a 11 | build. 12 | 2. Update the README.md with details of changes to the interface, this includes new environment 13 | variables, exposed ports, useful file locations and container parameters. 14 | 3. Increase the version numbers in any examples files and the README.md to the new version that this 15 | Pull Request would represent. The versioning scheme we use is [SemVer][semver]. 16 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you 17 | do not have permission to do that, you may request the second reviewer to merge it for you. 18 | 19 | ## Code of Conduct 20 | 21 | This project and everyone participating in it is governed by the [Code of Conduct][codeofconduct]. By participating, you are expected to uphold this code. Please report unacceptable behavior to [opensource@clearmatics.com][email]. 22 | 23 | [codeofconduct]: ../CODE_OF_CONDUCT.md 24 | [semver]: http://semver.org/ 25 | [email]: mailto:opensource@clearmatics.com 26 | 27 | -------------------------------------------------------------------------------- /contracts/bn256g1_tests.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | import './bn256g1.sol'; 8 | 9 | contract bn256g1_tests { 10 | using bn256g1 for bn256g1.Point; 11 | 12 | function testIsOnCurve() public view returns (bool) { 13 | var g = bn256g1.generator(); 14 | 15 | require(g.isOnCurve()); 16 | 17 | var x = g.scalarMult(uint256(sha256("1"))); 18 | 19 | require(x.isOnCurve()); 20 | require(x.X == 0x28af4f278e71322e8e155dce4641e18ddb8ce0d4cee01d8ea9d052cf564e9029); 21 | require(x.Y == 0x71c77766b8f58944c18c66df8edac3c4ff5ab15e246e5f7457ae4fd6adb939c); 22 | require(!bn256g1.scalarBaseMult(0).isOnCurve()); 23 | 24 | return true; 25 | } 26 | 27 | function testHashToPoint() public view returns (bool) { 28 | var p = bn256g1.hashToPoint(sha256("hello world")); 29 | 30 | require(p.isOnCurve()); 31 | require(p.X == 18149469767584732552991861025120904666601524803017597654373315627649680264678); 32 | require(p.Y == 18593544354303197021588991433499968191850988132424885073381608163097237734820); 33 | 34 | return true; 35 | } 36 | 37 | function testNegate() public view returns (bool) { 38 | var g = bn256g1.generator(); 39 | var x = g.pointAdd(g.negate()); 40 | 41 | require(x.isInfinity()); 42 | 43 | return true; 44 | } 45 | 46 | function testIdentity() public view returns (bool) { 47 | require(bn256g1.scalarBaseMult(0).isInfinity()); 48 | 49 | return true; 50 | } 51 | 52 | function testEquality() public view returns (bool) { 53 | var g = bn256g1.generator(); 54 | var a = g.scalarMult(9).pointAdd(g.scalarMult(5)); 55 | var b = g.scalarMult(12).pointAdd(g.scalarMult(2)); 56 | 57 | require(a.equal(b)); 58 | 59 | return true; 60 | } 61 | 62 | function testOrder() public view returns (bool) { 63 | var z = bn256g1.scalarBaseMult(bn256g1.genOrder()); 64 | require(z.isInfinity()); 65 | 66 | var one = bn256g1.scalarBaseMult(1); 67 | var x = z.pointAdd(one); 68 | require(x.X == one.X && x.Y == one.Y); 69 | 70 | return true; 71 | } 72 | 73 | function testModExp() public view returns (bool) { 74 | uint256 a; 75 | 76 | a = bn256g1.expMod(33, 2, 100); 77 | require(a == 89); 78 | 79 | a = bn256g1.expMod(50, 2, 100); 80 | require(a == 0); 81 | 82 | a = bn256g1.expMod(51, 2, 100); 83 | require(a == 1); 84 | 85 | return true; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [opensource@clearmatics.com][email]. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [email]: mailto:opensource@clearmatics.com 46 | [homepage]: http://contributor-covenant.org 47 | [version]: http://contributor-covenant.org/version/1/4/ 48 | -------------------------------------------------------------------------------- /contracts/LinkableRing_tests.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | import './LinkableRing.sol'; 8 | 9 | contract LinkableRing_tests { 10 | using LinkableRing for LinkableRing.Data; 11 | 12 | LinkableRing.Data internal m_ring; 13 | 14 | function LinkableRing_tests() public { 15 | // Nothing 16 | } 17 | 18 | function testInit() public returns (bool) { 19 | delete m_ring; 20 | 21 | require(!m_ring.isInitialized()); 22 | require(m_ring.isDead()); 23 | 24 | initTestRing(); 25 | 26 | require(!m_ring.isFull()); 27 | require(!m_ring.isDead()); 28 | 29 | return true; 30 | } 31 | 32 | function testVerify() public returns (bool) { 33 | initTestRing(); 34 | fillTestRing(); 35 | 36 | uint256[] memory ctlist = new uint256[](8); 37 | ctlist[0] = 20853301309224204140850907483145190973044613001758378871848115918385899219387; 38 | ctlist[1] = 9317131247297195885946346699744650907176126179419614612840844384077063186425; 39 | ctlist[2] = 20898468494972458585245059452949535846887121970230559918336684328791066147747; 40 | ctlist[3] = 2986143557871053785334761070644999793151956676132652606589985706762137398754; 41 | ctlist[4] = 10455017181508360833815002569095435558520129924248346429838424769628897243093; 42 | ctlist[5] = 7706146382413050422535575572291511409490627421923647014400327046464988688885; 43 | ctlist[6] = 446022580115833093457380747787879591969245085567346575340759689027920458706; 44 | ctlist[7] = 16400172916399253914651469367823034567665816937929536474245909361083746809541; 45 | 46 | var ok = m_ring.isSignatureValid(13495246100508828436129396215696389042103917384015723197132056291949822869447, 17179563752757494496597752941318743229705747077314286085295431297834666711491, ctlist); 47 | require( ok ); 48 | 49 | return ok; 50 | } 51 | 52 | function testParticipate() public returns (bool) { 53 | initTestRing(); 54 | fillTestRing(); 55 | 56 | var ok = m_ring.pubExists(15201544523224716611047554162655318369326098920760992806294282873621188361302); 57 | require(ok == true); 58 | require(m_ring.isFull()); 59 | require(m_ring.message() == 0x291a6780850827fcd8621d0e5471343831109bc14142ec101527b048bb3d1794); 60 | 61 | return true; 62 | } 63 | 64 | function initTestRing() internal { 65 | delete m_ring; 66 | 67 | var guid = sha256("1"); 68 | var ok = m_ring.initialize(guid); 69 | require(ok == true); 70 | require(m_ring.isInitialized()); 71 | require(!m_ring.isFull()); 72 | } 73 | 74 | function fillTestRing() internal { 75 | var ok = m_ring.addParticipant( 15201544523224716611047554162655318369326098920760992806294282873621188361302, 8049887880302834643867918893986801628784209472486881120173132635179564996750 ); 76 | require(ok == true); 77 | require(!m_ring.isFull()); 78 | 79 | ok = m_ring.addParticipant(2864146953215387991650307853187221646929890249230753473970630963555211270830, 19974888627227247767725306386952207830369770978312010830473870330715216459888 ); 80 | require(ok == true); 81 | 82 | ok = m_ring.addParticipant(11802586219790549114106218615216140214135730687869911031682317746534851646642, 18469118937248172961432772506316070842797392576874035050327233601294937134214); 83 | require(ok == true); 84 | 85 | ok = m_ring.addParticipant(14750767202794174494069895486860808993207681341774320026808054547344054421581, 12924920412071921826297345645283965810489658634968309881653899964121243502566 ); 86 | require(ok == true); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /mixerAbi.js: -------------------------------------------------------------------------------- 1 | var MixerAbi={"contracts":{"contracts/ERC223ReceivingContract.sol:ERC223ReceivingContract":{"abi":"[{\"constant\":true,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"tokenFallback\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]"},"contracts/LinkableRing.sol:LinkableRing":{"abi":"[{\"constant\":true,\"inputs\":[],\"name\":\"RING_SIZE\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]"},"contracts/Mixer.sol:ERC20Compatible":{"abi":"[{\"constant\":false,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"to\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]"},"contracts/Mixer.sol:Mixer":{"abi":"[{\"constant\":true,\"inputs\":[{\"name\":\"ring_guid\",\"type\":\"bytes32\"}],\"name\":\"message\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"token\",\"type\":\"address\"},{\"name\":\"denomination\",\"type\":\"uint256\"},{\"name\":\"pub_x\",\"type\":\"uint256\"},{\"name\":\"pub_y\",\"type\":\"uint256\"}],\"name\":\"depositERC20Compatible\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ring_id\",\"type\":\"bytes32\"},{\"name\":\"tag_x\",\"type\":\"uint256\"},{\"name\":\"tag_y\",\"type\":\"uint256\"},{\"name\":\"ctlist\",\"type\":\"uint256[]\"}],\"name\":\"withdrawERC20Compatible\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"from\",\"type\":\"address\"},{\"name\":\"value\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"tokenFallback\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"token\",\"type\":\"address\"},{\"name\":\"denomination\",\"type\":\"uint256\"},{\"name\":\"pub_x\",\"type\":\"uint256\"},{\"name\":\"pub_y\",\"type\":\"uint256\"}],\"name\":\"depositEther\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"ring_id\",\"type\":\"bytes32\"},{\"name\":\"tag_x\",\"type\":\"uint256\"},{\"name\":\"tag_y\",\"type\":\"uint256\"},{\"name\":\"ctlist\",\"type\":\"uint256[]\"}],\"name\":\"withdrawEther\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ring_id\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"pub_x\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"LogMixerDeposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ring_id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"tag_x\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"LogMixerWithdraw\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ring_id\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"message\",\"type\":\"bytes32\"}],\"name\":\"LogMixerReady\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"ring_id\",\"type\":\"bytes32\"}],\"name\":\"LogMixerDead\",\"type\":\"event\"}]"},"contracts/bn256g1.sol:bn256g1":{"abi":"[]"}},"version":"0.4.20+commit.3155dd80.Linux.g++"} 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Möbius 2 | 3 | [![Build Status](https://travis-ci.org/clearmatics/mobius.svg?branch=master)](https://travis-ci.org/clearmatics/mobius) 4 | 5 | Trustless Tumbling for Transaction Privacy 6 | 7 | 8 | ## Introduction 9 | 10 | Möbius is a Smart Contract that runs on Ethereum that offers trustless autonomous tumbling using linkable ring signatures. 11 | 12 | **This proof of concept is still evolving and comes with the caveat that it should not be used for anything other than a technology demonstration.** 13 | 14 | 15 | ## White Paper 16 | 17 | [S. Meiklejohn, R. Mercer. Möbius: Trustless Tumbling for Transaction Privacy][1] 18 | 19 | 20 | ## Using Möbius 21 | 22 | :point_right: **See the full [Tutorial](./mobiusTutorial.md)** 23 | 24 | ----------------------------------------------------- 25 | 26 | Möbius supports ether and ERC20 compatible token transactions. 27 | In order to use the Mixer with ERC20 compatible tokens, the `DepositERC20Compatible` and `WithdrawERC20Compatible` functions must be used. 28 | However, in order to do an ether transaction, one has to use the `DepositEther` and `WithdrawEther` functions. 29 | 30 | ----------------------------------------------------- 31 | 32 | To tumble a token it is deposited into the [Mixer](contracts/Mixer.sol) smart contract by sending the token and the stealth public key of the receiver to the `Deposit` method. 33 | 34 | The Mixer contract places the token into an unfilled [Ring](contracts/LinkableRing.sol) specific to that token and denomination and provides the GUID of the Ring. The current ring size is 4, so when 3 other people deposit the same denomination of token into the Mixer the Ring will have filled. Tokens can only be withdrawn when the Ring is full. 35 | 36 | The receiver then generates a linkable ring signature using their stealth private key, this signature and the Ring GUID is provided to the `Withdraw` method in exchange for the token. 37 | 38 | The lifecycle and state of the Mixer and Rings is monitored using the following Events: 39 | 40 | * `LogMixerDeposit` - Tokens have been deposited into a Ring, includes: Ring GUID, Receiver Public Key, Token, Value 41 | * `LogMixerReady` - Withdrawals can be now me made, includes: Ring GUID, Signing Message 42 | * `LogMixerWithdraw` - Tokens have been withdrawn from a Ring, includes: Ring GUID, Tag, Token, Value 43 | * `LogMixerDead` - All tokens have been withdrawn from a Ring, includes: Ring GUID 44 | 45 | The [Orbital](https://github.com/clearmatics/orbital) tool can be used to create the necessary keys and to create and verify compatible ring signatures, for details see the [Orbital Integration Tests](test/orbital.js). 46 | 47 | 48 | ## Caveats 49 | 50 | * #34 - Gas payer exposes sender/receiver 51 | * #22 - Only Ether is presently supported 52 | * #32 - Tokens are locked into the Ring until it's filled 53 | * #12 - Withdraw messages can be replayed 54 | 55 | 56 | ## Gas Usage 57 | 58 | Despite being an improvement over the previous iteration which used a Solidity P256k1 implementation, the new alt_bn128 opcodes are still expensive and there are many improvements which can be made to reduce these costs further. If you have any interesting optimisations or solutions to remove storage and memory operations please open an issue. 59 | 60 | Currently the Gas usage is: 61 | 62 | | Function | Avg | 63 | | -------- | ------- | 64 | | Deposit | 150k | 65 | | Withdraw | 725k | 66 | 67 | ## Developing 68 | 69 | [Truffle][2] is used to develop and test the Möbius Smart Contract. This has a dependency on [Node.js][3]. [solidity-coverage][7] provides code coverage metrics. 70 | 71 | Prerequisites: 72 | 73 | [yarn][4] needs to be installed (but [npm][5] should work just as well). 74 | 75 | yarn install 76 | 77 | This will install all the required packages. 78 | 79 | Start `testrpc` in a separate terminal tab or window. 80 | 81 | yarn testrpc 82 | 83 | # in separate window or tab 84 | yarn test 85 | 86 | This will compile the contract, deploy to the Ganache instance and run the tests. 87 | 88 | 89 | #### Testing with Orbital 90 | 91 | The [Orbital][6] tool is needed to generate the signatures and random keys for some of the tests. If `orbital` is in `$PATH` the `yarn test` command will run additional tests which verify the functionality of the Mixer contract using randomly generated keys instead of the fixed test cases. 92 | 93 | [1]: https://eprint.iacr.org/2017/881.pdf 94 | [2]: http://truffleframework.com/ 95 | [3]: https://nodejs.org/ 96 | [4]: https://yarnpkg.com/en/docs/install 97 | [5]: https://docs.npmjs.com/getting-started/installing-node 98 | [6]: https://github.com/clearmatics/orbital 99 | [7]: https://www.npmjs.com/package/solidity-coverage 100 | -------------------------------------------------------------------------------- /test/orbital.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | const fs = require('fs'); 6 | const path = require('path'); 7 | const shellescape = require('shell-escape'); 8 | const { execSync } = require('child_process'); 9 | const tmp = require("tmp"); 10 | var JSONBigInt = require('json-bigint-string'); 11 | 12 | const Mixer = artifacts.require("./Mixer.sol"); 13 | 14 | // Implements functionality similar to the 'which' command 15 | function which (name, defaultPath) { 16 | var X; 17 | try { 18 | X = execSync("/usr/bin/which " + name).toString(); 19 | } 20 | catch (err) { 21 | return defaultPath; 22 | } 23 | return X.trim("\n"); 24 | } 25 | 26 | // Filesystem path of the 'orbital' tool 27 | const defaultOrbitalBinPath = "/home/user/go/src/github.com/clearmatics/orbital/orbital"; 28 | function findOrbital () { 29 | var foundWithWhich = which("orbital", defaultOrbitalBinPath); 30 | if( ! foundWithWhich || ! fs.existsSync(foundWithWhich) ) { 31 | return null; 32 | } 33 | return foundWithWhich; 34 | } 35 | 36 | // Execute `orbital` command, with array of arguments 37 | const orbitalPath = findOrbital(); 38 | function orbital (args) { 39 | return execSync(shellescape([orbitalPath].concat(args))).toString().trim("\n"); 40 | } 41 | 42 | // Only run these integration tests when the `orbital` tool is present 43 | if( orbitalPath ) { 44 | async function writeToTemp(data) { 45 | var tmp_file = tmp.fileSync(); 46 | await new Promise((resolve, reject) => { 47 | fs.write(tmp_file.fd, JSON.stringify(data), (err) => { 48 | if( err ) 49 | reject(err); 50 | else { 51 | resolve(); 52 | } 53 | }); 54 | }); 55 | return tmp_file; 56 | } 57 | 58 | contract('Mixer', (accounts) => { 59 | it('Integrates with Orbital', async () => { 60 | // Generate 4 keys 61 | const keys_txt = orbital(['generate', '-n', '4']); 62 | const keys = JSONBigInt.parse(keys_txt); 63 | var keys_file = await writeToTemp(keys); 64 | 65 | // Deposit 1 Wei into mixer 66 | const txValue = 1; 67 | const owner = accounts[0]; 68 | const token = 0; // 0 = ether 69 | const txObj = { from: owner, value: txValue }; 70 | const logDepositEvent = 'LogMixerDeposit'; 71 | const logReadyEvent = 'LogMixerReady'; 72 | const logDeadEvent = 'LogMixerDead'; 73 | 74 | let instance = await Mixer.deployed(); 75 | const initialBalance = web3.eth.getBalance(instance.address); 76 | 77 | // For each key in inputs, deposit into the Ring 78 | var ring_msg = null; 79 | var ring_guid = null; 80 | var k = 0; 81 | for( var j in keys.pubkeys ) { 82 | const pubkey = keys.pubkeys[j]; 83 | k++; 84 | 85 | let result = await instance.depositEther(token, txValue, pubkey.x, pubkey.y, txObj); 86 | assert.ok(result.receipt.status, "Bad deposit status"); 87 | 88 | const depositEvent = result.logs.find(el => (el.event === logDepositEvent)); 89 | ring_guid = depositEvent.args.ring_id.toString(); 90 | 91 | const readyEvent = result.logs.find(el => (el.event === logReadyEvent)); 92 | if( readyEvent ) { 93 | ring_msg = readyEvent.args.message.toString().substr(2); 94 | } 95 | } 96 | 97 | // Contract balance should have increased to equal the N deposits 98 | const contractBalance = web3.eth.getBalance(instance.address); 99 | assert.equal(contractBalance.toString(), initialBalance.add(txValue * k).toString()); 100 | 101 | // Generate inputs from ring keys 102 | const inputs_txt = orbital(['inputs', '-f', keys_file.name, '-n', '4', '-m', ring_msg]); 103 | const inputs = JSON.parse(inputs_txt); 104 | 105 | // Verify signatures validate in orbital tool 106 | var inputs_file = await writeToTemp(inputs); 107 | const inputs_verified = orbital(['verify', '-f', inputs_file.name, '-m', ring_msg]); 108 | assert.equal(inputs_verified, "Signatures verified", "Orbital could not verify signatures"); 109 | 110 | // Then perform all the withdraws 111 | var result = null; 112 | var total_gas = 0; 113 | var i = 0; 114 | for( var k in inputs.signatures ) { 115 | i++; 116 | 117 | // Verify the withdraw signature works 118 | const sig = inputs.signatures[k]; 119 | const tau = sig.tau; 120 | const ctlist = sig.ctlist; 121 | result = await instance.withdrawEther(ring_guid, tau.x, tau.y, ctlist); 122 | assert.ok(result.receipt.status, "Bad withdraw status"); 123 | total_gas += result.receipt.gasUsed; 124 | 125 | // Verify same signature can't withdraw twice 126 | var ok = false; 127 | await instance.withdrawEther(ring_guid, tau.x, tau.y, ctlist).catch(function(err) { 128 | assert.include(err.message, 'revert', 'Withdraw twice should fail'); 129 | ok = true; 130 | }); 131 | if( ! ok ) 132 | assert.fail("Duplicate withdraw didn't fail!"); 133 | } 134 | 135 | console.log("\tAverage Gas per Withdraw: " + (total_gas / i)); 136 | 137 | // Verify the Ring is dead 138 | const expectedMixerDead = result.logs.some(el => (el.event === logDeadEvent)); 139 | assert.ok(expectedMixerDead, "Last Withdraw should emit MixerDead event"); 140 | 141 | const deadEvent = result.logs.find(el => (el.event === logDeadEvent)); 142 | assert.equal(deadEvent.args.ring_id.toString(), ring_guid, "Ring GUID batch doesn't match in MixerDead"); 143 | 144 | // And that all money has been withdrawn 145 | const finishBalance = web3.eth.getBalance(instance.address); 146 | assert.equal(finishBalance.toString(), initialBalance.toString(), "Finish balance should be same as initial balance"); 147 | 148 | inputs_file.removeCallback(); 149 | keys_file.removeCallback(); 150 | }); 151 | }); 152 | } 153 | -------------------------------------------------------------------------------- /test/mobius.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | const bigInt = require("big-integer"); 6 | var JSONBigInt = require('json-bigint-string'); 7 | 8 | const LinkableRing_tests = artifacts.require("./LinkableRing_tests.sol"); 9 | const Mixer = artifacts.require("./Mixer.sol"); 10 | const bn256g1_tests = artifacts.require("./bn256g1_tests.sol"); 11 | 12 | // XXX: truffle solidity tests are a lil broken due to the 'import' bug 13 | // e.g. the imports in contracts/ are relative to the CWD not the source file 14 | // this means when compiling the tests the CWD is the project root, so 15 | // conflicting paths... 16 | const testContracts = { 17 | LinkableRing_tests: LinkableRing_tests, 18 | bn256g1_tests: bn256g1_tests 19 | }; 20 | 21 | const allSimpleTests = { 22 | bn256g1_tests: [ 23 | "testIsOnCurve", 24 | "testHashToPoint", 25 | "testNegate", 26 | "testIdentity", 27 | "testEquality", 28 | "testOrder", 29 | "testModExp" 30 | ], 31 | LinkableRing_tests: [ 32 | "testInit", 33 | "testVerify", 34 | "testParticipate" 35 | ] 36 | }; 37 | 38 | Object.keys(allSimpleTests).forEach(function(k) { 39 | var obj = testContracts[k]; 40 | contract(k, (accounts) => { 41 | allSimpleTests[k].forEach(function (name) { 42 | it(name, (done) => { 43 | obj.deployed().then((instance) => { 44 | const txObj = {from: accounts[0]}; 45 | instance[name].call(txObj).then(result => { 46 | assert.ok(result, k + "." + name + " expected true!"); 47 | done(); 48 | }); 49 | }); 50 | }); 51 | }); 52 | }); 53 | }); 54 | 55 | // Random point on the alt_bn128 curve 56 | function RandomPoint () { 57 | const P = bigInt("21888242871839275222246405745257275088696311157297823662689037894645226208583"); 58 | const N = bigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617"); 59 | const A = bigInt("5472060717959818805561601436314318772174077789324455915672259473661306552146"); 60 | while( true ) { 61 | const x = bigInt.randBetween(1, N.prev()); 62 | const beta = x.multiply(x).mod(P).multiply(x).mod(P).add(3).mod(P); 63 | const y = beta.modPow(A, P); 64 | const y_squared = y.multiply(y).mod(P); 65 | if( y_squared.eq(beta) ) { 66 | return {x: x.toString(), y: y.toString()}; 67 | } 68 | } 69 | } 70 | 71 | function CreateDummyTx(account, value) { 72 | return { from: account, value: value }; 73 | } 74 | 75 | contract('Mixer', (accounts) => { 76 | it('Invalid and duplicate deposits', async () => { 77 | var point = RandomPoint(); 78 | 79 | const txObj = CreateDummyTx(accounts[0], 1); 80 | const token = 0; // 0 = ether 81 | 82 | let instance = await Mixer.deployed(); 83 | 84 | // This should succeed 85 | let result = await instance.depositEther(token, txObj.value, point.x, point.y, txObj); 86 | assert.ok(result.receipt.status, "Bad deposit status with valid point"); 87 | 88 | // This will fail because the point is already in a ring 89 | var ok = false; 90 | result = await instance.depositEther(token, txObj.value, point.x, point.y, txObj).catch(function(err) { 91 | assert.include(err.message, 'revert', 'Deposit with duplicate key should revert'); 92 | ok = true; 93 | }); 94 | if(!ok) { 95 | assert.fail("Deposit with duplicate key should revert"); 96 | } 97 | 98 | // This will fail because the point is invalid 99 | point = RandomPoint(); 100 | ok = false; 101 | result = await instance.depositEther(token, txObj.value, 123, point.y, txObj).catch(function(err) { 102 | assert.include(err.message, 'revert', 'Deposit with invalid point should revert'); 103 | ok = true; 104 | }); 105 | if(!ok) { 106 | assert.fail("Deposit with invalid point should have reverted!"); 107 | } 108 | 109 | // This will fail because the denomination is invalid 110 | ok = false; 111 | result = await instance.depositEther(token, 0, point.x, point.y, txObj).catch(function(err) { 112 | assert.include(err.message, 'revert', 'Deposit with invalid denomination should revert'); 113 | ok = true; 114 | }); 115 | if(!ok) { 116 | assert.fail("Deposit with invalid denomination should revert"); 117 | } 118 | 119 | // Then fill the ring with a remaining 3, otherwise further tests will fail 120 | for( var i = 0; i < 3; i++ ) { 121 | point = RandomPoint(); 122 | result = await instance.depositEther(token, txObj.value, point.x, point.y, txObj); 123 | } 124 | }); 125 | 126 | it('Events and basic functionality', async () => { 127 | let instance = await Mixer.deployed(); 128 | 129 | // Deposit 1 Wei into mixer 130 | const txValue = 1; 131 | const owner = accounts[0]; 132 | const token = 0; // 0 = ether 133 | const txObj = { from: owner, value: txValue }; 134 | const startingBalance = web3.eth.getBalance(instance.address); 135 | const ringSize = 4; 136 | const logDepositEvent = 'LogMixerDeposit'; 137 | const logReadyEvent = 'LogMixerReady'; 138 | 139 | // Deposit 4 times (the ring size) into the mixer 140 | // Verify: 141 | // - Mixer accepts deposits 142 | // - Mixer emits LogMixerDeposit event for each deposit 143 | // - Last deposit also emits MixerReady message 144 | var i = 0; 145 | var results = []; 146 | var ring_guid = null; 147 | var total_gas = 0; 148 | while(i < (ringSize * 2)) { 149 | i++; 150 | // Deposit a random public key 151 | const point = RandomPoint(); 152 | let result = await instance.depositEther(token, txValue, point.x, point.y, txObj); 153 | assert.ok(result.receipt.status, "Bad deposit status"); 154 | total_gas += result.receipt.gasUsed; 155 | 156 | // Balance should increase by 1 Wei each deposit 157 | const contractBalance = web3.eth.getBalance(instance.address); 158 | assert.equal(contractBalance.toString(), startingBalance.add(txValue * i).toString()); 159 | 160 | // A deposit event should be triggered 161 | const expectedMixerDeposit = result.logs.some(el => (el.event === logDepositEvent)); 162 | assert.ok(expectedMixerDeposit, "Deposit event was not emitted"); 163 | 164 | // Ring GUID should match the previous one 165 | const depositEvent = result.logs.find(el => (el.event === logDepositEvent)); 166 | if( ring_guid !== null ) { 167 | assert.equal(depositEvent.args.ring_id.toString(), ring_guid, "Ring GUID batch doesn't match"); 168 | } 169 | else { 170 | ring_guid = depositEvent.args.ring_id.toString(); 171 | } 172 | 173 | // For every N deposits, verify a ready event has triggered 174 | const isLast = 0 == (i % ringSize); 175 | if( isLast ) { 176 | const expectedMixerReady = result.logs.some(el => (el.event === logReadyEvent)); 177 | assert.ok(expectedMixerReady, "Ready event was not emitted"); 178 | 179 | const readyEvent = result.logs.find(el => (el.event === logReadyEvent)); 180 | assert.equal(readyEvent.args.ring_id, ring_guid, "Ring GUID batch doesn't match"); 181 | 182 | ring_guid = null; 183 | } 184 | } 185 | console.log("\tAverage Gas per Deposit: " + (total_gas / i)); 186 | }); 187 | }); 188 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /contracts/bn256g1.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | /* 8 | * This module wraps the alt_bn128 G1 Elliptic Curve functions into 9 | * a helpful and consistent library which provides familiar function 10 | * names and usage to Elliptic Curve libraries in other languages. 11 | * 12 | * This curve is described in the IACR paper 2010/429 13 | * 14 | * - https://eprint.iacr.org/2010/429 15 | * A Family of Implementation-Friendly BN Elliptic Curves 16 | * 17 | * Specified in the following EIPs: 18 | * 19 | * - https://github.com/ethereum/EIPs/pull/213 20 | * - https://github.com/ethereum/EIPs/pull/212 21 | * 22 | * The 𝔾1 curve is of the form: 23 | * 24 | * (E_b : y^2 = x^3 + b) over 𝔽_p 25 | * 26 | * Where: 27 | * 28 | * p ≡ 3 (mod 4) 29 | * b = 3 30 | * sqrt(a) = a^((p+1)/4) 31 | * 32 | * The primes `p` (field modulus) and `n` (order) are given by: 33 | * 34 | * p = p(u) = 36u^4 + 36u^3 + 24u^2 + 6u + 1 35 | * n = n(u) = 36u^4 + 36u^3 + 18u^2 + 6u + 1 36 | * 37 | * The BN field 𝔽_p contains a primitive cube root of unity, this makes 38 | * it very easy to implement using integer operations on a computer. 39 | * 40 | * For more details, refer to the IACR paper, we have tried to ensure 41 | * that the variable names and comments throughout this library make it 42 | * easier for cryptographers, mathematicians and programmers alike to 43 | * use the same terminology across multiple domains without confusion. 44 | * 45 | * The parameters used by the ALT_BN128 curve implemented in Ethereum are: 46 | * 47 | * p = 21888242871839275222246405745257275088696311157297823662689037894645226208583 48 | * n = 21888242871839275222246405745257275088548364400416034343698204186575808495617 49 | * b = 3 50 | * u = 4965661367192848881 51 | * a = 5472060717959818805561601436314318772174077789324455915672259473661306552146 52 | **/ 53 | 54 | library bn256g1 { 55 | // p = p(u) = 36u^4 + 36u^3 + 24u^2 + 6u + 1 56 | uint256 internal constant FIELD_ORDER = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47; 57 | 58 | // Number of elements in the field (often called `q`) 59 | // n = n(u) = 36u^4 + 36u^3 + 18u^2 + 6u + 1 60 | uint256 internal constant GEN_ORDER = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001; 61 | 62 | uint256 internal constant CURVE_B = 3; 63 | 64 | // a = (p+1) / 4 65 | uint256 internal constant CURVE_A = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52; 66 | 67 | struct Point { 68 | uint256 X; 69 | uint256 Y; 70 | } 71 | 72 | function genOrder() internal pure returns (uint256) { 73 | return GEN_ORDER; 74 | } 75 | 76 | function fieldOrder() internal pure returns (uint256) { 77 | return FIELD_ORDER; 78 | } 79 | 80 | function infinity() internal pure returns (Point) { 81 | return Point(0, 0); 82 | } 83 | 84 | function generator() internal pure returns (Point) { 85 | return Point(1, 2); 86 | } 87 | 88 | function equal(Point a, Point b) internal pure returns (bool) { 89 | return a.X == b.X && a.Y == b.Y; 90 | } 91 | 92 | /* 93 | * Return the negation of p, i.e. p.add(p.negate()) should be zero. 94 | **/ 95 | function negate(Point p) internal pure returns (Point) { 96 | if(p.X == 0 && p.Y == 0) { 97 | return Point(0, 0); 98 | } 99 | // TODO: SubMod function? 100 | return Point(p.X, FIELD_ORDER - (p.Y % FIELD_ORDER)); 101 | } 102 | 103 | /* 104 | * Using a hashed value as the initial starting X point, find the 105 | * nearest (X,Y) point on the curve. The input must be hashed first. 106 | * 107 | * Example: 108 | * 109 | * hashToPoint(sha256("hello world")) 110 | * 111 | * XXX: this isn't constant time! 112 | * 113 | * This implements the try-and-increment method of hashing a scalar 114 | * into a curve point. For more information see: 115 | * 116 | * - https://iacr.org/archive/crypto2009/56770300/56770300.pdf 117 | * How to Hash into Elliptic Curves 118 | * 119 | * - https://www.normalesup.org/~tibouchi/papers/bnhash-scis.pdf 120 | * A Note on Hashing to BN Curves 121 | **/ 122 | function hashToPoint(bytes32 s) internal view returns (Point) { 123 | uint256 beta = 0; 124 | uint256 y = 0; 125 | 126 | // XXX: Gen Order (n) or Field Order (p) ? 127 | uint256 x = uint256(s) % GEN_ORDER; 128 | 129 | while( true ) { 130 | (beta, y) = findYforX(x); 131 | 132 | // y^2 == beta 133 | if(beta == mulmod(y, y, FIELD_ORDER)) { 134 | return Point(x, y); 135 | } 136 | 137 | x = addmod(x, 1, FIELD_ORDER); 138 | } 139 | } 140 | 141 | /* 142 | * Given X, find Y 143 | * 144 | * where y = sqrt(x^3 + b) 145 | * 146 | * Returns: (x^3 + b), y 147 | **/ 148 | function findYforX(uint256 x) internal view returns (uint256, uint256) { 149 | // beta = (x^3 + b) % p 150 | uint256 beta = addmod(mulmod(mulmod(x, x, FIELD_ORDER), x, FIELD_ORDER), CURVE_B, FIELD_ORDER); 151 | 152 | // y^2 = x^3 + b 153 | // this acts like: y = sqrt(beta) 154 | uint256 y = expMod(beta, CURVE_A, FIELD_ORDER); 155 | 156 | return (beta, y); 157 | } 158 | 159 | function isInfinity(Point p) internal pure returns (bool) { 160 | return p.X == 0 && p.Y == 0; 161 | } 162 | 163 | /* 164 | * Verify if the X and Y coordinates represent a valid Point on the Curve 165 | * 166 | * Where the G1 curve is: x^2 = x^3 + b 167 | **/ 168 | function isOnCurve(Point p) internal pure returns (bool) { 169 | uint256 p_squared = mulmod(p.X, p.X, FIELD_ORDER); 170 | uint256 p_cubed = mulmod(p_squared, p.X, FIELD_ORDER); 171 | return addmod(p_cubed, CURVE_B, FIELD_ORDER) == mulmod(p.Y, p.Y, FIELD_ORDER); 172 | } 173 | 174 | /* 175 | * Multiply the curve generator by a scalar 176 | **/ 177 | function scalarBaseMult(uint256 x) internal view returns (Point r) { 178 | return scalarMult(generator(), x); 179 | } 180 | 181 | /* 182 | * Sum of two points 183 | **/ 184 | function pointAdd(Point p1, Point p2) internal view returns (Point r) { 185 | uint256[4] memory input; 186 | input[0] = p1.X; 187 | input[1] = p1.Y; 188 | input[2] = p2.X; 189 | input[3] = p2.Y; 190 | bool success; 191 | assembly { 192 | success := staticcall(sub(gas, 2000), 6, input, 0x80, r, 0x40) 193 | // Use "invalid" to make gas estimation work 194 | switch success case 0 { invalid } 195 | } 196 | require(success); 197 | } 198 | 199 | /* 200 | * Multiply point by a scalar 201 | **/ 202 | function scalarMult(Point p, uint256 s) internal view returns (Point r) { 203 | uint256[3] memory input; 204 | input[0] = p.X; 205 | input[1] = p.Y; 206 | input[2] = s; 207 | bool success; 208 | assembly { 209 | success := staticcall(sub(gas, 2000), 7, input, 0x60, r, 0x40) 210 | // Use "invalid" to make gas estimation work 211 | switch success case 0 { invalid } 212 | } 213 | require(success); 214 | } 215 | 216 | function expMod(uint256 base, uint256 exponent, uint256 modulus) 217 | internal view returns (uint256 retval) 218 | { 219 | bool success; 220 | uint256[1] memory output; 221 | uint256[6] memory input; 222 | input[0] = 0x20; // baseLen = new(big.Int).SetBytes(getData(input, 0, 32)) 223 | input[1] = 0x20; // expLen = new(big.Int).SetBytes(getData(input, 32, 32)) 224 | input[2] = 0x20; // modLen = new(big.Int).SetBytes(getData(input, 64, 32)) 225 | input[3] = base; 226 | input[4] = exponent; 227 | input[5] = modulus; 228 | assembly { 229 | success := staticcall(sub(gas, 2000), 5, input, 0xc0, output, 0x20) 230 | // Use "invalid" to make gas estimation work 231 | switch success case 0 { invalid } 232 | } 233 | require(success); 234 | return output[0]; 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /contracts/LinkableRing.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | import {bn256g1 as Curve} from './bn256g1.sol'; 8 | 9 | /* 10 | * This contract implements the Franklin Zhang linkable ring signature 11 | * algorithm as used by the Möbius whitepaper (IACR 2017/881): 12 | * 13 | * - https://eprint.iacr.org/2017/881.pdf 14 | * 15 | * Abstract: 16 | * 17 | * "Cryptocurrencies allow users to securely transfer money without 18 | * relying on a trusted intermediary, and the transparency of their 19 | * underlying ledgers also enables public verifiability. This openness, 20 | * however, comes at a cost to privacy, as even though the pseudonyms 21 | * users go by are not linked to their real-world identities, all 22 | * movement of money among these pseudonyms is traceable. In this paper, 23 | * we present Möbius, an Ethereum-based tumbler or mixing service. Möbius 24 | * achieves strong notions of anonymity, as even malicious senders cannot 25 | * identify which pseudonyms belong to the recipients to whom they sent 26 | * money, and is able to resist denial-of-service attacks. It also 27 | * achieves a much lower off-chain communication complexity than all 28 | * existing tumblers, with senders and recipients needing to send only 29 | * two initial messages in order to engage in an arbitrary number of 30 | * transactions." 31 | * 32 | * However, this specific contract introduces the following differences 33 | * in comparison to the white paper: 34 | * 35 | * - P256k1 replaced with ALT_BN128 (as per EIP-213) 36 | * - The Message signed by Participants has changed 37 | * - The Ring contract is now a library 38 | * - The Ring Data stores the Token, Denomination and GUID 39 | * - Ring is a fixed size 40 | * - One SHA256 iteration per public key on verify 41 | * 42 | * 43 | * Initialise Ring (R): 44 | * 45 | * h = H(guid...) 46 | * for y in R 47 | * h = H(h, y) 48 | * m = hashToPoint(h) 49 | * 50 | * 51 | * Verify Signature (σ): 52 | * 53 | * c = 0 54 | * h = H(m, τ) 55 | * for j,c,t in σ 56 | * y = R[j] 57 | * a = g^t + y^c 58 | * b = m^t + τ^c 59 | * h = H(h, a, b) 60 | * csum += c 61 | * h == csum 62 | * 63 | * 64 | * The Verify Signature routine differs from the Mobius whitepaper and 65 | * is slightly less efficient because it performs one H() operation 66 | * per public key, instead of appending all items to be hashed into a 67 | * list then hashing the result. 68 | * 69 | * Potential Performance improvements: 70 | * 71 | * - Switch to SHA3 72 | * - Reduce number of hash operations in verify (requires more memory, but only 1 hash) 73 | * - Reduce number of storage operations 74 | * - Use 'identity' precompiled contract 75 | **/ 76 | 77 | library LinkableRing { 78 | using Curve for Curve.Point; 79 | uint256 public constant RING_SIZE = 4; 80 | 81 | struct Data { 82 | Curve.Point hash; 83 | Curve.Point[] pubkeys; 84 | uint256[] tags; 85 | } 86 | 87 | /* 88 | * The message to be signed to withdraw from the ring once it's full 89 | **/ 90 | function message(Data storage self) internal view returns (bytes32) { 91 | require(isFull(self)); 92 | return bytes32(self.hash.X); 93 | } 94 | 95 | /* 96 | * Have all possible Tags been used, one for each Public Key 97 | * If the ring has not been initialized it is considered Dead. 98 | **/ 99 | function isDead(Data storage self) internal view returns (bool) { 100 | return self.hash.X == 0 || (self.tags.length >= RING_SIZE && self.pubkeys.length >= RING_SIZE); 101 | } 102 | 103 | /* 104 | * Does the X component of a Public Key exist in the Ring? 105 | **/ 106 | function pubExists(Data storage self, uint256 pub_x) internal view returns (bool) { 107 | for(uint i = 0; i < self.pubkeys.length; i++) { 108 | if(self.pubkeys[i].X == pub_x) { 109 | return true; 110 | } 111 | } 112 | return false; 113 | } 114 | 115 | /* 116 | * Does the X component of a Tag exist? 117 | **/ 118 | function tagExists(Data storage self, uint256 pub_x) internal view returns (bool) { 119 | for(uint i = 0; i < self.tags.length; i++) { 120 | if(self.tags[i] == pub_x) { 121 | return true; 122 | } 123 | } 124 | return false; 125 | } 126 | 127 | function isInitialized(Data storage self) internal view returns (bool) { 128 | return self.hash.X != 0; 129 | } 130 | 131 | /* 132 | * Initialise the Ring.Data structure with a token and denomination 133 | **/ 134 | function initialize(Data storage self, bytes32 guid) internal returns (bool) { 135 | require(uint256(guid) != 0); 136 | require(self.hash.X == 0); 137 | 138 | self.hash.X = uint256(guid); 139 | 140 | return true; 141 | } 142 | 143 | /* 144 | * Maximum number of participants reached 145 | **/ 146 | function isFull(Data storage self) internal view returns (bool) { 147 | return self.pubkeys.length == RING_SIZE; 148 | } 149 | 150 | /* 151 | * Add the Public Key to the ring as a ring participant 152 | **/ 153 | function addParticipant(Data storage self, uint256 pub_x, uint256 pub_y) 154 | internal returns (bool) 155 | { 156 | require(!isFull(self)); 157 | 158 | // accepting duplicate public keys would lock money forever 159 | // as each linkable ring signature allows only one withdrawal 160 | require(!pubExists(self, pub_x)); 161 | 162 | Curve.Point memory pub = Curve.Point(pub_x, pub_y); 163 | require(pub.isOnCurve()); 164 | 165 | // Fill Ring with Public Keys 166 | // R = {h ← H(h, y)} 167 | self.hash.X = uint256(sha256(self.hash.X, pub.X, pub.Y)); 168 | self.pubkeys.push(pub); 169 | 170 | if(isFull(self)) { 171 | // h ← H(h, m) 172 | self.hash = Curve.hashToPoint(bytes32(self.hash.X)); 173 | } 174 | 175 | return true; 176 | } 177 | 178 | /* 179 | * Save the tag, which will invalidate any future signatures from the same tag 180 | **/ 181 | function tagAdd(Data storage self, uint256 tag_x) internal { 182 | self.tags.push(tag_x); 183 | } 184 | 185 | /* 186 | * Generates an ordered hash segment for each public key in the ring 187 | * 188 | * a ← g^t + y^c 189 | * b ← h^t + τ^c 190 | * 191 | * Where: 192 | * 193 | * - y is a pubkey in R 194 | * - h is the root hash 195 | * - τ is the public key tag (unique per message) 196 | * - c is a random point 197 | * 198 | * Each segment is used when verifying the ring: 199 | * 200 | * h, sum({c...}) = H(h, {(τ,a,b)...}) 201 | **/ 202 | function ringLink(uint256 previous_hash, uint256 cj, uint256 tj, Curve.Point tau, Curve.Point h, Curve.Point yj) 203 | internal view returns (uint256 ho) 204 | { 205 | Curve.Point memory yc = yj.scalarMult(cj); 206 | 207 | // a ← g^t + y^c 208 | Curve.Point memory a = Curve.scalarBaseMult(tj).pointAdd(yc); 209 | 210 | // b ← h^t + τ^c 211 | Curve.Point memory b = h.scalarMult(tj).pointAdd(tau.scalarMult(cj)); 212 | 213 | return uint256(sha256(previous_hash, a.X, a.Y, b.X, b.Y)); 214 | } 215 | 216 | /** 217 | * Verify whether or not a Ring Signature is valid 218 | * 219 | * Must call tagAdd(tag_x) after a valid signature, if an existing 220 | * tag exists the signature is invalidated to prevent double-spend 221 | */ 222 | function isSignatureValid(Data storage self, uint256 tag_x, uint256 tag_y, uint256[] ctlist) 223 | internal view returns (bool) 224 | { 225 | // Ring must be full before signatures can be accepted 226 | require(isFull(self)); 227 | 228 | // If tag exists, the signature is no longer valid 229 | // Remember, the tag must be saved to the ring afterwards 230 | require(!tagExists(self, tag_x)); 231 | 232 | // h ← H(h, τ) 233 | uint256 hashout = uint256(sha256(self.hash.X, tag_x, tag_y)); 234 | uint256 csum = 0; 235 | 236 | for (uint i = 0; i < self.pubkeys.length; i++) { 237 | // h ← H(h, a, b) 238 | // sum({c...}) 239 | uint256 cj = ctlist[2*i] % Curve.genOrder(); 240 | uint256 tj = ctlist[2*i+1] % Curve.genOrder(); 241 | hashout = ringLink(hashout, cj, tj, Curve.Point(tag_x, tag_y), self.hash, self.pubkeys[i]); 242 | csum = addmod(csum, cj, Curve.genOrder()); 243 | } 244 | 245 | hashout %= Curve.genOrder(); 246 | return hashout == csum; 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /contracts/Mixer.sol: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016-2018 Clearmatics Technologies Ltd 2 | 3 | // SPDX-License-Identifier: LGPL-3.0+ 4 | 5 | pragma solidity ^0.4.19; 6 | 7 | import './LinkableRing.sol'; 8 | import './ERC223ReceivingContract.sol'; 9 | 10 | /* 11 | * Declare the ERC20Compatible interface in order to handle ERC20 tokens transfers 12 | * to and from the Mixer. Note that we only declare the functions we are interested in, 13 | * namely, transferFrom() (used to do a Deposit), and transfer() (used to do a withdrawal) 14 | **/ 15 | contract ERC20Compatible { 16 | function transferFrom(address from, address to, uint256 value) public; 17 | function transfer(address to, uint256 value) public; 18 | } 19 | 20 | /* 21 | * Each ring is given a globally unique ID which consist of: 22 | * 23 | * - contract address 24 | * - incrementing nonce 25 | * - token address 26 | * - denomination 27 | * 28 | * When a Deposit is made for a specific Token and Denomination 29 | * the Mixer will return the Ring GUID. The lifecycle of each Ring 30 | * can then be monitored using the following events which demarcate 31 | * the state transitions: 32 | * 33 | * LogMixerDeposit 34 | * For each Deposit a LogMixerDeposit message is emitted, this includes 35 | * the Ring GUID, the X point of the Stealth Address, and the Token 36 | * address and Denomination. 37 | * 38 | * LogMixerReady 39 | * When a Ring is full and withdrawals can be made a LogMixerReady 40 | * event is emitted, this includes the Ring GUID and the Message 41 | * which must be signed to Withdraw. 42 | * 43 | * LogMixerWithdraw 44 | * For each Withdraw a LogMixerWithdraw message is emitted, this includes 45 | * the Token, Denomination, Ring GUID and Tag of the withdrawer. 46 | * 47 | * LogMixerDead 48 | * When all participants have withdrawn their tokens from a Ring the 49 | * LogMixerDead event is emitted, this specifies the Ring GUID. 50 | **/ 51 | 52 | contract Mixer is ERC223ReceivingContract { 53 | using LinkableRing for LinkableRing.Data; 54 | 55 | struct Data { 56 | bytes32 guid; 57 | uint256 denomination; 58 | address token; 59 | LinkableRing.Data ring; 60 | } 61 | 62 | mapping(bytes32 => Data) internal m_rings; 63 | 64 | // With a public key, lookup which ring it belongs to 65 | mapping(uint256 => bytes32) internal m_pubx_to_ring; 66 | 67 | // Rings which aren't full yet, H(token,denom) -> ring_id 68 | mapping(bytes32 => bytes32) internal m_filling; 69 | 70 | // Nonce used to generate Ring Messages 71 | uint256 internal m_ring_ctr; 72 | 73 | // Token has been deposited into a Mixer Ring 74 | event LogMixerDeposit( 75 | bytes32 indexed ring_id, 76 | uint256 indexed pub_x, 77 | address token, 78 | uint256 value 79 | ); 80 | 81 | // Token has been withdraw from a Mixer Ring 82 | event LogMixerWithdraw( 83 | bytes32 indexed ring_id, 84 | uint256 tag_x, 85 | address token, 86 | uint256 value 87 | ); 88 | 89 | // A Mixer Ring is Full, Tokens can now be withdrawn from it 90 | event LogMixerReady(bytes32 indexed ring_id, bytes32 message); 91 | 92 | // A Mixer Ring has been fully withdrawn, the Ring is dead 93 | event LogMixerDead(bytes32 indexed ring_id); 94 | 95 | function Mixer() public { 96 | // Nothing 97 | } 98 | 99 | function () public { 100 | revert(); 101 | } 102 | 103 | /* 104 | * Given a GUID of a full Ring, return the Message to sign 105 | **/ 106 | function message(bytes32 ring_guid) 107 | public view returns (bytes32) 108 | { 109 | Data storage entry = m_rings[ring_guid]; 110 | LinkableRing.Data storage ring = entry.ring; 111 | 112 | // Entry is empty, non-existant ring 113 | require(0 != entry.denomination); 114 | 115 | return ring.message(); 116 | } 117 | 118 | /* 119 | * Deposit a specific denomination of Ethers which can only be withdrawn 120 | * by providing a ring signature by one of the public keys. 121 | **/ 122 | function depositEther(address token, uint256 denomination, uint256 pub_x, uint256 pub_y) 123 | public payable returns (bytes32) 124 | { 125 | require(token == 0); 126 | require(denomination == msg.value); 127 | 128 | bytes32 ring_guid = depositLogic(token, denomination, pub_x, pub_y); 129 | return ring_guid; 130 | } 131 | 132 | /* 133 | * Deposit a specific denomination of ERC20 compatible tokens which can only be withdrawn 134 | * by providing a ring signature by one of the public keys. 135 | **/ 136 | function depositERC20Compatible(address token, uint256 denomination, uint256 pub_x, uint256 pub_y) 137 | public returns (bytes32) 138 | { 139 | uint256 codeLength; 140 | assembly { 141 | codeLength := extcodesize(token) 142 | } 143 | 144 | require(token != 0 && codeLength > 0); 145 | bytes32 ring_guid = depositLogic(token, denomination, pub_x, pub_y); 146 | 147 | // Call to an untrusted external contract done at the end of the function for security measures 148 | ERC20Compatible untrustedErc20Token = ERC20Compatible(token); 149 | untrustedErc20Token.transferFrom(msg.sender, this, denomination); 150 | 151 | return ring_guid; 152 | } 153 | 154 | /* 155 | * To Withdraw a denomination of Ethers from the Ring, one of the Public Keys 156 | * must provide a Signature which has a unique Tag. Each Tag can only be used 157 | * once. 158 | **/ 159 | function withdrawEther(bytes32 ring_id, uint256 tag_x, uint256 tag_y, uint256[] ctlist) 160 | public returns (bool) 161 | { 162 | Data memory entry = withdrawLogic(ring_id, tag_x, tag_y, ctlist); 163 | msg.sender.transfer(entry.denomination); 164 | 165 | return true; 166 | } 167 | 168 | /* 169 | * To Withdraw a denomination of ERC20 compatible tokens from the Ring, one of the Public Keys 170 | * must provide a Signature which has a unique Tag. Each Tag can only be used 171 | * once. 172 | **/ 173 | function withdrawERC20Compatible(bytes32 ring_id, uint256 tag_x, uint256 tag_y, uint256[] ctlist) 174 | public returns (bool) 175 | { 176 | Data memory entry = withdrawLogic(ring_id, tag_x, tag_y, ctlist); 177 | 178 | // Call to an untrusted external contract done at the end of the function for security measures 179 | ERC20Compatible untrustedErc20Token = ERC20Compatible(entry.token); 180 | untrustedErc20Token.transfer(msg.sender, entry.denomination); 181 | 182 | return true; 183 | } 184 | 185 | /* 186 | * Lookup an unfilled/filling ring for a given token and denomination, 187 | * this will create a new unfilled ring if none exists. When the ring 188 | * is full the 'filling' ring will be deleted. 189 | **/ 190 | function lookupFillingRing(address token, uint256 denomination) 191 | internal returns (bytes32, Data storage) 192 | { 193 | // The filling ID allows quick lookup for the same Token and Denomination 194 | var filling_id = sha256(token, denomination); 195 | var ring_guid = m_filling[filling_id]; 196 | if(ring_guid != 0) { 197 | return (filling_id, m_rings[ring_guid]); 198 | } 199 | 200 | // The GUID is unique per Mixer instance, Nonce, Token and Denomination 201 | ring_guid = sha256(address(this), m_ring_ctr, filling_id); 202 | 203 | Data storage entry = m_rings[ring_guid]; 204 | 205 | // Entry must be initialized only once 206 | require(0 == entry.denomination); 207 | require(entry.ring.initialize(ring_guid)); 208 | 209 | entry.guid = ring_guid; 210 | entry.token = token; 211 | entry.denomination = denomination; 212 | 213 | m_ring_ctr += 1; 214 | m_filling[filling_id] = ring_guid; 215 | 216 | return (filling_id, entry); 217 | } 218 | 219 | function depositLogic(address token, uint256 denomination, uint256 pub_x, uint256 pub_y) 220 | internal returns (bytes32) 221 | { 222 | // Denomination must be positive power of 2, e.g. only 1 bit set 223 | require(denomination != 0 && 0 == (denomination & (denomination - 1))); 224 | 225 | // Public key can only exist in one ring at a time 226 | require(0 == uint256(m_pubx_to_ring[pub_x])); 227 | 228 | bytes32 filling_id; 229 | Data storage entry; 230 | (filling_id, entry) = lookupFillingRing(token, denomination); 231 | 232 | LinkableRing.Data storage ring = entry.ring; 233 | 234 | require(ring.addParticipant(pub_x, pub_y)); 235 | 236 | // Associate Public X point with Ring GUID 237 | // This allows the ring to be recovered with the public key 238 | // Without having to monitor/replay the RingDeposit events 239 | var ring_guid = entry.guid; 240 | m_pubx_to_ring[pub_x] = ring_guid; 241 | LogMixerDeposit(ring_guid, pub_x, token, denomination); 242 | 243 | // When full, emit the GUID as the Ring Message 244 | // Participants need to sign this Message to Withdraw 245 | if(ring.isFull()) { 246 | delete m_filling[filling_id]; 247 | LogMixerReady(ring_guid, ring.message()); 248 | } 249 | 250 | return ring_guid; 251 | } 252 | 253 | function withdrawLogic(bytes32 ring_id, uint256 tag_x, uint256 tag_y, uint256[] ctlist) 254 | internal returns (Data) 255 | { 256 | Data storage entry = m_rings[ring_id]; 257 | LinkableRing.Data storage ring = entry.ring; 258 | 259 | // Entry is empty, non-existant ring 260 | require(0 != entry.denomination); 261 | 262 | require(ring.isFull()); 263 | 264 | require(ring.isSignatureValid(tag_x, tag_y, ctlist)); 265 | 266 | // Tag must be added before withdraw 267 | ring.tagAdd(tag_x); 268 | 269 | LogMixerWithdraw(ring_id, tag_x, entry.token, entry.denomination); 270 | 271 | // We want to return a copy of the entry in order to be able to access 272 | // the token and denomination fields of this object. 273 | // Since the following instructions might delete the entry in the storage 274 | // we save it in a memory variable and return it to the calling function. 275 | Data memory entrySaved = entry; 276 | 277 | // When Tags.length == Pubkeys.length, the ring is dead 278 | // Remove mappings and delete ring 279 | if(ring.isDead()) { 280 | for(uint i = 0; i < ring.pubkeys.length; i++) { 281 | delete m_pubx_to_ring[ring.pubkeys[i].X]; 282 | } 283 | delete m_rings[ring_id]; 284 | LogMixerDead(ring_id); 285 | } 286 | 287 | return entrySaved; 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /mobiusTutorial.md: -------------------------------------------------------------------------------- 1 | # Sending transactions with Mobius 2 | 3 | ## Environment 4 | 5 | - Truffle: 6 | ```bash 7 | $ truffle version 8 | Truffle v4.1.0 (core: 4.1.0) 9 | Solidity v0.4.19 (solc-js) 10 | ``` 11 | 12 | - Geth: 13 | ```bash 14 | $ geth version 15 | Geth 16 | Version: 1.8.1-stable 17 | Git Commit: 1e67410e88d2685bc54611a7c9f75c327b553ccc 18 | ``` 19 | 20 | - Npm: 21 | ```bash 22 | $ npm --version 23 | 5.6.0 24 | ``` 25 | 26 | - Node: 27 | ```bash 28 | $ node --version 29 | v9.5.0 30 | ``` 31 | 32 | ## How to use Mobius ? 33 | 34 | --------------------------------------------------- 35 | 36 | As Möbius supports transfer of ethers and ERC20 compatible tokens, we denote by `Deposit` and `Withdraw` - in this tutorial - the action to do a deposit and a withdrawal to and from the Mixer. The user is free to use the appropriate suffix `Ether` or `ERC20Compatible`. 37 | 38 | :warning: In order for the `DepositERC20Compatible` function to run, the sender has to authorize the `Mixer` to trigger a transfer of tokens on his behalf, **FIRST**. To do this, the sender has to run: `token.approve([mixerAddress], [amountToApprove], {from: [senderAccount]});` (see: ERC20 interface for more details), before calling `DepositERC20Compatible`. 39 | 40 | :warning: The `DepositERC20Compatible` function is not payable, so the `value` field of the transaction object should be omitted. 41 | 42 | --------------------------------------------------- 43 | 44 | ### Assumptions 45 | 46 | 1. The `Mixer` has a `RING_SIZE` equal to 1 (see: https://github.com/clearmatics/mobius/blob/master/contracts/LinkableRing.sol#L80). 47 | If you want to follow the rest of the tutorial, please clone this repository and modify the `LinkableRing` contract accordingly: 48 | ```bash 49 | export $WORKDIR = ~/Path/To/Your/Working/Directory 50 | git clone https://github.com/clearmatics/mobius.git $WORKDIR 51 | cd $WORKDIR/mobius 52 | [YourFavoriteTextEditor] contracts/LinkableRing.sol 53 | [Change line 80: uint256 public constant RING_SIZE = 4; INTO uint256 public constant RING_SIZE = 1;] 54 | [Save and exit your editor] 55 | ``` 56 | 2. We call Alice the sender of the payment and Bob the recipient. 57 | 3. We assume that two accounts with some ethers are available in order to run this tutorial. 58 | 59 | ### Step 1: Generate a master key pair for Bob, using Orbital 60 | 61 | __Orbital:__ https://github.com/clearmatics/orbital 62 | 63 | 1. Run `orbital generate -n 1 > keys.json && cat keys.json`: 64 | ```javascript 65 | { 66 | "pubkeys": [ 67 | { 68 | "x": "0x26569781c3ab69ff42834ea67be539bb231fa48730afc3c89f2bba140b2045b2", 69 | "y": "0xbf75913861d38b5a01b53654daa260856d5dd705af6a24e57622811d485e407" 70 | } 71 | ], 72 | "privkeys": [ 73 | "0x216e142880261d4b743386185c41ae9cf3609f648dbedc15bd0790332b23fb87" 74 | ] 75 | } 76 | ``` 77 | 78 | ### Step 2: Compile and deploy the Mobius Contracts to your network 79 | 80 | :warning: **WARNING**: Mobius is not ready to use in production. It should only be used for a testing/prototyping purpose ! :warning: 81 | 82 | #### Start your ethereum client 83 | 84 | ##### Method 1: Use Ganache-cli (testrpc) 85 | 86 | 1. Make sure you have Ganache-cli installed 87 | ```bash 88 | Ganache CLI v6.0.3 (ganache-core: 2.0.2) 89 | ``` 90 | 2. Start Ganache-cli: 91 | ```bash 92 | yarn testrpc 93 | ``` 94 | 95 | ##### Method 2: Use your own local Geth private environment 96 | 97 | The steps described in this section should only be executed if you decided not to use `Ganache-cli` to run Mobius. 98 | 99 | 1. Create a `genesis.json` file like this one: `touch genesis.json` and copy paste the code below into your `genesis.json` file: 100 | ```javascript 101 | { 102 | "config": { 103 | "chainId": 127, 104 | "homesteadBlock": 0, 105 | "eip155Block": 0, 106 | "eip158Block": 0, 107 | "byzantiumBlock": 0 108 | }, 109 | "alloc" : { 110 | "0x557ef97e60a4aab92c3b3e000a67fb5d26be04b4": { 111 | "balance": "10000000000000000000000000000000000000000000000000000" 112 | }, 113 | "0x8a7cf916f9b6e1bb77ea6282eb5c8b5eb5b779cc": { 114 | "balance": "10000000000000" 115 | }, 116 | }, 117 | "coinbase" : "0x0000000000000000000000000000000000000000", 118 | "difficulty" : "0x20000", 119 | "extraData" : "", 120 | "gasLimit" : "0xFFFFFFF", 121 | "gasPrice" : "0x1", 122 | "nonce" : "0x0000000000000042", 123 | "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 124 | "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", 125 | "timestamp" : "0x00" 126 | } 127 | ``` 128 | *Note:* Make sure to have the line `"byzantiumBlock": 0` in the `config` of your `genesis.json` file in order to make sure that the Mobius contract will be able to execute precompiled contracts. (See: [Byzantium](https://blog.ethereum.org/2017/10/12/byzantium-hf-announcement/)) 129 | 2. Create the data directory for your local configuration of your ethereum network: 130 | ```bash 131 | mkdir ~/ethdev 132 | ``` 133 | 3. Start your node with the genesis configuration: 134 | ```bash 135 | geth --datadir ~/ethdev init genesis.json 136 | ``` 137 | 4. Start your mining node and open the geth console: 138 | ```bash 139 | geth --datadir ~/ethdev --identity=NODE_ONE --networkid=15 --verbosity=1 --mine --minerthreads=1 --rpc --rpcport=8545 --nodiscover --maxpeers=1 console 140 | ``` 141 | 142 | All the steps above are gathered into a script below. Run: `touch startCustomNode.sh && chmod +x startCustomNode.sh` and Copy/Paste the content below into the file, then run: `./startCustomNode.sh` 143 | ```bash 144 | #!/bin/bash 145 | 146 | if [ ! -f "./geth" ]; then 147 | echo "==> Fetching GETH 1.8.1 <==\n" 148 | wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.8.1-1e67410e.tar.gz 149 | echo "Unpacking GETH 1.8.1" 150 | tar -xvf geth-linux-amd64-1.8.1-1e67410e.tar.gz 151 | fi 152 | 153 | echo "==> Creating ~/ethdev folder <== \n" 154 | mkdir ~/ethdev 155 | 156 | echo "==> Initializing the private blockchain with custom genesis file <==\n" 157 | ./geth --datadir ~/ethdev init genesis.json 158 | 159 | echo "==> Starting miner node: Listening rpc on 8545 <==\n" 160 | ./geth --datadir ~/ethdev --identity=NODE_ONE --networkid=15 --verbosity=1 --mine --minerthreads=1 --rpc --rpcport=8545 --nodiscover --maxpeers=1 console 161 | ``` 162 | 163 | #### Deploy the Mobius contracts: 164 | 165 | ##### Method 1 (Easy way): Using truffle 166 | 167 | 1. Compile the contracts: 168 | ```bash 169 | truffle compile 170 | ``` 171 | 2. Deploy the contracts to the `development` network 172 | ```bash 173 | truffle deploy --network development 174 | ``` 175 | The logs of truffle deploy should output the address to which the Mixer has been deployed `Mixer: [Address]`. If you can't see this log, run `Mixer.deployed()` in the `truffle console` and save the address somewhere (we'll need it in a few steps). 176 | 3. Get the Mixer Abi: 177 | ```bash 178 | echo "var MixerAbi=`solc --optimize --combined-json abi contracts/Mixer.sol`" > mixerAbi.js 179 | ``` 180 | 181 | *In the Geth console, run the following commands* 182 | 183 | 1. Load the file containing the ABI of the Mixer contract: 184 | ```bash 185 | loadScript('mixerAbi.js') 186 | ``` 187 | 2. Store the ABI of the Mixer into a variable: 188 | ```bash 189 | var mixerContractAbi = MixerAbi.contracts['contracts/Mixer.sol:Mixer'].abi; 190 | ``` 191 | 3. Run: 192 | ```bash 193 | var mixerContract = eth.contract(JSON.parse(mixerContractAbi)); 194 | var mixerContractAddress = [Paste here the Mixe Address saved at step 2]; 195 | var mixer = mixerContract.at(mixerContractAddress); 196 | ``` 197 | After this step, we can use the `mixerInstance` variable in order to interact with the contract from the geth console. 198 | 199 | ##### Method 2 ("Hard way"): Manual deployment in Geth 200 | 201 | 1. Compile the Mixer contract: 202 | ```bash 203 | echo "var mixerOutput=`solc --optimize --combined-json abi,bin,interface contracts/Mixer.sol`" > mixer.js 204 | ``` 205 | 206 | *In the Geth console, run the following commands* 207 | 208 | 1. Load the `mixer.js` file: 209 | ```bash 210 | loadScript('mixer.js') 211 | ``` 212 | 2. Store the ABI of the Mixer into a variable: 213 | ```bash 214 | var mixerContractAbi = mixerOutput.contracts['contracts/Mixer.sol:Mixer'].abi 215 | ``` 216 | 3. Run: 217 | ```bash 218 | var mixerContract = eth.contract(JSON.parse(mixerContractAbi)) 219 | var mixerBinCode = "0x" + mixerOutput.contracts['contracts/Mixer.sol:Mixer'].bin 220 | personal.unlockAccount([AccountYouWantToUseToDeploy], [PasswordOfTheAccount], 0) 221 | var deployTransationObject = { from: eth.accounts[0], data: mixerBinCode, gas: 1000000 }; 222 | var mixerInstance = mixerContract.new(deployTransationObject) 223 | var mixerContractAdress = eth.getTransactionReceipt(mixerInstance.transactionHash).contractAddress 224 | var mixer = mixerContract.at(mixerContractAddress); 225 | ``` 226 | 227 | ### Step 3: Interact with Mobius and proceed to payments 228 | 229 | 1. Define listeners to listen to the Mixer events: 230 | ```javascript 231 | var mixerDepositEvent = mixer.LogMixerDeposit(); 232 | mixerDepositEvent.watch(function(error, result){ 233 | if (error) { console.log(error); return; } 234 | console.log("MixerDeposit event"); 235 | }); 236 | 237 | var mixerReadyEvent = mixer.LogMixerReady(); 238 | mixerReadyEvent.watch(function(error, result){ 239 | if (error) { console.log(error); return; } 240 | console.log("MixerReady event"); 241 | console.log("Ring message: " + result.args.message); 242 | console.log("Ring GUID: " + result.args.ring_id); 243 | }); 244 | 245 | var mixerWithdrawEvent = mixer.LogMixerWithdraw(); 246 | mixerWithdrawEvent.watch(function(error, result){ 247 | if (error) { console.log(error); return; } 248 | console.log("MixerWithdraw event"); 249 | }); 250 | 251 | var mixerDeadEvent = mixer.LogMixerDead(); 252 | mixerDeadEvent.watch(function(error, result){ 253 | if (error) { console.log(error); return; } 254 | console.log("MixerDead event"); 255 | }); 256 | ``` 257 | 2. Get the balance of the Mixer (should be equal to zero): 258 | ```bash 259 | eth.getBalance("[mixerAddress]") 260 | ``` 261 | 3. Deposit funds to the Mixer (after generating the keys with `orbital generate -n 1 > keys.json`): 262 | ```bash 263 | var pubX = [X component of pubKey in keys.json] 264 | var pubY = [Y component of pubKey in keys.json] 265 | 266 | var AliceAccount = eth.accounts[0]; 267 | var gasValue: [AmountOfGasAliceIsReadyToPay] 268 | var yourDenomination = [AmountOfMoneyYouWantToTransfer] 269 | 270 | // We trigger a deposit from Alice's account 271 | mixer.depositEther(0, yourDenomination, pubX, pubY, {from: AliceAccount, value: yourDenomination, gas: gasValue}) 272 | ``` 273 | 4. Verify that the deposit has successfully been done on the contract (the balance of the contract should be equal to the denomination)specified by the sender in the `Deposit` function 274 | ```bash 275 | eth.getBalance("[mixerAddress]") 276 | ``` 277 | 5. Generate the ring signature using orbital: 278 | ```bash 279 | orbital inputs -n 1 -f keys.json -m [RingMessage] > signature.json 280 | ``` 281 | 6. Withdraw funds from Bob's account: 282 | ```bash 283 | var bobAccount = eth.accounts[1]; 284 | personal.unlockAccount(bobAccount); // Unlock Bob's account 285 | 286 | var tauX = [tauX in signature.json]; 287 | var tauY = [tauY in signature.json]; 288 | var ctlist = [ctlistArray] 289 | 290 | var ringGuid = [ring GUID returned by the mixerReadyEvent]; 291 | 292 | var gasValue: [AmountOfGasBobIsReadyToPay] 293 | 294 | mixer.withdrawEther(ringGuid, tauX, tauY, ctlist, {from: bobAccount, gas: gasValue}); 295 | ``` 296 | 297 | ### Step 4: Verify that the payment worked 298 | 299 | 1. At this stage of the process, the balance of the Mixer should be equal to 0 again. Verify it: 300 | ``` 301 | eth.getBalance("[mixerAddress]") 302 | ``` 303 | 2. Bob's account should have been credited. In order to make sure that everything worked well, Bob's balance after the withdrawal should respect the equality: 304 | ``` 305 | BalanceAfterWithdrawal = (BalanceBeforeWithdrawal - (gasUsed * gasPrice)) + denomination 306 | ``` 307 | _Note:_ The `gasUsed` and `gasPrice` values can be accessed directly by running `eth.getTransactionReceipt("[HashOfTheWithdrawalTX]")`. 308 | ## Observed Caveat 309 | - Bob has to have funds on his account in order to be able to pay for the Withdraw function to be executed. Thus, Mobius cannot be used to send funds to an address that doesn't have a minimum amount of funds. 310 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | abbrev@1: 6 | version "1.1.1" 7 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 8 | 9 | abbrev@1.0.x: 10 | version "1.0.9" 11 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" 12 | 13 | align-text@^0.1.1, align-text@^0.1.3: 14 | version "0.1.4" 15 | resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" 16 | dependencies: 17 | kind-of "^3.0.2" 18 | longest "^1.0.1" 19 | repeat-string "^1.5.2" 20 | 21 | amdefine@>=0.0.4: 22 | version "1.0.1" 23 | resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" 24 | 25 | ansi-regex@^2.0.0: 26 | version "2.1.1" 27 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 28 | 29 | ansi-regex@^4.1.0: 30 | version "4.1.0" 31 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 32 | integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== 33 | 34 | ansi-styles@^3.2.0: 35 | version "3.2.1" 36 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 37 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 38 | dependencies: 39 | color-convert "^1.9.0" 40 | 41 | argparse@^1.0.7: 42 | version "1.0.10" 43 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 44 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 45 | dependencies: 46 | sprintf-js "~1.0.2" 47 | 48 | async@1.x, async@^1.4.0: 49 | version "1.5.2" 50 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 51 | 52 | balanced-match@^1.0.0: 53 | version "1.0.0" 54 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 55 | 56 | big-integer@1.6.48: 57 | version "1.6.48" 58 | resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" 59 | integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== 60 | 61 | "bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": 62 | version "2.0.7" 63 | resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" 64 | 65 | bindings@^1.2.1, bindings@^1.5.0: 66 | version "1.5.0" 67 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" 68 | integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== 69 | dependencies: 70 | file-uri-to-path "1.0.0" 71 | 72 | bip66@^1.1.5: 73 | version "1.1.5" 74 | resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" 75 | integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= 76 | dependencies: 77 | safe-buffer "^5.0.1" 78 | 79 | bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.8, bn.js@^4.4.0: 80 | version "4.11.8" 81 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" 82 | integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== 83 | 84 | brace-expansion@^1.1.7: 85 | version "1.1.11" 86 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 87 | dependencies: 88 | balanced-match "^1.0.0" 89 | concat-map "0.0.1" 90 | 91 | brorand@^1.0.1: 92 | version "1.1.0" 93 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 94 | 95 | browser-stdout@1.3.0: 96 | version "1.3.0" 97 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 98 | integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= 99 | 100 | browserify-aes@^1.0.6: 101 | version "1.2.0" 102 | resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" 103 | integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== 104 | dependencies: 105 | buffer-xor "^1.0.3" 106 | cipher-base "^1.0.0" 107 | create-hash "^1.1.0" 108 | evp_bytestokey "^1.0.3" 109 | inherits "^2.0.1" 110 | safe-buffer "^5.0.1" 111 | 112 | browserify-sha3@^0.0.1: 113 | version "0.0.1" 114 | resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" 115 | dependencies: 116 | js-sha3 "^0.3.1" 117 | 118 | buffer-from@^1.0.0: 119 | version "1.1.1" 120 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 121 | integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== 122 | 123 | buffer-xor@^1.0.3: 124 | version "1.0.3" 125 | resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" 126 | 127 | camelcase@^1.0.2: 128 | version "1.2.1" 129 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" 130 | 131 | camelcase@^3.0.0: 132 | version "3.0.0" 133 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" 134 | integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= 135 | 136 | camelcase@^5.0.0: 137 | version "5.3.1" 138 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 139 | integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== 140 | 141 | center-align@^0.1.1: 142 | version "0.1.3" 143 | resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" 144 | dependencies: 145 | align-text "^0.1.3" 146 | lazy-cache "^1.0.3" 147 | 148 | cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: 149 | version "1.0.4" 150 | resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" 151 | dependencies: 152 | inherits "^2.0.1" 153 | safe-buffer "^5.0.1" 154 | 155 | cliui@^2.1.0: 156 | version "2.1.0" 157 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" 158 | dependencies: 159 | center-align "^0.1.1" 160 | right-align "^0.1.1" 161 | wordwrap "0.0.2" 162 | 163 | cliui@^3.2.0: 164 | version "3.2.0" 165 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" 166 | integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= 167 | dependencies: 168 | string-width "^1.0.1" 169 | strip-ansi "^3.0.1" 170 | wrap-ansi "^2.0.0" 171 | 172 | cliui@^5.0.0: 173 | version "5.0.0" 174 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" 175 | integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== 176 | dependencies: 177 | string-width "^3.1.0" 178 | strip-ansi "^5.2.0" 179 | wrap-ansi "^5.1.0" 180 | 181 | code-point-at@^1.0.0: 182 | version "1.1.0" 183 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 184 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 185 | 186 | color-convert@^1.9.0: 187 | version "1.9.1" 188 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" 189 | dependencies: 190 | color-name "^1.1.1" 191 | 192 | color-name@^1.1.1: 193 | version "1.1.3" 194 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 195 | 196 | commander@2.11.0: 197 | version "2.11.0" 198 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 199 | integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== 200 | 201 | concat-map@0.0.1: 202 | version "0.0.1" 203 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 204 | 205 | create-hash@^1.1.0, create-hash@^1.1.2: 206 | version "1.1.3" 207 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd" 208 | dependencies: 209 | cipher-base "^1.0.1" 210 | inherits "^2.0.1" 211 | ripemd160 "^2.0.0" 212 | sha.js "^2.4.0" 213 | 214 | create-hash@^1.2.0: 215 | version "1.2.0" 216 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" 217 | integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== 218 | dependencies: 219 | cipher-base "^1.0.1" 220 | inherits "^2.0.1" 221 | md5.js "^1.3.4" 222 | ripemd160 "^2.0.1" 223 | sha.js "^2.4.0" 224 | 225 | create-hmac@^1.1.4: 226 | version "1.1.6" 227 | resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" 228 | dependencies: 229 | cipher-base "^1.0.3" 230 | create-hash "^1.1.0" 231 | inherits "^2.0.1" 232 | ripemd160 "^2.0.0" 233 | safe-buffer "^5.0.1" 234 | sha.js "^2.4.8" 235 | 236 | cross-spawn@^6.0.0: 237 | version "6.0.5" 238 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 239 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 240 | dependencies: 241 | nice-try "^1.0.4" 242 | path-key "^2.0.1" 243 | semver "^5.5.0" 244 | shebang-command "^1.2.0" 245 | which "^1.2.9" 246 | 247 | crypto-js@^3.1.4: 248 | version "3.1.8" 249 | resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" 250 | integrity sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU= 251 | 252 | death@^1.1.0: 253 | version "1.1.0" 254 | resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318" 255 | 256 | debug@3.1.0: 257 | version "3.1.0" 258 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 259 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== 260 | dependencies: 261 | ms "2.0.0" 262 | 263 | decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.2.0: 264 | version "1.2.0" 265 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 266 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 267 | 268 | deep-is@~0.1.3: 269 | version "0.1.3" 270 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" 271 | 272 | diff@3.3.1: 273 | version "3.3.1" 274 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" 275 | integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== 276 | 277 | drbg.js@^1.0.1: 278 | version "1.0.1" 279 | resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" 280 | integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= 281 | dependencies: 282 | browserify-aes "^1.0.6" 283 | create-hash "^1.1.2" 284 | create-hmac "^1.1.4" 285 | 286 | elliptic@^6.4.1: 287 | version "6.5.1" 288 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.1.tgz#c380f5f909bf1b9b4428d028cd18d3b0efd6b52b" 289 | integrity sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg== 290 | dependencies: 291 | bn.js "^4.4.0" 292 | brorand "^1.0.1" 293 | hash.js "^1.0.0" 294 | hmac-drbg "^1.0.0" 295 | inherits "^2.0.1" 296 | minimalistic-assert "^1.0.0" 297 | minimalistic-crypto-utils "^1.0.0" 298 | 299 | emoji-regex@^7.0.1: 300 | version "7.0.3" 301 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 302 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 303 | 304 | end-of-stream@^1.1.0: 305 | version "1.4.4" 306 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 307 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 308 | dependencies: 309 | once "^1.4.0" 310 | 311 | error-ex@^1.2.0: 312 | version "1.3.2" 313 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 314 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 315 | dependencies: 316 | is-arrayish "^0.2.1" 317 | 318 | escape-string-regexp@1.0.5: 319 | version "1.0.5" 320 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 321 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 322 | 323 | escodegen@1.8.x: 324 | version "1.8.1" 325 | resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" 326 | dependencies: 327 | esprima "^2.7.1" 328 | estraverse "^1.9.1" 329 | esutils "^2.0.2" 330 | optionator "^0.8.1" 331 | optionalDependencies: 332 | source-map "~0.2.0" 333 | 334 | esprima@2.7.x, esprima@^2.7.1: 335 | version "2.7.3" 336 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" 337 | 338 | esprima@^4.0.0: 339 | version "4.0.1" 340 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 341 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 342 | 343 | estraverse@^1.9.1: 344 | version "1.9.3" 345 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" 346 | 347 | esutils@^2.0.2: 348 | version "2.0.2" 349 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 350 | 351 | ethereumjs-testrpc-sc@6.1.6: 352 | version "6.1.6" 353 | resolved "https://registry.yarnpkg.com/ethereumjs-testrpc-sc/-/ethereumjs-testrpc-sc-6.1.6.tgz#290595380b5182814564d4aa38f35b7788aab070" 354 | integrity sha512-iv2qiGBFgk9mn5Nq2enX8dG5WQ7Lk+FCqpnxfPfH4Ns8KLPwttmNOy264nh3SXDJJvcQwz/XnlLteDQVILotbg== 355 | dependencies: 356 | source-map-support "^0.5.3" 357 | 358 | ethereumjs-util@6.1.0: 359 | version "6.1.0" 360 | resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" 361 | integrity sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q== 362 | dependencies: 363 | bn.js "^4.11.0" 364 | create-hash "^1.1.2" 365 | ethjs-util "0.1.6" 366 | keccak "^1.0.2" 367 | rlp "^2.0.0" 368 | safe-buffer "^5.1.1" 369 | secp256k1 "^3.0.1" 370 | 371 | ethjs-util@0.1.6: 372 | version "0.1.6" 373 | resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" 374 | integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== 375 | dependencies: 376 | is-hex-prefixed "1.0.0" 377 | strip-hex-prefix "1.0.0" 378 | 379 | evp_bytestokey@^1.0.3: 380 | version "1.0.3" 381 | resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" 382 | dependencies: 383 | md5.js "^1.3.4" 384 | safe-buffer "^5.1.1" 385 | 386 | execa@^1.0.0: 387 | version "1.0.0" 388 | resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" 389 | integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== 390 | dependencies: 391 | cross-spawn "^6.0.0" 392 | get-stream "^4.0.0" 393 | is-stream "^1.1.0" 394 | npm-run-path "^2.0.0" 395 | p-finally "^1.0.0" 396 | signal-exit "^3.0.0" 397 | strip-eof "^1.0.0" 398 | 399 | fast-levenshtein@~2.0.4: 400 | version "2.0.6" 401 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 402 | 403 | file-uri-to-path@1.0.0: 404 | version "1.0.0" 405 | resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" 406 | integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== 407 | 408 | find-up@^1.0.0: 409 | version "1.1.2" 410 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 411 | integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= 412 | dependencies: 413 | path-exists "^2.0.0" 414 | pinkie-promise "^2.0.0" 415 | 416 | find-up@^3.0.0: 417 | version "3.0.0" 418 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 419 | integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== 420 | dependencies: 421 | locate-path "^3.0.0" 422 | 423 | fs-extra@^0.30.0: 424 | version "0.30.0" 425 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" 426 | integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= 427 | dependencies: 428 | graceful-fs "^4.1.2" 429 | jsonfile "^2.1.0" 430 | klaw "^1.0.0" 431 | path-is-absolute "^1.0.0" 432 | rimraf "^2.2.8" 433 | 434 | fs.realpath@^1.0.0: 435 | version "1.0.0" 436 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 437 | 438 | ganache-cli@6.7.0: 439 | version "6.7.0" 440 | resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.7.0.tgz#b59845578221bdf686cf124d007c5ee62e85a62f" 441 | integrity sha512-9CZsClo9hl5MxGL7hkk14mie89Q94P0idh92jcV7LmppTYTCG7SHatuwcfqN7emFHArMt3fneN4QbH2do2N6Ow== 442 | dependencies: 443 | ethereumjs-util "6.1.0" 444 | source-map-support "0.5.12" 445 | yargs "13.2.4" 446 | 447 | get-caller-file@^1.0.1: 448 | version "1.0.3" 449 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" 450 | integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== 451 | 452 | get-caller-file@^2.0.1: 453 | version "2.0.5" 454 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 455 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== 456 | 457 | get-stream@^4.0.0: 458 | version "4.1.0" 459 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" 460 | integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== 461 | dependencies: 462 | pump "^3.0.0" 463 | 464 | glob@7.1.2, glob@^7.0.0: 465 | version "7.1.2" 466 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 467 | dependencies: 468 | fs.realpath "^1.0.0" 469 | inflight "^1.0.4" 470 | inherits "2" 471 | minimatch "^3.0.4" 472 | once "^1.3.0" 473 | path-is-absolute "^1.0.0" 474 | 475 | glob@^5.0.15: 476 | version "5.0.15" 477 | resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 478 | dependencies: 479 | inflight "^1.0.4" 480 | inherits "2" 481 | minimatch "2 || 3" 482 | once "^1.3.0" 483 | path-is-absolute "^1.0.0" 484 | 485 | glob@^7.1.3: 486 | version "7.1.6" 487 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 488 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 489 | dependencies: 490 | fs.realpath "^1.0.0" 491 | inflight "^1.0.4" 492 | inherits "2" 493 | minimatch "^3.0.4" 494 | once "^1.3.0" 495 | path-is-absolute "^1.0.0" 496 | 497 | graceful-fs@^4.1.2, graceful-fs@^4.1.6: 498 | version "4.1.11" 499 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 500 | 501 | graceful-fs@^4.1.9: 502 | version "4.2.3" 503 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" 504 | integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== 505 | 506 | growl@1.10.3: 507 | version "1.10.3" 508 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" 509 | integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== 510 | 511 | handlebars@^4.0.1: 512 | version "4.0.11" 513 | resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" 514 | dependencies: 515 | async "^1.4.0" 516 | optimist "^0.6.1" 517 | source-map "^0.4.4" 518 | optionalDependencies: 519 | uglify-js "^2.6" 520 | 521 | has-flag@^1.0.0: 522 | version "1.0.0" 523 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 524 | 525 | has-flag@^2.0.0: 526 | version "2.0.0" 527 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" 528 | integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= 529 | 530 | hash-base@^2.0.0: 531 | version "2.0.2" 532 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" 533 | dependencies: 534 | inherits "^2.0.1" 535 | 536 | hash-base@^3.0.0: 537 | version "3.0.4" 538 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" 539 | dependencies: 540 | inherits "^2.0.1" 541 | safe-buffer "^5.0.1" 542 | 543 | hash.js@^1.0.0, hash.js@^1.0.3: 544 | version "1.1.3" 545 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" 546 | dependencies: 547 | inherits "^2.0.3" 548 | minimalistic-assert "^1.0.0" 549 | 550 | he@1.1.1: 551 | version "1.1.1" 552 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 553 | 554 | hmac-drbg@^1.0.0: 555 | version "1.0.1" 556 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 557 | dependencies: 558 | hash.js "^1.0.3" 559 | minimalistic-assert "^1.0.0" 560 | minimalistic-crypto-utils "^1.0.1" 561 | 562 | hosted-git-info@^2.1.4: 563 | version "2.6.0" 564 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.6.0.tgz#23235b29ab230c576aab0d4f13fc046b0b038222" 565 | 566 | inflight@^1.0.4: 567 | version "1.0.6" 568 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 569 | dependencies: 570 | once "^1.3.0" 571 | wrappy "1" 572 | 573 | inherits@2, inherits@^2.0.1, inherits@^2.0.3: 574 | version "2.0.3" 575 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 576 | 577 | interpret@^1.0.0: 578 | version "1.1.0" 579 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" 580 | 581 | invert-kv@^1.0.0: 582 | version "1.0.0" 583 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" 584 | integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= 585 | 586 | invert-kv@^2.0.0: 587 | version "2.0.0" 588 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" 589 | integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== 590 | 591 | is-arrayish@^0.2.1: 592 | version "0.2.1" 593 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 594 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 595 | 596 | is-buffer@^1.1.5: 597 | version "1.1.6" 598 | resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 599 | 600 | is-fullwidth-code-point@^1.0.0: 601 | version "1.0.0" 602 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 603 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 604 | dependencies: 605 | number-is-nan "^1.0.0" 606 | 607 | is-fullwidth-code-point@^2.0.0: 608 | version "2.0.0" 609 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 610 | 611 | is-hex-prefixed@1.0.0: 612 | version "1.0.0" 613 | resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" 614 | integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= 615 | 616 | is-stream@^1.1.0: 617 | version "1.1.0" 618 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 619 | 620 | is-utf8@^0.2.0: 621 | version "0.2.1" 622 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 623 | integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= 624 | 625 | isexe@^2.0.0: 626 | version "2.0.0" 627 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 628 | 629 | istanbul@^0.4.5: 630 | version "0.4.5" 631 | resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" 632 | dependencies: 633 | abbrev "1.0.x" 634 | async "1.x" 635 | escodegen "1.8.x" 636 | esprima "2.7.x" 637 | glob "^5.0.15" 638 | handlebars "^4.0.1" 639 | js-yaml "3.x" 640 | mkdirp "0.5.x" 641 | nopt "3.x" 642 | once "1.x" 643 | resolve "1.1.x" 644 | supports-color "^3.1.0" 645 | which "^1.1.1" 646 | wordwrap "^1.0.0" 647 | 648 | js-sha3@^0.3.1: 649 | version "0.3.1" 650 | resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" 651 | 652 | js-yaml@3.x: 653 | version "3.13.1" 654 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 655 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 656 | dependencies: 657 | argparse "^1.0.7" 658 | esprima "^4.0.0" 659 | 660 | json-bigint-string@^1.0.0: 661 | version "1.0.0" 662 | resolved "https://registry.yarnpkg.com/json-bigint-string/-/json-bigint-string-1.0.0.tgz#3399784d778bb78440bd72c7094af0e075bbe683" 663 | 664 | jsonfile@^2.1.0: 665 | version "2.4.0" 666 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" 667 | integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= 668 | optionalDependencies: 669 | graceful-fs "^4.1.6" 670 | 671 | keccak@^1.0.2: 672 | version "1.4.0" 673 | resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" 674 | integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== 675 | dependencies: 676 | bindings "^1.2.1" 677 | inherits "^2.0.3" 678 | nan "^2.2.1" 679 | safe-buffer "^5.1.0" 680 | 681 | keccakjs@^0.2.1: 682 | version "0.2.1" 683 | resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" 684 | dependencies: 685 | browserify-sha3 "^0.0.1" 686 | sha3 "^1.1.0" 687 | 688 | kind-of@^3.0.2: 689 | version "3.2.2" 690 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 691 | dependencies: 692 | is-buffer "^1.1.5" 693 | 694 | klaw@^1.0.0: 695 | version "1.3.1" 696 | resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" 697 | integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= 698 | optionalDependencies: 699 | graceful-fs "^4.1.9" 700 | 701 | lazy-cache@^1.0.3: 702 | version "1.0.4" 703 | resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" 704 | 705 | lcid@^1.0.0: 706 | version "1.0.0" 707 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" 708 | integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= 709 | dependencies: 710 | invert-kv "^1.0.0" 711 | 712 | lcid@^2.0.0: 713 | version "2.0.0" 714 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" 715 | integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== 716 | dependencies: 717 | invert-kv "^2.0.0" 718 | 719 | levn@~0.3.0: 720 | version "0.3.0" 721 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 722 | dependencies: 723 | prelude-ls "~1.1.2" 724 | type-check "~0.3.2" 725 | 726 | load-json-file@^1.0.0: 727 | version "1.1.0" 728 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 729 | integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= 730 | dependencies: 731 | graceful-fs "^4.1.2" 732 | parse-json "^2.2.0" 733 | pify "^2.0.0" 734 | pinkie-promise "^2.0.0" 735 | strip-bom "^2.0.0" 736 | 737 | locate-path@^3.0.0: 738 | version "3.0.0" 739 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 740 | integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== 741 | dependencies: 742 | p-locate "^3.0.0" 743 | path-exists "^3.0.0" 744 | 745 | lodash.assign@^4.0.3, lodash.assign@^4.0.6: 746 | version "4.2.0" 747 | resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" 748 | integrity sha1-DZnzzNem0mHRm9rrkkUAXShYCOc= 749 | 750 | longest@^1.0.1: 751 | version "1.0.1" 752 | resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" 753 | 754 | map-age-cleaner@^0.1.1: 755 | version "0.1.3" 756 | resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" 757 | integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== 758 | dependencies: 759 | p-defer "^1.0.0" 760 | 761 | md5.js@^1.3.4: 762 | version "1.3.4" 763 | resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" 764 | dependencies: 765 | hash-base "^3.0.0" 766 | inherits "^2.0.1" 767 | 768 | mem@^4.0.0: 769 | version "4.3.0" 770 | resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" 771 | integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== 772 | dependencies: 773 | map-age-cleaner "^0.1.1" 774 | mimic-fn "^2.0.0" 775 | p-is-promise "^2.0.0" 776 | 777 | memorystream@^0.3.1: 778 | version "0.3.1" 779 | resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" 780 | integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= 781 | 782 | mimic-fn@^2.0.0: 783 | version "2.1.0" 784 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" 785 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== 786 | 787 | minimalistic-assert@^1.0.0: 788 | version "1.0.0" 789 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3" 790 | 791 | minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: 792 | version "1.0.1" 793 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 794 | 795 | "minimatch@2 || 3", minimatch@^3.0.4: 796 | version "3.0.4" 797 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 798 | dependencies: 799 | brace-expansion "^1.1.7" 800 | 801 | minimist@0.0.8: 802 | version "0.0.8" 803 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 804 | 805 | minimist@~0.0.1: 806 | version "0.0.10" 807 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" 808 | 809 | mkdirp@0.5.1, mkdirp@0.5.x: 810 | version "0.5.1" 811 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 812 | dependencies: 813 | minimist "0.0.8" 814 | 815 | mocha@^4.1.0: 816 | version "4.1.0" 817 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" 818 | integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== 819 | dependencies: 820 | browser-stdout "1.3.0" 821 | commander "2.11.0" 822 | debug "3.1.0" 823 | diff "3.3.1" 824 | escape-string-regexp "1.0.5" 825 | glob "7.1.2" 826 | growl "1.10.3" 827 | he "1.1.1" 828 | mkdirp "0.5.1" 829 | supports-color "4.4.0" 830 | 831 | ms@2.0.0: 832 | version "2.0.0" 833 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 834 | 835 | nan@^2.0.5: 836 | version "2.9.2" 837 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.9.2.tgz#f564d75f5f8f36a6d9456cca7a6c4fe488ab7866" 838 | 839 | nan@^2.14.0, nan@^2.2.1: 840 | version "2.14.0" 841 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" 842 | integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== 843 | 844 | nice-try@^1.0.4: 845 | version "1.0.4" 846 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" 847 | 848 | nopt@3.x: 849 | version "3.0.6" 850 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" 851 | dependencies: 852 | abbrev "1" 853 | 854 | normalize-package-data@^2.3.2: 855 | version "2.5.0" 856 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 857 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 858 | dependencies: 859 | hosted-git-info "^2.1.4" 860 | resolve "^1.10.0" 861 | semver "2 || 3 || 4 || 5" 862 | validate-npm-package-license "^3.0.1" 863 | 864 | npm-run-path@^2.0.0: 865 | version "2.0.2" 866 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 867 | dependencies: 868 | path-key "^2.0.0" 869 | 870 | number-is-nan@^1.0.0: 871 | version "1.0.1" 872 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 873 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 874 | 875 | once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: 876 | version "1.4.0" 877 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 878 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 879 | dependencies: 880 | wrappy "1" 881 | 882 | optimist@^0.6.1: 883 | version "0.6.1" 884 | resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" 885 | dependencies: 886 | minimist "~0.0.1" 887 | wordwrap "~0.0.2" 888 | 889 | optionator@^0.8.1: 890 | version "0.8.2" 891 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" 892 | dependencies: 893 | deep-is "~0.1.3" 894 | fast-levenshtein "~2.0.4" 895 | levn "~0.3.0" 896 | prelude-ls "~1.1.2" 897 | type-check "~0.3.2" 898 | wordwrap "~1.0.0" 899 | 900 | original-require@1.0.1: 901 | version "1.0.1" 902 | resolved "https://registry.yarnpkg.com/original-require/-/original-require-1.0.1.tgz#0f130471584cd33511c5ec38c8d59213f9ac5e20" 903 | integrity sha1-DxMEcVhM0zURxew4yNWSE/msXiA= 904 | 905 | os-locale@^1.4.0: 906 | version "1.4.0" 907 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" 908 | integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= 909 | dependencies: 910 | lcid "^1.0.0" 911 | 912 | os-locale@^3.1.0: 913 | version "3.1.0" 914 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" 915 | integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== 916 | dependencies: 917 | execa "^1.0.0" 918 | lcid "^2.0.0" 919 | mem "^4.0.0" 920 | 921 | p-defer@^1.0.0: 922 | version "1.0.0" 923 | resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" 924 | integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= 925 | 926 | p-finally@^1.0.0: 927 | version "1.0.0" 928 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 929 | 930 | p-is-promise@^2.0.0: 931 | version "2.1.0" 932 | resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" 933 | integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== 934 | 935 | p-limit@^2.0.0: 936 | version "2.2.1" 937 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" 938 | integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== 939 | dependencies: 940 | p-try "^2.0.0" 941 | 942 | p-locate@^3.0.0: 943 | version "3.0.0" 944 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 945 | integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== 946 | dependencies: 947 | p-limit "^2.0.0" 948 | 949 | p-try@^2.0.0: 950 | version "2.2.0" 951 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 952 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 953 | 954 | parse-json@^2.2.0: 955 | version "2.2.0" 956 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 957 | integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= 958 | dependencies: 959 | error-ex "^1.2.0" 960 | 961 | path-exists@^2.0.0: 962 | version "2.1.0" 963 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 964 | integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= 965 | dependencies: 966 | pinkie-promise "^2.0.0" 967 | 968 | path-exists@^3.0.0: 969 | version "3.0.0" 970 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 971 | 972 | path-is-absolute@^1.0.0: 973 | version "1.0.1" 974 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 975 | 976 | path-key@^2.0.0, path-key@^2.0.1: 977 | version "2.0.1" 978 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 979 | 980 | path-parse@^1.0.5: 981 | version "1.0.5" 982 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" 983 | 984 | path-parse@^1.0.6: 985 | version "1.0.6" 986 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 987 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 988 | 989 | path-type@^1.0.0: 990 | version "1.1.0" 991 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 992 | integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= 993 | dependencies: 994 | graceful-fs "^4.1.2" 995 | pify "^2.0.0" 996 | pinkie-promise "^2.0.0" 997 | 998 | pegjs@^0.10.0: 999 | version "0.10.0" 1000 | resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" 1001 | integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= 1002 | 1003 | pify@^2.0.0: 1004 | version "2.3.0" 1005 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 1006 | integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= 1007 | 1008 | pinkie-promise@^2.0.0: 1009 | version "2.0.1" 1010 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 1011 | dependencies: 1012 | pinkie "^2.0.0" 1013 | 1014 | pinkie@^2.0.0: 1015 | version "2.0.4" 1016 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 1017 | 1018 | prelude-ls@~1.1.2: 1019 | version "1.1.2" 1020 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 1021 | 1022 | pump@^3.0.0: 1023 | version "3.0.0" 1024 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1025 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 1026 | dependencies: 1027 | end-of-stream "^1.1.0" 1028 | once "^1.3.1" 1029 | 1030 | read-pkg-up@^1.0.1: 1031 | version "1.0.1" 1032 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 1033 | integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= 1034 | dependencies: 1035 | find-up "^1.0.0" 1036 | read-pkg "^1.0.0" 1037 | 1038 | read-pkg@^1.0.0: 1039 | version "1.1.0" 1040 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 1041 | integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= 1042 | dependencies: 1043 | load-json-file "^1.0.0" 1044 | normalize-package-data "^2.3.2" 1045 | path-type "^1.0.0" 1046 | 1047 | rechoir@^0.6.2: 1048 | version "0.6.2" 1049 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 1050 | dependencies: 1051 | resolve "^1.1.6" 1052 | 1053 | repeat-string@^1.5.2: 1054 | version "1.6.1" 1055 | resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 1056 | 1057 | req-cwd@^1.0.1: 1058 | version "1.0.1" 1059 | resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-1.0.1.tgz#0d73aeae9266e697a78f7976019677e76acf0fff" 1060 | dependencies: 1061 | req-from "^1.0.1" 1062 | 1063 | req-from@^1.0.1: 1064 | version "1.0.1" 1065 | resolved "https://registry.yarnpkg.com/req-from/-/req-from-1.0.1.tgz#bf81da5147947d32d13b947dc12a58ad4587350e" 1066 | dependencies: 1067 | resolve-from "^2.0.0" 1068 | 1069 | require-directory@^2.1.1: 1070 | version "2.1.1" 1071 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1072 | 1073 | require-from-string@^1.1.0: 1074 | version "1.2.1" 1075 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" 1076 | integrity sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg= 1077 | 1078 | require-main-filename@^1.0.1: 1079 | version "1.0.1" 1080 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" 1081 | integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= 1082 | 1083 | require-main-filename@^2.0.0: 1084 | version "2.0.0" 1085 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 1086 | integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== 1087 | 1088 | resolve-from@^2.0.0: 1089 | version "2.0.0" 1090 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" 1091 | 1092 | resolve@1.1.x: 1093 | version "1.1.7" 1094 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" 1095 | 1096 | resolve@^1.1.6: 1097 | version "1.5.0" 1098 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" 1099 | dependencies: 1100 | path-parse "^1.0.5" 1101 | 1102 | resolve@^1.10.0: 1103 | version "1.12.0" 1104 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" 1105 | integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== 1106 | dependencies: 1107 | path-parse "^1.0.6" 1108 | 1109 | right-align@^0.1.1: 1110 | version "0.1.3" 1111 | resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" 1112 | dependencies: 1113 | align-text "^0.1.1" 1114 | 1115 | rimraf@^2.2.8, rimraf@^2.6.3: 1116 | version "2.7.1" 1117 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" 1118 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 1119 | dependencies: 1120 | glob "^7.1.3" 1121 | 1122 | ripemd160@^2.0.0, ripemd160@^2.0.1: 1123 | version "2.0.1" 1124 | resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7" 1125 | dependencies: 1126 | hash-base "^2.0.0" 1127 | inherits "^2.0.1" 1128 | 1129 | rlp@^2.0.0: 1130 | version "2.2.4" 1131 | resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.4.tgz#d6b0e1659e9285fc509a5d169a9bd06f704951c1" 1132 | integrity sha512-fdq2yYCWpAQBhwkZv+Z8o/Z4sPmYm1CUq6P7n6lVTOdb949CnqA0sndXal5C1NleSVSZm6q5F3iEbauyVln/iw== 1133 | dependencies: 1134 | bn.js "^4.11.1" 1135 | 1136 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1: 1137 | version "5.1.1" 1138 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 1139 | 1140 | safe-buffer@^5.1.2: 1141 | version "5.2.0" 1142 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" 1143 | integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== 1144 | 1145 | secp256k1@^3.0.1: 1146 | version "3.7.1" 1147 | resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1" 1148 | integrity sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g== 1149 | dependencies: 1150 | bindings "^1.5.0" 1151 | bip66 "^1.1.5" 1152 | bn.js "^4.11.8" 1153 | create-hash "^1.2.0" 1154 | drbg.js "^1.0.1" 1155 | elliptic "^6.4.1" 1156 | nan "^2.14.0" 1157 | safe-buffer "^5.1.2" 1158 | 1159 | "semver@2 || 3 || 4 || 5", semver@^5.5.0: 1160 | version "5.5.0" 1161 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 1162 | 1163 | semver@^5.3.0: 1164 | version "5.7.1" 1165 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1166 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1167 | 1168 | set-blocking@^2.0.0: 1169 | version "2.0.0" 1170 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1171 | 1172 | sha.js@^2.4.0, sha.js@^2.4.8: 1173 | version "2.4.10" 1174 | resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b" 1175 | dependencies: 1176 | inherits "^2.0.1" 1177 | safe-buffer "^5.0.1" 1178 | 1179 | sha3@^1.1.0: 1180 | version "1.2.0" 1181 | resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.0.tgz#6989f1b70a498705876a373e2c62ace96aa9399a" 1182 | dependencies: 1183 | nan "^2.0.5" 1184 | 1185 | shebang-command@^1.2.0: 1186 | version "1.2.0" 1187 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1188 | dependencies: 1189 | shebang-regex "^1.0.0" 1190 | 1191 | shebang-regex@^1.0.0: 1192 | version "1.0.0" 1193 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1194 | 1195 | shell-escape@^0.2.0: 1196 | version "0.2.0" 1197 | resolved "https://registry.yarnpkg.com/shell-escape/-/shell-escape-0.2.0.tgz#68fd025eb0490b4f567a027f0bf22480b5f84133" 1198 | 1199 | shelljs@^0.7.4: 1200 | version "0.7.8" 1201 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" 1202 | integrity sha1-3svPh0sNHl+3LhSxZKloMEjprLM= 1203 | dependencies: 1204 | glob "^7.0.0" 1205 | interpret "^1.0.0" 1206 | rechoir "^0.6.2" 1207 | 1208 | signal-exit@^3.0.0: 1209 | version "3.0.2" 1210 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" 1211 | 1212 | sol-explore@^1.6.2: 1213 | version "1.6.2" 1214 | resolved "https://registry.yarnpkg.com/sol-explore/-/sol-explore-1.6.2.tgz#43ae8c419fd3ac056a05f8a9d1fb1022cd41ecc2" 1215 | 1216 | solc@0.4.26: 1217 | version "0.4.26" 1218 | resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.26.tgz#5390a62a99f40806b86258c737c1cf653cc35cb5" 1219 | integrity sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA== 1220 | dependencies: 1221 | fs-extra "^0.30.0" 1222 | memorystream "^0.3.1" 1223 | require-from-string "^1.1.0" 1224 | semver "^5.3.0" 1225 | yargs "^4.7.1" 1226 | 1227 | solidity-coverage@0.5.11: 1228 | version "0.5.11" 1229 | resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.5.11.tgz#1ee45f6d98b75a615aadb8f9aa7db4a2b32258e7" 1230 | integrity sha512-qikdsSi6+9XbfvwA0aI7HUVpF9fIFNqRWTw23M89GMDY+b6Gj0wWU9IngJS0fimoZIAdEp3bfChxvpfVcrUesg== 1231 | dependencies: 1232 | death "^1.1.0" 1233 | ethereumjs-testrpc-sc "6.1.6" 1234 | istanbul "^0.4.5" 1235 | keccakjs "^0.2.1" 1236 | req-cwd "^1.0.1" 1237 | shelljs "^0.7.4" 1238 | sol-explore "^1.6.2" 1239 | solidity-parser-sc "0.4.11" 1240 | tree-kill "^1.2.0" 1241 | web3 "^0.18.4" 1242 | 1243 | solidity-parser-sc@0.4.11: 1244 | version "0.4.11" 1245 | resolved "https://registry.yarnpkg.com/solidity-parser-sc/-/solidity-parser-sc-0.4.11.tgz#86734c9205537007f4d6201b57176e41696ee607" 1246 | integrity sha512-1kV5iC7m3CtMDfmHaVNwz2saSGQVIuF16rIxU417Al38MVCWHMQQ5vT6cmLsNwDe60S74auobWij9vNawSeOyw== 1247 | dependencies: 1248 | mocha "^4.1.0" 1249 | pegjs "^0.10.0" 1250 | yargs "^4.6.0" 1251 | 1252 | source-map-support@0.5.12: 1253 | version "0.5.12" 1254 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" 1255 | integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== 1256 | dependencies: 1257 | buffer-from "^1.0.0" 1258 | source-map "^0.6.0" 1259 | 1260 | source-map-support@^0.5.3: 1261 | version "0.5.16" 1262 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" 1263 | integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== 1264 | dependencies: 1265 | buffer-from "^1.0.0" 1266 | source-map "^0.6.0" 1267 | 1268 | source-map@^0.4.4: 1269 | version "0.4.4" 1270 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" 1271 | dependencies: 1272 | amdefine ">=0.0.4" 1273 | 1274 | source-map@^0.6.0: 1275 | version "0.6.1" 1276 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1277 | 1278 | source-map@~0.2.0: 1279 | version "0.2.0" 1280 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" 1281 | dependencies: 1282 | amdefine ">=0.0.4" 1283 | 1284 | source-map@~0.5.1: 1285 | version "0.5.7" 1286 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" 1287 | 1288 | spdx-correct@^3.0.0: 1289 | version "3.0.0" 1290 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" 1291 | dependencies: 1292 | spdx-expression-parse "^3.0.0" 1293 | spdx-license-ids "^3.0.0" 1294 | 1295 | spdx-exceptions@^2.1.0: 1296 | version "2.1.0" 1297 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" 1298 | 1299 | spdx-expression-parse@^3.0.0: 1300 | version "3.0.0" 1301 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" 1302 | dependencies: 1303 | spdx-exceptions "^2.1.0" 1304 | spdx-license-ids "^3.0.0" 1305 | 1306 | spdx-license-ids@^3.0.0: 1307 | version "3.0.0" 1308 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" 1309 | 1310 | sprintf-js@~1.0.2: 1311 | version "1.0.3" 1312 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1313 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 1314 | 1315 | string-width@^1.0.1: 1316 | version "1.0.2" 1317 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1318 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 1319 | dependencies: 1320 | code-point-at "^1.0.0" 1321 | is-fullwidth-code-point "^1.0.0" 1322 | strip-ansi "^3.0.0" 1323 | 1324 | string-width@^3.0.0, string-width@^3.1.0: 1325 | version "3.1.0" 1326 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 1327 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 1328 | dependencies: 1329 | emoji-regex "^7.0.1" 1330 | is-fullwidth-code-point "^2.0.0" 1331 | strip-ansi "^5.1.0" 1332 | 1333 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 1334 | version "3.0.1" 1335 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1336 | dependencies: 1337 | ansi-regex "^2.0.0" 1338 | 1339 | strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: 1340 | version "5.2.0" 1341 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 1342 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 1343 | dependencies: 1344 | ansi-regex "^4.1.0" 1345 | 1346 | strip-bom@^2.0.0: 1347 | version "2.0.0" 1348 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 1349 | integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= 1350 | dependencies: 1351 | is-utf8 "^0.2.0" 1352 | 1353 | strip-eof@^1.0.0: 1354 | version "1.0.0" 1355 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 1356 | 1357 | strip-hex-prefix@1.0.0: 1358 | version "1.0.0" 1359 | resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" 1360 | integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= 1361 | dependencies: 1362 | is-hex-prefixed "1.0.0" 1363 | 1364 | supports-color@4.4.0: 1365 | version "4.4.0" 1366 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" 1367 | integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== 1368 | dependencies: 1369 | has-flag "^2.0.0" 1370 | 1371 | supports-color@^3.1.0: 1372 | version "3.2.3" 1373 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" 1374 | dependencies: 1375 | has-flag "^1.0.0" 1376 | 1377 | tmp@0.1.0: 1378 | version "0.1.0" 1379 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" 1380 | integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== 1381 | dependencies: 1382 | rimraf "^2.6.3" 1383 | 1384 | tree-kill@^1.2.0: 1385 | version "1.2.1" 1386 | resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.1.tgz#5398f374e2f292b9dcc7b2e71e30a5c3bb6c743a" 1387 | integrity sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q== 1388 | 1389 | truffle@4.1.16: 1390 | version "4.1.16" 1391 | resolved "https://registry.yarnpkg.com/truffle/-/truffle-4.1.16.tgz#5cc160dcbbbcff6078e80ce328873d83247b084e" 1392 | integrity sha512-Ew0YSyy2802wqqe1Ko4kxo1FMffM+l9uEUXJ+GScwAAXFXwKWRC++eEa9pIIQdHcEj0rJo0jXhp65vS/LOcNwA== 1393 | dependencies: 1394 | mocha "^4.1.0" 1395 | original-require "1.0.1" 1396 | solc "0.4.26" 1397 | 1398 | type-check@~0.3.2: 1399 | version "0.3.2" 1400 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 1401 | dependencies: 1402 | prelude-ls "~1.1.2" 1403 | 1404 | uglify-js@^2.6: 1405 | version "2.8.29" 1406 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" 1407 | dependencies: 1408 | source-map "~0.5.1" 1409 | yargs "~3.10.0" 1410 | optionalDependencies: 1411 | uglify-to-browserify "~1.0.0" 1412 | 1413 | uglify-to-browserify@~1.0.0: 1414 | version "1.0.2" 1415 | resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" 1416 | 1417 | utf8@^2.1.1: 1418 | version "2.1.2" 1419 | resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" 1420 | integrity sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY= 1421 | 1422 | validate-npm-package-license@^3.0.1: 1423 | version "3.0.3" 1424 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" 1425 | dependencies: 1426 | spdx-correct "^3.0.0" 1427 | spdx-expression-parse "^3.0.0" 1428 | 1429 | web3@^0.18.4: 1430 | version "0.18.4" 1431 | resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" 1432 | integrity sha1-gewXhBRUkfLqqJVbMcBgSeB8Xn0= 1433 | dependencies: 1434 | bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" 1435 | crypto-js "^3.1.4" 1436 | utf8 "^2.1.1" 1437 | xhr2 "*" 1438 | xmlhttprequest "*" 1439 | 1440 | which-module@^1.0.0: 1441 | version "1.0.0" 1442 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" 1443 | integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= 1444 | 1445 | which-module@^2.0.0: 1446 | version "2.0.0" 1447 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 1448 | 1449 | which@^1.1.1, which@^1.2.9: 1450 | version "1.3.0" 1451 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" 1452 | dependencies: 1453 | isexe "^2.0.0" 1454 | 1455 | window-size@0.1.0: 1456 | version "0.1.0" 1457 | resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" 1458 | 1459 | window-size@^0.2.0: 1460 | version "0.2.0" 1461 | resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" 1462 | integrity sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU= 1463 | 1464 | wordwrap@0.0.2: 1465 | version "0.0.2" 1466 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" 1467 | 1468 | wordwrap@^1.0.0, wordwrap@~1.0.0: 1469 | version "1.0.0" 1470 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 1471 | 1472 | wordwrap@~0.0.2: 1473 | version "0.0.3" 1474 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" 1475 | 1476 | wrap-ansi@^2.0.0: 1477 | version "2.1.0" 1478 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 1479 | integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= 1480 | dependencies: 1481 | string-width "^1.0.1" 1482 | strip-ansi "^3.0.1" 1483 | 1484 | wrap-ansi@^5.1.0: 1485 | version "5.1.0" 1486 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" 1487 | integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== 1488 | dependencies: 1489 | ansi-styles "^3.2.0" 1490 | string-width "^3.0.0" 1491 | strip-ansi "^5.0.0" 1492 | 1493 | wrappy@1: 1494 | version "1.0.2" 1495 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1496 | 1497 | xhr2@*: 1498 | version "0.2.0" 1499 | resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.2.0.tgz#eddeff782f3b7551061b8d75645085269396e521" 1500 | integrity sha512-BDtiD0i2iKPK/S8OAZfpk6tyzEDnKKSjxWHcMBVmh+LuqJ8A32qXTyOx+TVOg2dKvq6zGBq2sgKPkEeRs1qTRA== 1501 | 1502 | xmlhttprequest@*: 1503 | version "1.8.0" 1504 | resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" 1505 | integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= 1506 | 1507 | y18n@^3.2.1: 1508 | version "3.2.1" 1509 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" 1510 | integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= 1511 | 1512 | y18n@^4.0.0: 1513 | version "4.0.0" 1514 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" 1515 | integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== 1516 | 1517 | yargs-parser@^13.1.0: 1518 | version "13.1.1" 1519 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" 1520 | integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== 1521 | dependencies: 1522 | camelcase "^5.0.0" 1523 | decamelize "^1.2.0" 1524 | 1525 | yargs-parser@^2.4.1: 1526 | version "2.4.1" 1527 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" 1528 | integrity sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ= 1529 | dependencies: 1530 | camelcase "^3.0.0" 1531 | lodash.assign "^4.0.6" 1532 | 1533 | yargs@13.2.4: 1534 | version "13.2.4" 1535 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" 1536 | integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg== 1537 | dependencies: 1538 | cliui "^5.0.0" 1539 | find-up "^3.0.0" 1540 | get-caller-file "^2.0.1" 1541 | os-locale "^3.1.0" 1542 | require-directory "^2.1.1" 1543 | require-main-filename "^2.0.0" 1544 | set-blocking "^2.0.0" 1545 | string-width "^3.0.0" 1546 | which-module "^2.0.0" 1547 | y18n "^4.0.0" 1548 | yargs-parser "^13.1.0" 1549 | 1550 | yargs@^4.6.0, yargs@^4.7.1: 1551 | version "4.8.1" 1552 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" 1553 | integrity sha1-wMQpJMpKqmsObaFznfshZDn53cA= 1554 | dependencies: 1555 | cliui "^3.2.0" 1556 | decamelize "^1.1.1" 1557 | get-caller-file "^1.0.1" 1558 | lodash.assign "^4.0.3" 1559 | os-locale "^1.4.0" 1560 | read-pkg-up "^1.0.1" 1561 | require-directory "^2.1.1" 1562 | require-main-filename "^1.0.1" 1563 | set-blocking "^2.0.0" 1564 | string-width "^1.0.1" 1565 | which-module "^1.0.0" 1566 | window-size "^0.2.0" 1567 | y18n "^3.2.1" 1568 | yargs-parser "^2.4.1" 1569 | 1570 | yargs@~3.10.0: 1571 | version "3.10.0" 1572 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" 1573 | dependencies: 1574 | camelcase "^1.0.2" 1575 | cliui "^2.1.0" 1576 | decamelize "^1.0.0" 1577 | window-size "0.1.0" 1578 | --------------------------------------------------------------------------------