├── .gitattributes ├── .gitignore ├── README.md ├── ethereum ├── .gitignore ├── contracts │ ├── ERC20Interface.sol │ ├── Migrations.sol │ ├── SecretNote.sol │ └── verifier.sol ├── migrations │ ├── 1_initial_migration.js │ └── 2_deploy_contracts.js ├── scripts │ ├── claimNote.js │ ├── createNote.js │ ├── debug.js │ ├── listener.js │ ├── proof.json │ ├── transferNote.js │ └── zokcmd.js ├── test │ ├── SecretNoteTest.js │ └── verifierTest.js ├── truffle.js └── zk-circuit.code ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json └── src ├── App.css ├── App.js ├── App.test.js ├── components ├── home.js ├── landing.js ├── stateless │ ├── cashTable.js │ └── ownerCashTable.js ├── swapper.js └── zeroCash.js ├── index.css ├── index.js ├── logo.svg ├── production ├── SecretNote.json ├── ganacheWeb3.js ├── kyber │ ├── abi │ │ ├── KNC.abi │ │ ├── KyberNetworkProxy.abi │ │ ├── MANA.abi │ │ ├── OMG.abi │ │ ├── SALT.abi │ │ └── ZIL.abi │ ├── getExpectedRate.js │ ├── swapEtherToToken.js │ ├── swapTokenToEther.js │ ├── swapTokenToToken.js │ └── trade.js ├── secretNote.js └── web3.js └── serviceWorker.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZkDAI 2 | Private DAI transactions on ethereum. 3 | 4 | [Demo video](https://youtu.be/55qt4tj2O3Y) 5 | 6 | [Devpost](https://devpost.com/software/ethsingapore-zk-dai) 7 | 8 | [Slides](https://docs.google.com/presentation/d/1wQgbbT8A4Jwr3X3EC7oubtVlL_kNNlTS4z9XSxpXIQo/edit?usp=sharing) 9 | 10 | 11 | Dev setup instructions 12 | [Video](https://www.youtube.com/watch?v=DCnaUYbk75k&feature=youtu.be) 13 | -------------------------------------------------------------------------------- /ethereum/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /ethereum/contracts/ERC20Interface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | 4 | // https://github.com/ethereum/EIPs/issues/20 5 | interface ERC20 { 6 | function totalSupply() public view returns (uint supply); 7 | function balanceOf(address _owner) public view returns (uint balance); 8 | function transfer(address _to, uint _value) public returns (bool success); 9 | function transferFrom(address _from, address _to, uint _value) public returns (bool success); 10 | function approve(address _spender, uint _value) public returns (bool success); 11 | function allowance(address _owner, address _spender) public view returns (uint remaining); 12 | function decimals() public view returns(uint digits); 13 | event Approval(address indexed _owner, address indexed _spender, uint _value); 14 | } 15 | -------------------------------------------------------------------------------- /ethereum/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.23; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ethereum/contracts/SecretNote.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | import "./ERC20Interface.sol"; 4 | import "./verifier.sol"; 5 | 6 | contract SecretNote is Verifier { 7 | 8 | ERC20 internal DAI_TOKEN_ADDRESS = ERC20(0xad6d458402f60fd3bd25163575031acdce07538d); 9 | 10 | constructor() {} 11 | 12 | enum State {Invalid, Created, Spent} 13 | mapping(bytes32 => State) public notes; // mapping of hash of the note to state 14 | string[] public allNotes; 15 | bytes32[] public allHashedNotes; 16 | 17 | function createNote(address owner, uint amount, string encryptedNote) public { 18 | bytes32 note = sha256(bytes32(owner), bytes32(amount)); 19 | createNote(note, encryptedNote); 20 | } 21 | 22 | function claimNote(uint amount) public { 23 | bytes32 note = sha256(bytes32(msg.sender), bytes32(amount)); 24 | require( 25 | notes[note] == State.Created, 26 | 'note doesnt exist' 27 | ); 28 | notes[note] = State.Spent; 29 | require( 30 | DAI_TOKEN_ADDRESS.transfer(msg.sender, amount * (10 ** 18)), 31 | 'daiToken transfer failed' 32 | ); 33 | emit Claim(msg.sender, amount * (10 ** 18)); 34 | } 35 | event Claim(address to, uint amount); 36 | 37 | function transferNote( 38 | uint[2] a, 39 | uint[2] a_p, 40 | uint[2][2] b, 41 | uint[2] b_p, 42 | uint[2] c, 43 | uint[2] c_p, 44 | uint[2] h, 45 | uint[2] k, 46 | uint[7] input, 47 | string encryptedNote1, 48 | string encryptedNote2 49 | ) { 50 | require( 51 | verifyTx(a, a_p, b, b_p, c, c_p, h, k, input), 52 | 'Invalid zk proof' 53 | ); 54 | 55 | bytes32 spendingNote = calcNoteHash(input[0], input[1]); 56 | require( 57 | notes[spendingNote] == State.Created, 58 | 'spendingNote doesnt exist' 59 | ); 60 | 61 | notes[spendingNote] = State.Spent; 62 | bytes32 newNote1 = calcNoteHash(input[2], input[3]); 63 | createNote(newNote1, encryptedNote1); 64 | bytes32 newNote2 = calcNoteHash(input[4], input[5]); 65 | createNote(newNote2, encryptedNote2); 66 | } 67 | 68 | function getNotesLength() public view returns(uint) { 69 | return allNotes.length; 70 | } 71 | 72 | event NoteCreated(bytes32 noteId, uint index); 73 | function createNote(bytes32 note, string encryptedNote) internal { 74 | notes[note] = State.Created; 75 | allNotes.push(encryptedNote); 76 | allHashedNotes.push(note); 77 | emit NoteCreated(note, allNotes.length - 1); 78 | } 79 | 80 | function calcNoteHash(uint _a, uint _b) internal returns(bytes32 note) { 81 | bytes16 a = bytes16(_a); 82 | bytes16 b = bytes16(_b); 83 | bytes memory _note = new bytes(32); 84 | 85 | for (uint i = 0; i < 16; i++) { 86 | _note[i] = a[i]; 87 | _note[16 + i] = b[i]; 88 | } 89 | note = bytesToBytes32(_note, 0); 90 | } 91 | 92 | function bytesToBytes32(bytes b, uint offset) internal pure returns (bytes32) { 93 | bytes32 out; 94 | for (uint i = 0; i < 32; i++) { 95 | out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); 96 | } 97 | return out; 98 | } 99 | } -------------------------------------------------------------------------------- /ethereum/contracts/verifier.sol: -------------------------------------------------------------------------------- 1 | // This file is MIT Licensed. 2 | // 3 | // Copyright 2017 Christian Reitwiessner 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 7 | 8 | pragma solidity ^0.4.14; 9 | library Pairing { 10 | struct G1Point { 11 | uint X; 12 | uint Y; 13 | } 14 | // Encoding of field elements is: X[0] * z + X[1] 15 | struct G2Point { 16 | uint[2] X; 17 | uint[2] Y; 18 | } 19 | /// @return the generator of G1 20 | function P1() pure internal returns (G1Point) { 21 | return G1Point(1, 2); 22 | } 23 | /// @return the generator of G2 24 | function P2() pure internal returns (G2Point) { 25 | return G2Point( 26 | [11559732032986387107991004021392285783925812861821192530917403151452391805634, 27 | 10857046999023057135944570762232829481370756359578518086990519993285655852781], 28 | [4082367875863433681332203403145435568316851327593401208105741076214120093531, 29 | 8495653923123431417604973247489272438418190587263600148770280649306958101930] 30 | ); 31 | } 32 | /// @return the negation of p, i.e. p.addition(p.negate()) should be zero. 33 | function negate(G1Point p) pure internal returns (G1Point) { 34 | // The prime q in the base field F_q for G1 35 | uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583; 36 | if (p.X == 0 && p.Y == 0) 37 | return G1Point(0, 0); 38 | return G1Point(p.X, q - (p.Y % q)); 39 | } 40 | /// @return the sum of two points of G1 41 | function addition(G1Point p1, G1Point p2) internal returns (G1Point r) { 42 | uint[4] memory input; 43 | input[0] = p1.X; 44 | input[1] = p1.Y; 45 | input[2] = p2.X; 46 | input[3] = p2.Y; 47 | bool success; 48 | assembly { 49 | success := call(sub(gas, 2000), 6, 0, input, 0xc0, r, 0x60) 50 | // Use "invalid" to make gas estimation work 51 | switch success case 0 { invalid() } 52 | } 53 | require(success); 54 | } 55 | /// @return the product of a point on G1 and a scalar, i.e. 56 | /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p. 57 | function scalar_mul(G1Point p, uint s) internal returns (G1Point r) { 58 | uint[3] memory input; 59 | input[0] = p.X; 60 | input[1] = p.Y; 61 | input[2] = s; 62 | bool success; 63 | assembly { 64 | success := call(sub(gas, 2000), 7, 0, input, 0x80, r, 0x60) 65 | // Use "invalid" to make gas estimation work 66 | switch success case 0 { invalid() } 67 | } 68 | require (success); 69 | } 70 | /// @return the result of computing the pairing check 71 | /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 72 | /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should 73 | /// return true. 74 | function pairing(G1Point[] p1, G2Point[] p2) internal returns (bool) { 75 | require(p1.length == p2.length); 76 | uint elements = p1.length; 77 | uint inputSize = elements * 6; 78 | uint[] memory input = new uint[](inputSize); 79 | for (uint i = 0; i < elements; i++) 80 | { 81 | input[i * 6 + 0] = p1[i].X; 82 | input[i * 6 + 1] = p1[i].Y; 83 | input[i * 6 + 2] = p2[i].X[0]; 84 | input[i * 6 + 3] = p2[i].X[1]; 85 | input[i * 6 + 4] = p2[i].Y[0]; 86 | input[i * 6 + 5] = p2[i].Y[1]; 87 | } 88 | uint[1] memory out; 89 | bool success; 90 | assembly { 91 | success := call(sub(gas, 2000), 8, 0, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) 92 | // Use "invalid" to make gas estimation work 93 | switch success case 0 { invalid() } 94 | } 95 | require(success); 96 | return out[0] != 0; 97 | } 98 | /// Convenience method for a pairing check for two pairs. 99 | function pairingProd2(G1Point a1, G2Point a2, G1Point b1, G2Point b2) internal returns (bool) { 100 | G1Point[] memory p1 = new G1Point[](2); 101 | G2Point[] memory p2 = new G2Point[](2); 102 | p1[0] = a1; 103 | p1[1] = b1; 104 | p2[0] = a2; 105 | p2[1] = b2; 106 | return pairing(p1, p2); 107 | } 108 | /// Convenience method for a pairing check for three pairs. 109 | function pairingProd3( 110 | G1Point a1, G2Point a2, 111 | G1Point b1, G2Point b2, 112 | G1Point c1, G2Point c2 113 | ) internal returns (bool) { 114 | G1Point[] memory p1 = new G1Point[](3); 115 | G2Point[] memory p2 = new G2Point[](3); 116 | p1[0] = a1; 117 | p1[1] = b1; 118 | p1[2] = c1; 119 | p2[0] = a2; 120 | p2[1] = b2; 121 | p2[2] = c2; 122 | return pairing(p1, p2); 123 | } 124 | /// Convenience method for a pairing check for four pairs. 125 | function pairingProd4( 126 | G1Point a1, G2Point a2, 127 | G1Point b1, G2Point b2, 128 | G1Point c1, G2Point c2, 129 | G1Point d1, G2Point d2 130 | ) internal returns (bool) { 131 | G1Point[] memory p1 = new G1Point[](4); 132 | G2Point[] memory p2 = new G2Point[](4); 133 | p1[0] = a1; 134 | p1[1] = b1; 135 | p1[2] = c1; 136 | p1[3] = d1; 137 | p2[0] = a2; 138 | p2[1] = b2; 139 | p2[2] = c2; 140 | p2[3] = d2; 141 | return pairing(p1, p2); 142 | } 143 | } 144 | contract Verifier { 145 | using Pairing for *; 146 | struct VerifyingKey { 147 | Pairing.G2Point A; 148 | Pairing.G1Point B; 149 | Pairing.G2Point C; 150 | Pairing.G2Point gamma; 151 | Pairing.G1Point gammaBeta1; 152 | Pairing.G2Point gammaBeta2; 153 | Pairing.G2Point Z; 154 | Pairing.G1Point[] IC; 155 | } 156 | struct Proof { 157 | Pairing.G1Point A; 158 | Pairing.G1Point A_p; 159 | Pairing.G2Point B; 160 | Pairing.G1Point B_p; 161 | Pairing.G1Point C; 162 | Pairing.G1Point C_p; 163 | Pairing.G1Point K; 164 | Pairing.G1Point H; 165 | } 166 | function verifyingKey() pure internal returns (VerifyingKey vk) { 167 | vk.A = Pairing.G2Point([0x1a8f6dffaed1c959a7d71aa2657a2a789c8cf89f326b588c05ab37a9f39e1b4e, 0x16e8c896c9f76efde51c34cf38958f1d135e640938bb93b3fe1b916afbe2180f], [0x555d5dab0f873f97e7678be2a449985c768165af93602d4d16972816f3f16d1, 0x1a3cc67e34d012cd4e4f3fb518360e02c302e4d686a91f5986697865ace1caa4]); 168 | vk.B = Pairing.G1Point(0x13d238247df32190384980ed184e542ac93ddc5979c5db32e337b4ec609d33fe, 0x25f1dd410d4f3e32985866c99bf12ee9dbd00f8d7199120a9c773cf497d4c7c8); 169 | vk.C = Pairing.G2Point([0x2da063c189bf638f9c002b7c12419c0f06e17b80838454af497b0a17d6152342, 0x3b5a992bf33a454f0dcf9fbb9d789ce1f54475c5d51d93919494f62cc2e6097], [0x1e128bdc2bbd373e265113a5c2c5baa41c4831e50005260d702421dae2a028ec, 0xba58826e1eb8e21ccc98da25bd87af438cff5c28297807f687aafc56ddb9e21]); 170 | vk.gamma = Pairing.G2Point([0x28921c80556a6fcce84f693cac87c0f8772ecd4511b1383f39f50837df73770a, 0x5dada211aa99b96d72fd7164b99c65b51b6e9d72161a50b85c365af1e0e4ea7], [0x21da090cbd4f5b7551d41aed5ee9ba64b6c8a42c7e1824296420f1f964adf50, 0xd94b34e3ffc829279f46e39b6bf15e129225c67f0fdad865b96dbb320e32c89]); 171 | vk.gammaBeta1 = Pairing.G1Point(0x4f700830971f262c6b64ea7be3f1d83e540f08d6c4602ceda8b4002757bb08, 0x15b17a574ee3017c65ccb79b5352025473d1670ba8b1a6f4d75036a27b7164cf); 172 | vk.gammaBeta2 = Pairing.G2Point([0xdcde8fac990ca51c4a30e6b8d3d65fc603e8f4c697b2751b518bfb62c3766c8, 0x206a0b60cf83518fce1a034beaac502dbb88facf91a5e0781038697e9b35bd51], [0x1e2a317cc69ce2f8c9602e61d204de4c9a388c811670748b8ef8c1dc1cb74f51, 0x30b94e7e1f772aa30206e8dd9c8bacc40418da6758ed456be78240d0c7dae06]); 173 | vk.Z = Pairing.G2Point([0x147446f69a2130e8b430a91d539ed116a4fe6a355ff3965b126fbc7d726327ce, 0xd8aece85d17d3935909e9b40633d8ee762bb3b2d385606e95095794859cc0cc], [0x1e1ff543c3e4898147e5b53bdb7afd09b021539a287f86bdca21de042c698a31, 0xbaf91af14027a68bd44d9752570c5e8bd3811203fe45daa6dfe26dc3dc1d94d]); 174 | vk.IC = new Pairing.G1Point[](8); 175 | vk.IC[0] = Pairing.G1Point(0x7a9ca7be3dabc10b743e4197fdeb58336f061b5b298acaabad3856857c444c5, 0x297369c7601b9f352bc72bdbdc9db0a45a53d2005ac1ac5b465484b550dc37cc); 176 | vk.IC[1] = Pairing.G1Point(0x2b613dd24e9637212712b7e544254283766556df4ef593fa12f0304bbbe42e79, 0x2e454ec4cca92db576a178f1d974a3b5764f20d4f8d24dce4c5739477da3770e); 177 | vk.IC[2] = Pairing.G1Point(0x1b67fd85eca0e51c466d5e745afee799f48aef820fae99c5de7a755bd95f796d, 0xb1974ae8e2ce51f931c2df183312aa426f6f9e6598d913fc7e571384cff5002); 178 | vk.IC[3] = Pairing.G1Point(0x949bb1e30664f373d9abf5be86c66a886d0fad11fda0a47fcdc33d36285dea3, 0x8d8da79e509592eb1a981e96a0cf02aa4a148cc795bad859576ee0d65f2935a); 179 | vk.IC[4] = Pairing.G1Point(0x2c74a3233ca44615eae03effad335f6c1dd1ab2d9e8df100662855325df478c, 0xae767525b2d60cb58bbb83bd6619bbc8a16fca0c350dc690048c4bcac54a50e); 180 | vk.IC[5] = Pairing.G1Point(0xd895438a8263bb4806def515d34f0045a4e053dc4322b236983694736086ea3, 0x18eb2ad17e99cd883a85289b2425c30bd0ca8ec8c337edea9beb6cbb6c9b6ffa); 181 | vk.IC[6] = Pairing.G1Point(0x2e81bd8679092fe9558f1a720781a38bc85893e9a8f5bfc588f0df175fb5fcb6, 0x430be466714efe5e9f3134b8303b92553289571a7e338c283f1591a458886c7); 182 | vk.IC[7] = Pairing.G1Point(0x1e4d988b5a23db2a6623dafdafe16fd5f93ba4131a621a2eea571515669c4de6, 0xaf140f4d92d62259a0409837a8027056692f0bc63cb402f66303a9855849160); 183 | } 184 | function verify(uint[] input, Proof proof) internal returns (uint) { 185 | VerifyingKey memory vk = verifyingKey(); 186 | require(input.length + 1 == vk.IC.length); 187 | // Compute the linear combination vk_x 188 | Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); 189 | for (uint i = 0; i < input.length; i++) 190 | vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i])); 191 | vk_x = Pairing.addition(vk_x, vk.IC[0]); 192 | if (!Pairing.pairingProd2(proof.A, vk.A, Pairing.negate(proof.A_p), Pairing.P2())) return 1; 193 | if (!Pairing.pairingProd2(vk.B, proof.B, Pairing.negate(proof.B_p), Pairing.P2())) return 2; 194 | if (!Pairing.pairingProd2(proof.C, vk.C, Pairing.negate(proof.C_p), Pairing.P2())) return 3; 195 | if (!Pairing.pairingProd3( 196 | proof.K, vk.gamma, 197 | Pairing.negate(Pairing.addition(vk_x, Pairing.addition(proof.A, proof.C))), vk.gammaBeta2, 198 | Pairing.negate(vk.gammaBeta1), proof.B 199 | )) return 4; 200 | if (!Pairing.pairingProd3( 201 | Pairing.addition(vk_x, proof.A), proof.B, 202 | Pairing.negate(proof.H), vk.Z, 203 | Pairing.negate(proof.C), Pairing.P2() 204 | )) return 5; 205 | return 0; 206 | } 207 | event Verified(string s); 208 | function verifyTx( 209 | uint[2] a, 210 | uint[2] a_p, 211 | uint[2][2] b, 212 | uint[2] b_p, 213 | uint[2] c, 214 | uint[2] c_p, 215 | uint[2] h, 216 | uint[2] k, 217 | uint[7] input 218 | ) public returns (bool r) { 219 | Proof memory proof; 220 | proof.A = Pairing.G1Point(a[0], a[1]); 221 | proof.A_p = Pairing.G1Point(a_p[0], a_p[1]); 222 | proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); 223 | proof.B_p = Pairing.G1Point(b_p[0], b_p[1]); 224 | proof.C = Pairing.G1Point(c[0], c[1]); 225 | proof.C_p = Pairing.G1Point(c_p[0], c_p[1]); 226 | proof.H = Pairing.G1Point(h[0], h[1]); 227 | proof.K = Pairing.G1Point(k[0], k[1]); 228 | uint[] memory inputValues = new uint[](input.length); 229 | for(uint i = 0; i < input.length; i++){ 230 | inputValues[i] = input[i]; 231 | } 232 | if (verify(inputValues, proof) == 0) { 233 | emit Verified("Transaction successfully verified."); 234 | return true; 235 | } else { 236 | return false; 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /ethereum/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /ethereum/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | // var verifier = artifacts.require("./verifier.sol"); 2 | var SecretNote = artifacts.require("./SecretNote.sol"); 3 | 4 | module.exports = function(deployer) { 5 | // deployer.deploy(SecretNote, 0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, 0x00eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee); 6 | deployer.deploy(SecretNote); 7 | }; 8 | -------------------------------------------------------------------------------- /ethereum/scripts/claimNote.js: -------------------------------------------------------------------------------- 1 | // const contractArtifact = artifacts.require('./SecretNote.sol'); 2 | // import secretNoteContract from './listener.js'; 3 | const abi = [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "a", 9 | "type": "uint256[2]" 10 | }, 11 | { 12 | "name": "a_p", 13 | "type": "uint256[2]" 14 | }, 15 | { 16 | "name": "b", 17 | "type": "uint256[2][2]" 18 | }, 19 | { 20 | "name": "b_p", 21 | "type": "uint256[2]" 22 | }, 23 | { 24 | "name": "c", 25 | "type": "uint256[2]" 26 | }, 27 | { 28 | "name": "c_p", 29 | "type": "uint256[2]" 30 | }, 31 | { 32 | "name": "h", 33 | "type": "uint256[2]" 34 | }, 35 | { 36 | "name": "k", 37 | "type": "uint256[2]" 38 | }, 39 | { 40 | "name": "input", 41 | "type": "uint256[7]" 42 | } 43 | ], 44 | "name": "verifyTx", 45 | "outputs": [ 46 | { 47 | "name": "r", 48 | "type": "bool" 49 | } 50 | ], 51 | "payable": false, 52 | "stateMutability": "nonpayable", 53 | "type": "function" 54 | }, 55 | { 56 | "constant": true, 57 | "inputs": [ 58 | { 59 | "name": "", 60 | "type": "uint256" 61 | } 62 | ], 63 | "name": "allHashedNotes", 64 | "outputs": [ 65 | { 66 | "name": "", 67 | "type": "bytes32" 68 | } 69 | ], 70 | "payable": false, 71 | "stateMutability": "view", 72 | "type": "function" 73 | }, 74 | { 75 | "constant": true, 76 | "inputs": [ 77 | { 78 | "name": "", 79 | "type": "bytes32" 80 | } 81 | ], 82 | "name": "notes", 83 | "outputs": [ 84 | { 85 | "name": "", 86 | "type": "uint8" 87 | } 88 | ], 89 | "payable": false, 90 | "stateMutability": "view", 91 | "type": "function" 92 | }, 93 | { 94 | "constant": true, 95 | "inputs": [ 96 | { 97 | "name": "", 98 | "type": "uint256" 99 | } 100 | ], 101 | "name": "allNotes", 102 | "outputs": [ 103 | { 104 | "name": "", 105 | "type": "string" 106 | } 107 | ], 108 | "payable": false, 109 | "stateMutability": "view", 110 | "type": "function" 111 | }, 112 | { 113 | "inputs": [], 114 | "payable": false, 115 | "stateMutability": "nonpayable", 116 | "type": "constructor" 117 | }, 118 | { 119 | "anonymous": false, 120 | "inputs": [ 121 | { 122 | "indexed": false, 123 | "name": "m", 124 | "type": "bytes32" 125 | }, 126 | { 127 | "indexed": false, 128 | "name": "m2", 129 | "type": "bytes32" 130 | } 131 | ], 132 | "name": "debug", 133 | "type": "event" 134 | }, 135 | { 136 | "anonymous": false, 137 | "inputs": [ 138 | { 139 | "indexed": false, 140 | "name": "noteId", 141 | "type": "bytes32" 142 | }, 143 | { 144 | "indexed": false, 145 | "name": "index", 146 | "type": "uint256" 147 | } 148 | ], 149 | "name": "NoteCreated", 150 | "type": "event" 151 | }, 152 | { 153 | "anonymous": false, 154 | "inputs": [ 155 | { 156 | "indexed": false, 157 | "name": "a", 158 | "type": "bytes16" 159 | }, 160 | { 161 | "indexed": false, 162 | "name": "b", 163 | "type": "bytes16" 164 | } 165 | ], 166 | "name": "d2", 167 | "type": "event" 168 | }, 169 | { 170 | "anonymous": false, 171 | "inputs": [ 172 | { 173 | "indexed": false, 174 | "name": "s", 175 | "type": "string" 176 | } 177 | ], 178 | "name": "Verified", 179 | "type": "event" 180 | }, 181 | { 182 | "constant": true, 183 | "inputs": [], 184 | "name": "getNotesLength", 185 | "outputs": [ 186 | { 187 | "name": "", 188 | "type": "uint256" 189 | } 190 | ], 191 | "payable": false, 192 | "stateMutability": "view", 193 | "type": "function" 194 | }, 195 | { 196 | "constant": false, 197 | "inputs": [ 198 | { 199 | "name": "owner", 200 | "type": "address" 201 | }, 202 | { 203 | "name": "amount", 204 | "type": "uint256" 205 | }, 206 | { 207 | "name": "encryptedNote", 208 | "type": "string" 209 | } 210 | ], 211 | "name": "createNoteDummy", 212 | "outputs": [], 213 | "payable": false, 214 | "stateMutability": "nonpayable", 215 | "type": "function" 216 | }, 217 | { 218 | "constant": false, 219 | "inputs": [ 220 | { 221 | "name": "a", 222 | "type": "uint256[2]" 223 | }, 224 | { 225 | "name": "a_p", 226 | "type": "uint256[2]" 227 | }, 228 | { 229 | "name": "b", 230 | "type": "uint256[2][2]" 231 | }, 232 | { 233 | "name": "b_p", 234 | "type": "uint256[2]" 235 | }, 236 | { 237 | "name": "c", 238 | "type": "uint256[2]" 239 | }, 240 | { 241 | "name": "c_p", 242 | "type": "uint256[2]" 243 | }, 244 | { 245 | "name": "h", 246 | "type": "uint256[2]" 247 | }, 248 | { 249 | "name": "k", 250 | "type": "uint256[2]" 251 | }, 252 | { 253 | "name": "input", 254 | "type": "uint256[7]" 255 | }, 256 | { 257 | "name": "encryptedNote1", 258 | "type": "string" 259 | }, 260 | { 261 | "name": "encryptedNote2", 262 | "type": "string" 263 | } 264 | ], 265 | "name": "transferNote", 266 | "outputs": [], 267 | "payable": false, 268 | "stateMutability": "nonpayable", 269 | "type": "function" 270 | } 271 | ] 272 | 273 | const secretNoteAddress = '0x1578d87c52be8bcddb6d8f8e9b3749e06ad814d0' 274 | 275 | const BN = require('bn.js') 276 | const fs = require('fs'); 277 | const path = require('path'); 278 | 279 | async function execute() { 280 | // console.log(path.join(__dirname, 'proof.json')) 281 | let proofJson = fs.readFileSync(path.join(__dirname, 'proof.json'), 'utf8'); 282 | var rx2 = /([0-9]+)[,]/gm 283 | // console.log(proofJson.match(rx2)) 284 | proofJson.match(rx2).forEach(p => { 285 | proofJson = proofJson.replace(p, `"${p.slice(0, p.length-1)}",`) 286 | }) 287 | proofJson = JSON.parse(proofJson); 288 | // console.log(proofJson) 289 | 290 | const proof = proofJson.proof; 291 | const input = proofJson.input; 292 | input.forEach((i, key) => { 293 | if (typeof i == 'number') i = i.toString(); 294 | input[key] = '0x' + new BN(i, 10).toString('hex') 295 | }) 296 | 297 | const _proof = []; 298 | Object.keys(proof).forEach(key => _proof.push(proof[key])); 299 | _proof.push(input) 300 | 301 | const encNote1 = await encrypt('9e8f633D0C46ED7170EF3B30E291c64a91a49C7E', '9'); 302 | const encNote2 = await encrypt('3644B986B3F5Ba3cb8D5627A22465942f8E06d09', '2'); 303 | // console.log(..._proof, encNote1, encNote2) 304 | console.log('calling transferNote with params', ..._proof, encNote1, encNote2); 305 | let secretNoteContract = new web3.eth.Contract(abi, secretNoteAddress); 306 | 307 | try { 308 | await secretNoteContract.methods.transferNote(..._proof, encNote1, encNote2) 309 | .send({ 310 | from: '0x2B522cABE9950D1153c26C1b399B293CaA99FcF9', 311 | gasPrice: '0x' + parseInt('10000000000').toString(16) 312 | }) 313 | // const tx = await instance.transferNote(..._proof, encNote1, encNote2); 314 | // console.dir(tx, {depth: null}); 315 | } catch(e) { 316 | console.log(e) 317 | } 318 | } 319 | 320 | async function encrypt(address, _amount) { 321 | // 20 12 322 | let amount = new BN(_amount, 16).toString(16, 24); // 12 bytes = 24 chars in hex 323 | const payload = address + amount; 324 | return payload; 325 | // console.log('enc payload', payload) 326 | // const encryptedNote = await web3.eth.accounts.encrypt('0x' + payload, 'vitalik') 327 | // return JSON.stringify(encryptedNote); 328 | } 329 | 330 | module.exports = async function(callback) { 331 | // perform actions 332 | await execute(); 333 | callback(); 334 | } -------------------------------------------------------------------------------- /ethereum/scripts/createNote.js: -------------------------------------------------------------------------------- 1 | const contractArtifact = artifacts.require('./SecretNote.sol'); 2 | const BN = require('bn.js') 3 | 4 | async function execute() { 5 | const accounts = await web3.eth.getAccounts(); 6 | // console.log(accounts) 7 | const instance = await contractArtifact.deployed(); 8 | let enc = await encrypt(accounts[0].slice(2), 'AF') 9 | console.log('enc', enc) 10 | const tx = await instance.createNoteDummy(accounts[0], '0xaf', enc); 11 | console.dir(tx, {depth: null}); 12 | } 13 | 14 | module.exports = async function(callback) { 15 | // perform actions 16 | await execute(); 17 | callback(); 18 | } 19 | 20 | // async function createNote() { 21 | // const SecretNote = new web3.eth.Contract( 22 | // compiledSecretNote.abi, 23 | // contractAddress 24 | // ); 25 | 26 | 27 | // } 28 | // let instance = await SecretNote.deployed(); 29 | // let enc = await encrypt(accounts[0].slice(2), '5') 30 | // const tx = await instance.createNoteDummy('0x5', enc); 31 | // console.dir(tx, {depth: null}); 32 | 33 | // const noteId = tx.logs[0].args.noteId; 34 | // const index = tx.logs[0].args.index; 35 | // // console.log('noteId', noteId) 36 | 37 | // // decrypt 38 | // const cipher = await instance.allNotes.call(index) 39 | // const noteHash = await decrypt(cipher); 40 | // console.log('noteHash', noteHash) 41 | // // check noteHash in mapping now 42 | // const state = await instance.notes.call('0x' + noteHash) 43 | // console.log('state', state.toNumber()) 44 | 45 | async function encrypt(address, _amount) { 46 | // 20 12 47 | let amount = new BN(_amount, 16).toString(16, 24); // 12 bytes = 24 chars in hex 48 | const payload = address + amount; 49 | return payload; 50 | // console.log('enc payload', payload) 51 | // const encryptedNote = await web3.eth.accounts.encrypt('0x' + payload, 'vitalik') 52 | // return JSON.stringify(encryptedNote); 53 | } 54 | 55 | // async function decrypt(cipher) { 56 | // let payload = await web3.eth.accounts.decrypt(JSON.parse(cipher), 'vitalik').privateKey 57 | // payload = payload.slice(2) 58 | // const address = payload.slice(0, 40) // remove 0x and 59 | // const amount = payload.slice(40) 60 | // console.log(address, amount); 61 | 62 | // // pad address and amount to 32bytes 63 | // let _address = new BN(address, 16).toString(16, 64); 64 | // let _amount = new BN(amount, 16).toString(16, 64); // 32 bytes = 64 chars in hex 65 | // const buf = Buffer.from(_address + _amount, 'hex'); 66 | // const digest = crypto.createHash('sha256').update(buf).digest('hex'); 67 | // return digest; 68 | // } -------------------------------------------------------------------------------- /ethereum/scripts/debug.js: -------------------------------------------------------------------------------- 1 | var BN = require('bn.js') 2 | console.log(new BN('5936233000000000000', 10).div(new BN('1000000000000000000')).toString('hex')) 3 | // console.log(new BN('4cb90df856e2ba65405b6443363920a6', 16).toString(10)) 4 | // console.log(new BN('101982185945281508769031670699010891942', 10).toString(16)) -------------------------------------------------------------------------------- /ethereum/scripts/listener.js: -------------------------------------------------------------------------------- 1 | const abi = [ 2 | { 3 | "constant": false, 4 | "inputs": [ 5 | { 6 | "name": "a", 7 | "type": "uint256[2]" 8 | }, 9 | { 10 | "name": "a_p", 11 | "type": "uint256[2]" 12 | }, 13 | { 14 | "name": "b", 15 | "type": "uint256[2][2]" 16 | }, 17 | { 18 | "name": "b_p", 19 | "type": "uint256[2]" 20 | }, 21 | { 22 | "name": "c", 23 | "type": "uint256[2]" 24 | }, 25 | { 26 | "name": "c_p", 27 | "type": "uint256[2]" 28 | }, 29 | { 30 | "name": "h", 31 | "type": "uint256[2]" 32 | }, 33 | { 34 | "name": "k", 35 | "type": "uint256[2]" 36 | }, 37 | { 38 | "name": "input", 39 | "type": "uint256[7]" 40 | } 41 | ], 42 | "name": "verifyTx", 43 | "outputs": [ 44 | { 45 | "name": "r", 46 | "type": "bool" 47 | } 48 | ], 49 | "payable": false, 50 | "stateMutability": "nonpayable", 51 | "type": "function", 52 | "signature": "0x1cdf1357" 53 | }, 54 | { 55 | "constant": true, 56 | "inputs": [ 57 | { 58 | "name": "", 59 | "type": "uint256" 60 | } 61 | ], 62 | "name": "allHashedNotes", 63 | "outputs": [ 64 | { 65 | "name": "", 66 | "type": "bytes32" 67 | } 68 | ], 69 | "payable": false, 70 | "stateMutability": "view", 71 | "type": "function", 72 | "signature": "0x58a5d596" 73 | }, 74 | { 75 | "constant": true, 76 | "inputs": [ 77 | { 78 | "name": "", 79 | "type": "bytes32" 80 | } 81 | ], 82 | "name": "notes", 83 | "outputs": [ 84 | { 85 | "name": "", 86 | "type": "uint8" 87 | } 88 | ], 89 | "payable": false, 90 | "stateMutability": "view", 91 | "type": "function", 92 | "signature": "0x85de26b7" 93 | }, 94 | { 95 | "constant": true, 96 | "inputs": [ 97 | { 98 | "name": "", 99 | "type": "uint256" 100 | } 101 | ], 102 | "name": "allNotes", 103 | "outputs": [ 104 | { 105 | "name": "", 106 | "type": "string" 107 | } 108 | ], 109 | "payable": false, 110 | "stateMutability": "view", 111 | "type": "function", 112 | "signature": "0xddabcf41" 113 | }, 114 | { 115 | "inputs": [], 116 | "payable": false, 117 | "stateMutability": "nonpayable", 118 | "type": "constructor", 119 | "signature": "constructor" 120 | }, 121 | { 122 | "anonymous": false, 123 | "inputs": [ 124 | { 125 | "indexed": false, 126 | "name": "m", 127 | "type": "bytes32" 128 | }, 129 | { 130 | "indexed": false, 131 | "name": "m2", 132 | "type": "bytes32" 133 | } 134 | ], 135 | "name": "debug", 136 | "type": "event", 137 | "signature": "0x02451fae0adb7ceff4e670c0e623b1c9e0b2898e612e291ad76e596de0a2d053" 138 | }, 139 | { 140 | "anonymous": false, 141 | "inputs": [ 142 | { 143 | "indexed": false, 144 | "name": "to", 145 | "type": "address" 146 | }, 147 | { 148 | "indexed": false, 149 | "name": "amount", 150 | "type": "uint256" 151 | } 152 | ], 153 | "name": "Claim", 154 | "type": "event", 155 | "signature": "0x47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4" 156 | }, 157 | { 158 | "anonymous": false, 159 | "inputs": [ 160 | { 161 | "indexed": false, 162 | "name": "noteId", 163 | "type": "bytes32" 164 | }, 165 | { 166 | "indexed": false, 167 | "name": "index", 168 | "type": "uint256" 169 | } 170 | ], 171 | "name": "NoteCreated", 172 | "type": "event", 173 | "signature": "0xc904a92388c152c0c63dfe30e3e880273673ef7d33ea18195aecb5ba50f546fc" 174 | }, 175 | { 176 | "anonymous": false, 177 | "inputs": [ 178 | { 179 | "indexed": false, 180 | "name": "a", 181 | "type": "bytes16" 182 | }, 183 | { 184 | "indexed": false, 185 | "name": "b", 186 | "type": "bytes16" 187 | } 188 | ], 189 | "name": "d2", 190 | "type": "event", 191 | "signature": "0xd278e8c3a630dc4a7eb08180a3880316949e0f4b449df0b97df01512353786ce" 192 | }, 193 | { 194 | "anonymous": false, 195 | "inputs": [ 196 | { 197 | "indexed": false, 198 | "name": "s", 199 | "type": "string" 200 | } 201 | ], 202 | "name": "Verified", 203 | "type": "event", 204 | "signature": "0x3f3cfdb26fb5f9f1786ab4f1a1f9cd4c0b5e726cbdfc26e495261731aad44e39" 205 | }, 206 | { 207 | "constant": true, 208 | "inputs": [], 209 | "name": "getNotesLength", 210 | "outputs": [ 211 | { 212 | "name": "", 213 | "type": "uint256" 214 | } 215 | ], 216 | "payable": false, 217 | "stateMutability": "view", 218 | "type": "function", 219 | "signature": "0xeb3d72d1" 220 | }, 221 | { 222 | "constant": false, 223 | "inputs": [ 224 | { 225 | "name": "owner", 226 | "type": "address" 227 | }, 228 | { 229 | "name": "amount", 230 | "type": "uint256" 231 | }, 232 | { 233 | "name": "encryptedNote", 234 | "type": "string" 235 | } 236 | ], 237 | "name": "createNoteDummy", 238 | "outputs": [], 239 | "payable": false, 240 | "stateMutability": "nonpayable", 241 | "type": "function", 242 | "signature": "0xd9758ae0" 243 | }, 244 | { 245 | "constant": false, 246 | "inputs": [ 247 | { 248 | "name": "amount", 249 | "type": "uint256" 250 | } 251 | ], 252 | "name": "claimNote", 253 | "outputs": [], 254 | "payable": false, 255 | "stateMutability": "nonpayable", 256 | "type": "function", 257 | "signature": "0xa4654ead" 258 | }, 259 | { 260 | "constant": false, 261 | "inputs": [ 262 | { 263 | "name": "a", 264 | "type": "uint256[2]" 265 | }, 266 | { 267 | "name": "a_p", 268 | "type": "uint256[2]" 269 | }, 270 | { 271 | "name": "b", 272 | "type": "uint256[2][2]" 273 | }, 274 | { 275 | "name": "b_p", 276 | "type": "uint256[2]" 277 | }, 278 | { 279 | "name": "c", 280 | "type": "uint256[2]" 281 | }, 282 | { 283 | "name": "c_p", 284 | "type": "uint256[2]" 285 | }, 286 | { 287 | "name": "h", 288 | "type": "uint256[2]" 289 | }, 290 | { 291 | "name": "k", 292 | "type": "uint256[2]" 293 | }, 294 | { 295 | "name": "input", 296 | "type": "uint256[7]" 297 | }, 298 | { 299 | "name": "encryptedNote1", 300 | "type": "string" 301 | }, 302 | { 303 | "name": "encryptedNote2", 304 | "type": "string" 305 | } 306 | ], 307 | "name": "transferNote", 308 | "outputs": [], 309 | "payable": false, 310 | "stateMutability": "nonpayable", 311 | "type": "function", 312 | "signature": "0x573d7339" 313 | } 314 | ] 315 | 316 | // import Web3 from 'web3'; 317 | const Web3 = require('web3'); 318 | const BN = require('bn.js') 319 | // const provider = new Web3.providers.HttpProvider( 320 | // 'https://ropsten.infura.io/v3/6dfe769f94364017b82a58d6b5c3543e' 321 | // ); 322 | 323 | // let web3 = new Web3(provider); 324 | const _web3 = new Web3(new Web3.providers.WebsocketProvider('wss://ropsten.infura.io/ws')) 325 | 326 | let daiContract = new _web3.eth.Contract([{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}], 327 | '0xaD6D458402F60fD3Bd25163575031ACDce07538D'); 328 | 329 | const secretNoteAddress = '0x187dc8FF9092471A71e344C18F52Cad17e43d719' 330 | 331 | let secretNoteContract = new web3.eth.Contract(abi, secretNoteAddress); 332 | // exports.module = {secretNoteAddress, abi}; 333 | 334 | const options = { 335 | filter: { 336 | to: secretNoteAddress, 337 | from: '0x91a502C678605fbCe581eae053319747482276b9', 338 | }, 339 | fromBlock: 'latest' 340 | } 341 | 342 | async function execute() { 343 | return new Promise((resolve, reject) => { 344 | let b = false; 345 | daiContract.events.Transfer(options, 346 | async (error, event) => { 347 | if (error) { 348 | console.log(error) 349 | return 350 | } 351 | console.log(event); 352 | 353 | // create secret note 354 | try { 355 | const tx = await web3.eth.getTransaction(event.transactionHash) 356 | const benefiaciary = tx.from.slice(2); 357 | const val = new BN(event.returnValues.value, 10).div(new BN('1000000000000000000')).toString('hex') 358 | if(!b) { 359 | b = true; 360 | await createNote(benefiaciary, val); 361 | } 362 | } catch(e) { 363 | console.log(e) 364 | } 365 | }) 366 | }) 367 | } 368 | 369 | async function createNote(address, amount) { 370 | let enc = encrypt(address, amount); 371 | console.log('enc', enc) 372 | await secretNoteContract.methods.createNoteDummy('0x' + address, '0x' + amount, enc) 373 | .send({ 374 | from: '0x2B522cABE9950D1153c26C1b399B293CaA99FcF9', 375 | gasPrice: '0x' + parseInt('10000000000').toString(16) 376 | }) 377 | } 378 | 379 | function encrypt(address, _amount) { 380 | let amount = new BN(_amount, 16).toString(16, 24); // 12 bytes = 24 chars in hex 381 | const payload = address + amount; 382 | return payload; 383 | } 384 | 385 | module.exports = async function(callback) { 386 | // perform actions 387 | await execute(); 388 | callback(); 389 | } -------------------------------------------------------------------------------- /ethereum/scripts/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "proof": 3 | { 4 | "A":["0x233b7323a1eff097ea957f885bbbed0099feafbbb1c9e1547bc18d8f37107e7", "0x2471a4f529416582c38d4f2edc6affeba73960a6acc9953a8fb94a797e1c2e"], 5 | "A_p":["0x29ccf24672d2c7a97fbd1cd85f18620379a10478de8627a3d7c52a630bb299dd", "0x2b811a131f800390b3175adbfc6ea5b8d788000d7e7b0cad33072d1879c4d990"], 6 | "B": 7 | [["0x19111522103e78d109c4f522aca98ba7151000dc02423587d760bb12350a20a0", "0x28f121ca2942c5ae05ba16b6d0cd52008926f0798b1c6af99e4191226fe15ab7"], ["0x24a588ab1c938350e5a7d3deb5c3108abd9e0d6edaff32a5b6e9fa2dee89c3b6", "0x297fd7d08a100e1d3747b557a248f11c1aaa8c76345526fc9819f90e51514854"]], 8 | 9 | "B_p":["0x16e11eb74fe4e86802c460d03f29408d9d4a60f63f898c1dafc4fb3377a23add", "0xf79505321f467d631ae5e56c61834f7097d89452239750ebd84ccc177de1df9"], 10 | "C":["0x131434e436971fc3496961833c76fe9dbfc912a43d2f980515bcaa07b997f9a8", "0x2775da3a4722d910aaae35a2a5cf965e3d5d69d6dd9d912f0538c03acd4a8865"], 11 | "C_p":["0x7f82a3cce608adbd8eb8ce75034364c2d7ffd43725b5310344d3c13f0d2c743", "0xfe8fb8d33c22002c7215f3ce4649f76a5312ef906db73aed3a774668d44a50e"], 12 | "H":["0x2f0b0994392c07d8f177a4aeb788b76ad7334c22284e0c3351f429b08ca21652", "0x194f2dcce5526e7885413ecaf3ca75bf22f57b38f48865289bbe45ee28823154"], 13 | "K":["0x13a6febb622ee068ec196024ed73cb939281a4ec14ebcb50d7e5eec0b4e71ad3", "0x2d0d92c7de659cf24e16c4216845583f0a1080d460c14b448a30b41000f715c7"] 14 | }, 15 | "input":[232310020822901034104762510965330293111,290107346578087637545360782727286918188,210219292964116369102883671286459321076,227322991366389551999749449849806758625,42022122505097917127364068979301637648,120910671520054972343429929459551033400,1]} -------------------------------------------------------------------------------- /ethereum/scripts/transferNote.js: -------------------------------------------------------------------------------- 1 | // const contractArtifact = artifacts.require('./SecretNote.sol'); 2 | // import secretNoteContract from './listener.js'; 3 | const abi = [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "a", 9 | "type": "uint256[2]" 10 | }, 11 | { 12 | "name": "a_p", 13 | "type": "uint256[2]" 14 | }, 15 | { 16 | "name": "b", 17 | "type": "uint256[2][2]" 18 | }, 19 | { 20 | "name": "b_p", 21 | "type": "uint256[2]" 22 | }, 23 | { 24 | "name": "c", 25 | "type": "uint256[2]" 26 | }, 27 | { 28 | "name": "c_p", 29 | "type": "uint256[2]" 30 | }, 31 | { 32 | "name": "h", 33 | "type": "uint256[2]" 34 | }, 35 | { 36 | "name": "k", 37 | "type": "uint256[2]" 38 | }, 39 | { 40 | "name": "input", 41 | "type": "uint256[7]" 42 | } 43 | ], 44 | "name": "verifyTx", 45 | "outputs": [ 46 | { 47 | "name": "r", 48 | "type": "bool" 49 | } 50 | ], 51 | "payable": false, 52 | "stateMutability": "nonpayable", 53 | "type": "function", 54 | "signature": "0x1cdf1357" 55 | }, 56 | { 57 | "constant": true, 58 | "inputs": [ 59 | { 60 | "name": "", 61 | "type": "uint256" 62 | } 63 | ], 64 | "name": "allHashedNotes", 65 | "outputs": [ 66 | { 67 | "name": "", 68 | "type": "bytes32" 69 | } 70 | ], 71 | "payable": false, 72 | "stateMutability": "view", 73 | "type": "function", 74 | "signature": "0x58a5d596" 75 | }, 76 | { 77 | "constant": true, 78 | "inputs": [ 79 | { 80 | "name": "", 81 | "type": "bytes32" 82 | } 83 | ], 84 | "name": "notes", 85 | "outputs": [ 86 | { 87 | "name": "", 88 | "type": "uint8" 89 | } 90 | ], 91 | "payable": false, 92 | "stateMutability": "view", 93 | "type": "function", 94 | "signature": "0x85de26b7" 95 | }, 96 | { 97 | "constant": true, 98 | "inputs": [ 99 | { 100 | "name": "", 101 | "type": "uint256" 102 | } 103 | ], 104 | "name": "allNotes", 105 | "outputs": [ 106 | { 107 | "name": "", 108 | "type": "string" 109 | } 110 | ], 111 | "payable": false, 112 | "stateMutability": "view", 113 | "type": "function", 114 | "signature": "0xddabcf41" 115 | }, 116 | { 117 | "inputs": [], 118 | "payable": false, 119 | "stateMutability": "nonpayable", 120 | "type": "constructor", 121 | "signature": "constructor" 122 | }, 123 | { 124 | "anonymous": false, 125 | "inputs": [ 126 | { 127 | "indexed": false, 128 | "name": "m", 129 | "type": "bytes32" 130 | }, 131 | { 132 | "indexed": false, 133 | "name": "m2", 134 | "type": "bytes32" 135 | } 136 | ], 137 | "name": "debug", 138 | "type": "event", 139 | "signature": "0x02451fae0adb7ceff4e670c0e623b1c9e0b2898e612e291ad76e596de0a2d053" 140 | }, 141 | { 142 | "anonymous": false, 143 | "inputs": [ 144 | { 145 | "indexed": false, 146 | "name": "to", 147 | "type": "address" 148 | }, 149 | { 150 | "indexed": false, 151 | "name": "amount", 152 | "type": "uint256" 153 | } 154 | ], 155 | "name": "Claim", 156 | "type": "event", 157 | "signature": "0x47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4" 158 | }, 159 | { 160 | "anonymous": false, 161 | "inputs": [ 162 | { 163 | "indexed": false, 164 | "name": "noteId", 165 | "type": "bytes32" 166 | }, 167 | { 168 | "indexed": false, 169 | "name": "index", 170 | "type": "uint256" 171 | } 172 | ], 173 | "name": "NoteCreated", 174 | "type": "event", 175 | "signature": "0xc904a92388c152c0c63dfe30e3e880273673ef7d33ea18195aecb5ba50f546fc" 176 | }, 177 | { 178 | "anonymous": false, 179 | "inputs": [ 180 | { 181 | "indexed": false, 182 | "name": "a", 183 | "type": "bytes16" 184 | }, 185 | { 186 | "indexed": false, 187 | "name": "b", 188 | "type": "bytes16" 189 | } 190 | ], 191 | "name": "d2", 192 | "type": "event", 193 | "signature": "0xd278e8c3a630dc4a7eb08180a3880316949e0f4b449df0b97df01512353786ce" 194 | }, 195 | { 196 | "anonymous": false, 197 | "inputs": [ 198 | { 199 | "indexed": false, 200 | "name": "s", 201 | "type": "string" 202 | } 203 | ], 204 | "name": "Verified", 205 | "type": "event", 206 | "signature": "0x3f3cfdb26fb5f9f1786ab4f1a1f9cd4c0b5e726cbdfc26e495261731aad44e39" 207 | }, 208 | { 209 | "constant": true, 210 | "inputs": [], 211 | "name": "getNotesLength", 212 | "outputs": [ 213 | { 214 | "name": "", 215 | "type": "uint256" 216 | } 217 | ], 218 | "payable": false, 219 | "stateMutability": "view", 220 | "type": "function", 221 | "signature": "0xeb3d72d1" 222 | }, 223 | { 224 | "constant": false, 225 | "inputs": [ 226 | { 227 | "name": "owner", 228 | "type": "address" 229 | }, 230 | { 231 | "name": "amount", 232 | "type": "uint256" 233 | }, 234 | { 235 | "name": "encryptedNote", 236 | "type": "string" 237 | } 238 | ], 239 | "name": "createNoteDummy", 240 | "outputs": [], 241 | "payable": false, 242 | "stateMutability": "nonpayable", 243 | "type": "function", 244 | "signature": "0xd9758ae0" 245 | }, 246 | { 247 | "constant": false, 248 | "inputs": [ 249 | { 250 | "name": "amount", 251 | "type": "uint256" 252 | } 253 | ], 254 | "name": "claimNote", 255 | "outputs": [], 256 | "payable": false, 257 | "stateMutability": "nonpayable", 258 | "type": "function", 259 | "signature": "0xa4654ead" 260 | }, 261 | { 262 | "constant": false, 263 | "inputs": [ 264 | { 265 | "name": "a", 266 | "type": "uint256[2]" 267 | }, 268 | { 269 | "name": "a_p", 270 | "type": "uint256[2]" 271 | }, 272 | { 273 | "name": "b", 274 | "type": "uint256[2][2]" 275 | }, 276 | { 277 | "name": "b_p", 278 | "type": "uint256[2]" 279 | }, 280 | { 281 | "name": "c", 282 | "type": "uint256[2]" 283 | }, 284 | { 285 | "name": "c_p", 286 | "type": "uint256[2]" 287 | }, 288 | { 289 | "name": "h", 290 | "type": "uint256[2]" 291 | }, 292 | { 293 | "name": "k", 294 | "type": "uint256[2]" 295 | }, 296 | { 297 | "name": "input", 298 | "type": "uint256[7]" 299 | }, 300 | { 301 | "name": "encryptedNote1", 302 | "type": "string" 303 | }, 304 | { 305 | "name": "encryptedNote2", 306 | "type": "string" 307 | } 308 | ], 309 | "name": "transferNote", 310 | "outputs": [], 311 | "payable": false, 312 | "stateMutability": "nonpayable", 313 | "type": "function", 314 | "signature": "0x573d7339" 315 | } 316 | ] 317 | 318 | const secretNoteAddress = '0x187dc8FF9092471A71e344C18F52Cad17e43d719' 319 | 320 | const BN = require('bn.js') 321 | const fs = require('fs'); 322 | const path = require('path'); 323 | 324 | async function execute() { 325 | // console.log(path.join(__dirname, 'proof.json')) 326 | let proofJson = fs.readFileSync(path.join(__dirname, 'proof.json'), 'utf8'); 327 | var rx2 = /([0-9]+)[,]/gm 328 | // console.log(proofJson.match(rx2)) 329 | proofJson.match(rx2).forEach(p => { 330 | proofJson = proofJson.replace(p, `"${p.slice(0, p.length-1)}",`) 331 | }) 332 | proofJson = JSON.parse(proofJson); 333 | // console.log(proofJson) 334 | 335 | const proof = proofJson.proof; 336 | const input = proofJson.input; 337 | input.forEach((i, key) => { 338 | if (typeof i == 'number') i = i.toString(); 339 | input[key] = '0x' + new BN(i, 10).toString('hex') 340 | }) 341 | 342 | const _proof = []; 343 | Object.keys(proof).forEach(key => _proof.push(proof[key])); 344 | _proof.push(input) 345 | 346 | const encNote1 = await encrypt('9e8f633D0C46ED7170EF3B30E291c64a91a49C7E', '9'); 347 | const encNote2 = await encrypt('3644B986B3F5Ba3cb8D5627A22465942f8E06d09', '2'); 348 | // console.log(..._proof, encNote1, encNote2) 349 | console.log('calling transferNote with params', ..._proof, encNote1, encNote2); 350 | let secretNoteContract = new web3.eth.Contract(abi, secretNoteAddress); 351 | 352 | try { 353 | await secretNoteContract.methods.transferNote(..._proof, encNote1, encNote2) 354 | .send({ 355 | from: '0x2B522cABE9950D1153c26C1b399B293CaA99FcF9', 356 | gasPrice: '0x' + parseInt('10000000000').toString(16) 357 | }) 358 | // const tx = await instance.transferNote(..._proof, encNote1, encNote2); 359 | // console.dir(tx, {depth: null}); 360 | } catch(e) { 361 | console.log(e) 362 | } 363 | } 364 | 365 | async function encrypt(address, _amount) { 366 | // 20 12 367 | let amount = new BN(_amount, 16).toString(16, 24); // 12 bytes = 24 chars in hex 368 | const payload = address + amount; 369 | return payload; 370 | // console.log('enc payload', payload) 371 | // const encryptedNote = await web3.eth.accounts.encrypt('0x' + payload, 'vitalik') 372 | // return JSON.stringify(encryptedNote); 373 | } 374 | 375 | module.exports = async function(callback) { 376 | // perform actions 377 | await execute(); 378 | callback(); 379 | } -------------------------------------------------------------------------------- /ethereum/scripts/zokcmd.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto'); 2 | const BN = require('bn.js'); 3 | 4 | function getSecretZokratesParams(concat) { 5 | return [concat.slice(0, 32), concat.slice(32, 64), concat.slice(64, 96), concat.slice(96)]//.map(e => e.toString(10)) 6 | } 7 | 8 | function getPublicZokratesParams(hexPayload) { 9 | // console.log('getPublicZokratesParams - hexPayload', hexPayload) 10 | const buf = Buffer.from(hexPayload, 'hex'); 11 | const digest = crypto.createHash('sha256').update(buf).digest('hex'); 12 | // console.log('digest', digest) 13 | // split into 128 bits each 14 | return [digest.slice(0, 32), digest.slice(32)] 15 | } 16 | 17 | function getHexPayload(from, amount) { 18 | let paddedAddress = new BN(from, 16).toString(16, 64); 19 | let paddedAmount = new BN(amount, 16).toString(16, 64); 20 | return paddedAddress + paddedAmount; 21 | } 22 | 23 | function getNoteParams(from, amount) { 24 | let hexPayload = getHexPayload(from, amount); 25 | // console.log('hexPayload', hexPayload) 26 | let zkParams = getPublicZokratesParams(hexPayload).concat(getSecretZokratesParams(hexPayload)); 27 | return zkParams; 28 | } 29 | 30 | function printZokratesCommand(params) { 31 | let cmd = './zokrates compute-witness -a ' 32 | params.forEach(p => { 33 | cmd += `${new BN(p, 16).toString(10)} ` 34 | }) 35 | console.log(cmd); 36 | } 37 | 38 | function getTransferZkParams(from, fromAmount, to, toAmount) { 39 | from = from.slice(2); 40 | fromAmount = fromAmount.slice(2); 41 | to = to.slice(2); 42 | toAmount = toAmount.slice(2); 43 | 44 | let change = parseInt(fromAmount, 16) - parseInt(toAmount, 16); 45 | const params = getNoteParams(from, fromAmount).concat(getNoteParams(to, toAmount)); 46 | let leftOver = getNoteParams(from, change); 47 | // for the leftover change note, first 2 params (spender public key) are the same. delete elements at 2, 3 index 48 | leftOver.splice(2, 2); 49 | printZokratesCommand(params.concat(leftOver)); 50 | } 51 | 52 | getTransferZkParams( 53 | '0x3644B986B3F5Ba3cb8D5627A22465942f8E06d09', // sender 54 | '0xb', // value of the secret note 55 | '0x9e8f633D0C46ED7170EF3B30E291c64a91a49C7E', // receiver 56 | '0x9' // value to be sent 57 | ); 58 | -------------------------------------------------------------------------------- /ethereum/test/SecretNoteTest.js: -------------------------------------------------------------------------------- 1 | const SecretNote = artifacts.require("SecretNote"); 2 | const BN = require('bn.js'); 3 | const crypto = require('crypto'); 4 | 5 | contract('SecretNote', function(accounts) { 6 | it.only('createNoteDummy', async function() { 7 | // const e = await encrypt('2B522cABE9950D1153c26C1b399B293CaA99FcF9', '5'); 8 | // const d = await decrypt(e); 9 | let instance = await SecretNote.deployed(); 10 | let enc = await encrypt(accounts[0].slice(2), '5') 11 | const tx = await instance.createNoteDummy('0x5', enc); 12 | console.dir(tx, {depth: null}); 13 | 14 | const noteId = tx.logs[0].args.noteId; 15 | const index = tx.logs[0].args.index; 16 | // console.log('noteId', noteId) 17 | 18 | // decrypt 19 | const cipher = await instance.allNotes.call(index) 20 | const noteHash = await decrypt(cipher); 21 | console.log('noteHash', noteHash) 22 | // check noteHash in mapping now 23 | const state = await instance.notes.call('0x' + noteHash) 24 | console.log('state', state.toNumber()) // state 1 25 | }) 26 | }) 27 | 28 | async function encrypt(address, _amount) { 29 | // 20 12 30 | let amount = new BN(_amount, 16).toString(16, 24); // 12 bytes = 24 chars in hex 31 | const payload = address + amount; 32 | console.log('enc payload', payload) 33 | const encryptedNote = await web3.eth.accounts.encrypt('0x' + payload, 'vitalik') 34 | return JSON.stringify(encryptedNote); 35 | } 36 | 37 | async function decrypt(cipher) { 38 | let payload = await web3.eth.accounts.decrypt(JSON.parse(cipher), 'vitalik').privateKey 39 | payload = payload.slice(2) 40 | const address = payload.slice(0, 40) // remove 0x and 41 | const amount = payload.slice(40) 42 | console.log(address, amount); 43 | 44 | // pad address and amount to 32bytes 45 | let _address = new BN(address, 16).toString(16, 64); 46 | let _amount = new BN(amount, 16).toString(16, 64); // 32 bytes = 64 chars in hex 47 | const buf = Buffer.from(_address + _amount, 'hex'); 48 | const digest = crypto.createHash('sha256').update(buf).digest('hex'); 49 | return digest; 50 | } -------------------------------------------------------------------------------- /ethereum/test/verifierTest.js: -------------------------------------------------------------------------------- 1 | const verifier = artifacts.require("verifier"); 2 | const fs = require('fs'); 3 | const BN = require('bn.js'); 4 | 5 | contract('verifier', function(accounts) { 6 | it('verifyTx', async function() { 7 | let proofJson = fs.readFileSync('./zksnark/proof.json', 'utf8'); 8 | var rx2 = /([0-9]+)[,]/gm 9 | // console.log(proofJson.match(rx2)) 10 | proofJson.match(rx2).forEach(p => { 11 | proofJson = proofJson.replace(p, `"${p.slice(0, p.length-1)}",`) 12 | }) 13 | proofJson = JSON.parse(proofJson); 14 | // console.log(proofJson) 15 | 16 | const proof = proofJson.proof; 17 | const input = proofJson.input; 18 | input.forEach((i, key) => { 19 | if (typeof i == 'number') i = i.toString(); 20 | input[key] = '0x' + new BN(i, 10).toString('hex') 21 | }) 22 | 23 | const _proof = []; 24 | Object.keys(proof).forEach(key => _proof.push(proof[key])); 25 | _proof.push(input) 26 | 27 | let instance = await verifier.deployed(); 28 | console.log('calling verifyTx with proof', _proof); 29 | const success = await instance.verifyTx.call(..._proof); 30 | assert(success); 31 | }) 32 | }) -------------------------------------------------------------------------------- /ethereum/truffle.js: -------------------------------------------------------------------------------- 1 | var HDWalletProvider = require("truffle-hdwallet-provider"); 2 | const MNEMONIC = 'gesture rather obey video awake genuine patient base soon parrot upset lounge'; 3 | 4 | /* 5 | * NB: since truffle-hdwallet-provider 0.0.5 you must wrap HDWallet providers in a 6 | * function when declaring them. Failure to do so will cause commands to hang. ex: 7 | * ``` 8 | * mainnet: { 9 | * provider: function() { 10 | * return new HDWalletProvider(mnemonic, 'https://mainnet.infura.io/') 11 | * }, 12 | * network_id: '1', 13 | * gas: 4500000, 14 | * gasPrice: 10000000000, 15 | * }, 16 | */ 17 | 18 | // module.exports = { 19 | // // See 20 | // // to customize your Truffle configuration! 21 | // networks: { 22 | // development: { 23 | // host: "127.0.0.1", 24 | // port: 9545, 25 | // network_id: "*" // Match any network id 26 | // }, 27 | // ropsten: { 28 | // provider: function () { 29 | // return new HDWalletProvider(MNEMONIC, "https://ropsten.infura.io/v3/f2aa27e5bf2b4bf1b3b002e8687b61da") 30 | // }, 31 | // network_id: 3, 32 | // gas: 3000000 //make sure this gas allocation isn't over 4M, which is the max 33 | // } 34 | // }, 35 | // }; 36 | 37 | module.exports = { 38 | networks: { 39 | development: { 40 | // provider: function () { 41 | // return new HDWalletProvider(MNEMONIC, "http://localhost:8545", 0, /* address_index */) 42 | // }, 43 | host: "127.0.0.1", 44 | port: 8545, 45 | network_id: "*" // Match any network id 46 | }, 47 | ropsten: { 48 | provider: function () { 49 | return new HDWalletProvider(MNEMONIC, "https://ropsten.infura.io/v3/f2aa27e5bf2b4bf1b3b002e8687b61da", 0, 5) 50 | }, 51 | network_id: 3, 52 | gas: 3000000 //make sure this gas allocation isn't over 4M, which is the max 53 | } 54 | } 55 | }; -------------------------------------------------------------------------------- /ethereum/zk-circuit.code: -------------------------------------------------------------------------------- 1 | import "LIBSNARK/sha256packed" 2 | 3 | // https://zokrates.github.io/sha256example.html#computing-a-hash-using-zokrates 4 | // A field value can only hold 254 bits due to the size of the underlying prime field used by zokrates. Therefore, 256 bit values need to be passed as 2 params of 128 bit values. 5 | 6 | // https://zokrates.github.io/concepts/stdlib.html?highlight=sha256#sha256packed 7 | // At the time of writing sha256packed takes 4 field elements as inputs, unpacks each of them to 128 bits (big endian), concatenates them and applies sha256. It then returns two field elements, each representing 128 bits of the result. 8 | 9 | // Public inputs 10 | // onh0 + onh1: Hash of the note (secret note) 11 | // nn1h0 + nn1h1: Hash of the new note 1 12 | // nn2h0 + nn1h1: Hash of the new note 2 13 | 14 | // Private inputs 15 | // ona + onb: secret key of the sender 16 | // onc + ond: (256 bits) representing the value of the note to be spent 17 | 18 | // nn1a + nn1b: public key of the receiver 19 | // nn1c + nn1d: the value of the note to be sent 20 | 21 | // nn2c + nn2d: leftover change 22 | def main(field onh0, field onh1, private field ona, private field onb, private field onc, private field ond, field nn1h0, field nn1h1, private field nn1a, private field nn1b, private field nn1c, private field nn1d, field nn2h0, field nn2h1, private field nn2c, private field nn2d) -> (field): 23 | // get public key corresponding to private key 24 | // too complex to implement for the hackathon :p - so sending in the public key instead 25 | field pka = ona 26 | field pkb = onb 27 | 28 | // old note 29 | h0, h1 = sha256packed(pka, pkb, onc, ond) 30 | h0 == onh0 // verify with public input (hash of the note) 31 | h1 == onh1 32 | 33 | // new note 1 that goes to pkreciever 34 | h0, h1 = sha256packed(nn1a, nn1b, nn1c, nn1d) 35 | h0 == nn1h0 36 | h1 == nn1h1 37 | 38 | // new note (left over change) that goes back to sender (pk) 39 | h0, h1 = sha256packed(pka, pkb, nn2c, nn2d) 40 | h0 == nn2h0 41 | h1 == nn2h1 42 | 43 | ond == nn1d + nn2d // assuming the values fit in 128 bit nums - hence onc, nn1c, nn2c are 0 44 | return 1 -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zeth", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "bn.js": "^4.11.8", 7 | "ethereumjs-tx": "^1.3.7", 8 | "ethereumjs-util": "^6.0.0", 9 | "express": "^4.16.4", 10 | "mdbreact": "^4.8.4", 11 | "react": "^16.6.3", 12 | "react-dom": "^16.6.3", 13 | "react-router": "^4.3.1", 14 | "react-router-dom": "^4.3.1", 15 | "react-scripts": "2.1.1", 16 | "truffle-hdwallet-provider": "0.0.6", 17 | "web3": "^1.0.0-beta.36" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": "react-app" 27 | }, 28 | "browserslist": [ 29 | ">0.2%", 30 | "not dead", 31 | "not ie <= 11", 32 | "not op_mini all" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arminvoid/ethsingapore-zk-dai/4955d5f8fad5a0c973353458455b0994a0461786/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 14 | 15 | 24 | ZkDAI 25 | 26 | 27 | 28 | 31 |
32 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | } 9 | 10 | .App-header { 11 | background-color: #282c34; 12 | min-height: 100vh; 13 | display: flex; 14 | flex-direction: column; 15 | align-items: center; 16 | justify-content: center; 17 | font-size: calc(10px + 2vmin); 18 | color: white; 19 | } 20 | 21 | .App-link { 22 | color: #61dafb; 23 | } 24 | 25 | @keyframes App-logo-spin { 26 | from { 27 | transform: rotate(0deg); 28 | } 29 | to { 30 | transform: rotate(360deg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { MDBContainer, MDBRow, MDBCol } from 'mdbreact' 3 | import './App.css'; 4 | import 'font-awesome/css/font-awesome.min.css'; 5 | import 'bootstrap-css-only/css/bootstrap.min.css'; 6 | import 'mdbreact/dist/css/mdb.css'; 7 | import { BrowserRouter, Route, Switch } from 'react-router-dom'; 8 | 9 | import Landing from './components/landing' 10 | import Home from './components/home' 11 | 12 | 13 | class App extends Component { 14 | render() { 15 | return ( 16 | 17 | 18 | 19 | {/* 20 | */} 21 | 22 | 23 | 24 | ); 25 | } 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | ReactDOM.unmountComponentAtNode(div); 9 | }); 10 | -------------------------------------------------------------------------------- /src/components/home.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Swapper from './swapper' 3 | import ZeroCash from './zeroCash' 4 | import { MDBContainer, Animation } from 'mdbreact' 5 | 6 | 7 | class Home extends Component { 8 | render() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ) 17 | } 18 | } 19 | 20 | export default Home; -------------------------------------------------------------------------------- /src/components/landing.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Button, Animation } from 'mdbreact'; 3 | import web3 from '../production/web3'; 4 | const ethUtil = require('ethereumjs-util'); 5 | 6 | class Landing extends Component { 7 | state = { 8 | metaMaskLoginError: false 9 | }; 10 | 11 | 12 | login = async () => { 13 | const address = await web3.eth.getCoinbase(); 14 | const netId = await web3.eth.net.getId(); 15 | if (ethUtil.isValidAddress(address) && netId == 3) { 16 | this.setState({ metaMaskLoginError: false }); 17 | this.props.history.push('/home'); 18 | } else { 19 | this.setState({ metaMaskLoginError: true }); 20 | } 21 | }; 22 | 23 | render() { 24 | let metaMaskErrorAlert = null; 25 | 26 | if (this.state.metaMaskLoginError) { 27 | metaMaskErrorAlert = ( 28 |
32 | Error: 33 | Metamask (n/w: Ropsten) is required to use ZEtH! 34 |
Please sign into Metamask or switch the network the network to Ropsten 35 | order to proceed. 36 |
37 | ); 38 | } 39 | 40 | return ( 41 |
42 | 43 |

44 | ZkDAI 45 |

46 |
47 | 48 | 49 | 57 | 58 | {metaMaskErrorAlert} 59 |
60 | ); 61 | } 62 | } 63 | 64 | export default Landing; -------------------------------------------------------------------------------- /src/components/stateless/cashTable.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Table, TableBody, TableHead } from 'mdbreact'; 3 | 4 | const CashTable = (props) => { 5 | let tableRows; 6 | if(props.content){ 7 | tableRows = props.content.map((data, index) => { 8 | return ( 9 | {index} 10 | {data.hash} 11 | ); 12 | }); 13 | } 14 | return ( 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | {tableRows} 25 | 26 |
#Cash Hash
27 | ); 28 | } 29 | 30 | export default CashTable; -------------------------------------------------------------------------------- /src/components/stateless/ownerCashTable.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Table, TableBody, TableHead } from 'mdbreact'; 3 | import { claimDAI } from '../../production/secretNote'; 4 | 5 | const OwnerCashTable = (props) => { 6 | 7 | 8 | const claim = async (amount) => { 9 | console.log('Claiming', amount) 10 | claimDAI(parseInt(amount)); 11 | } 12 | 13 | const getTableRows = () => { 14 | const tableRows = props.content.map((data, index) => { 15 | let claimer; 16 | if (data.status == 'Created') { 17 | claimer = 24 | } else { 25 | claimer = 31 | } 32 | return ( 33 | {index} 34 | {data.hash} 35 | {data.status} 36 | {data.amount} 37 | {claimer} 38 | ); 39 | }); 40 | return tableRows; 41 | 42 | } 43 | return ( 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {getTableRows()} 57 | 58 |
#Cash HashStatusAmountLiquidate
59 | ); 60 | 61 | } 62 | 63 | export default OwnerCashTable; -------------------------------------------------------------------------------- /src/components/swapper.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import { MDBContainer, Animation } from 'mdbreact' 3 | 4 | class Swapper extends Component { 5 | render() { 6 | 7 | const kyberWidget = (Pay with tokens); 10 | 11 | return ( 12 | 13 | 14 | 15 | {kyberWidget} 16 | 17 | 18 | ); 19 | } 20 | } 21 | 22 | export default Swapper -------------------------------------------------------------------------------- /src/components/zeroCash.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react' 2 | import CashTable from './stateless/cashTable' 3 | import OwnerCashTable from './stateless/ownerCashTable' 4 | import { getNotes, getCurrentAccount, getAllNotes } from '../production/secretNote' 5 | 6 | class ZeroCash extends Component { 7 | state = { 8 | notes: [], 9 | allNotes: [], 10 | } 11 | 12 | getNotes = async () => { 13 | const notes = await getNotes(); 14 | this.setState({ notes }) 15 | } 16 | 17 | getAllNotes = async () => { 18 | const allNotes = await getAllNotes(); 19 | this.setState({ allNotes }) 20 | } 21 | 22 | getAccount = async () => { 23 | const account = await getCurrentAccount(); 24 | this.setState({ account }) 25 | } 26 | 27 | componentDidMount() { 28 | this.getNotes(); 29 | this.getAccount(); 30 | this.getAllNotes(); 31 | } 32 | 33 | render() { 34 | return ( 35 |
36 |

ZkDAI

37 |

Your Cash ({this.state.account})

38 | {/* */} 39 | 40 |
41 |

Cash Pool

42 | 43 |
44 | ); 45 | } 46 | } 47 | 48 | export default ZeroCash -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 5 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 6 | sans-serif; 7 | -webkit-font-smoothing: antialiased; 8 | -moz-osx-font-smoothing: grayscale; 9 | } 10 | 11 | code { 12 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 13 | monospace; 14 | } 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: http://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/production/ganacheWeb3.js: -------------------------------------------------------------------------------- 1 | const Web3 = require('web3'); 2 | const provider = new Web3.providers.HttpProvider( 3 | 'http://localhost:8545' 4 | ); 5 | const web3 = new Web3(provider); 6 | 7 | export default web3; -------------------------------------------------------------------------------- /src/production/kyber/abi/KNC.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/abi/KyberNetworkProxy.abi: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"alerter","type":"address"}],"name":"removeAlerter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x01a12fd3"},{"constant":true,"inputs":[],"name":"pendingAdmin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x26782247"},{"constant":true,"inputs":[],"name":"getOperators","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x27a099d8"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"amount","type":"uint256"},{"name":"sendTo","type":"address"}],"name":"withdrawToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x3ccdbb28"},{"constant":false,"inputs":[{"name":"newAlerter","type":"address"}],"name":"addAlerter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x408ee7fe"},{"constant":true,"inputs":[],"name":"kyberNetworkContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x4f61ff8b"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"transferAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x75829def"},{"constant":false,"inputs":[],"name":"claimAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x77f50f97"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"transferAdminQuickly","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x7acc8678"},{"constant":true,"inputs":[],"name":"getAlerters","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x7c423f54"},{"constant":false,"inputs":[{"name":"newOperator","type":"address"}],"name":"addOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x9870d7fe"},{"constant":false,"inputs":[{"name":"operator","type":"address"}],"name":"removeOperator","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xac8a584a"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"},{"name":"sendTo","type":"address"}],"name":"withdrawEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xce56c454"},{"constant":true,"inputs":[{"name":"token","type":"address"},{"name":"user","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xd4fac45d"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xf851a440"},{"inputs":[{"name":"_admin","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"trader","type":"address"},{"indexed":false,"name":"src","type":"address"},{"indexed":false,"name":"dest","type":"address"},{"indexed":false,"name":"actualSrcAmount","type":"uint256"},{"indexed":false,"name":"actualDestAmount","type":"uint256"}],"name":"ExecuteTrade","type":"event","signature":"0x1849bd6a030a1bca28b83437fd3de96f3d27a5d172fa7e9c78e7b61468928a39"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newNetworkContract","type":"address"},{"indexed":false,"name":"oldNetworkContract","type":"address"}],"name":"KyberNetworkSet","type":"event","signature":"0x8936e1f096bf0a8c9df862b3d1d5b82774cad78116200175f00b5b7ba3010b02"},{"anonymous":false,"inputs":[{"indexed":false,"name":"token","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"sendTo","type":"address"}],"name":"TokenWithdraw","type":"event","signature":"0x72cb8a894ddb372ceec3d2a7648d86f17d5a15caae0e986c53109b8a9a9385e6"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"sendTo","type":"address"}],"name":"EtherWithdraw","type":"event","signature":"0xec47e7ed86c86774d1a72c19f35c639911393fe7c1a34031fdbd260890da90de"},{"anonymous":false,"inputs":[{"indexed":false,"name":"pendingAdmin","type":"address"}],"name":"TransferAdminPending","type":"event","signature":"0x3b81caf78fa51ecbc8acb482fd7012a277b428d9b80f9d156e8a54107496cc40"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAdmin","type":"address"},{"indexed":false,"name":"previousAdmin","type":"address"}],"name":"AdminClaimed","type":"event","signature":"0x65da1cfc2c2e81576ad96afb24a581f8e109b7a403b35cbd3243a1c99efdb9ed"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newAlerter","type":"address"},{"indexed":false,"name":"isAdd","type":"bool"}],"name":"AlerterAdded","type":"event","signature":"0x5611bf3e417d124f97bf2c788843ea8bb502b66079fbee02158ef30b172cb762"},{"anonymous":false,"inputs":[{"indexed":false,"name":"newOperator","type":"address"},{"indexed":false,"name":"isAdd","type":"bool"}],"name":"OperatorAdded","type":"event","signature":"0x091a7a4b85135fdd7e8dbc18b12fabe5cc191ea867aa3c2e1a24a102af61d58b"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"srcAmount","type":"uint256"},{"name":"dest","type":"address"},{"name":"destAddress","type":"address"},{"name":"maxDestAmount","type":"uint256"},{"name":"minConversionRate","type":"uint256"},{"name":"walletId","type":"address"}],"name":"trade","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function","signature":"0xcb3c28c7"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"srcAmount","type":"uint256"},{"name":"dest","type":"address"},{"name":"minConversionRate","type":"uint256"}],"name":"swapTokenToToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x7409e2eb"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"minConversionRate","type":"uint256"}],"name":"swapEtherToToken","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function","signature":"0x7a2a0456"},{"constant":false,"inputs":[{"name":"token","type":"address"},{"name":"srcAmount","type":"uint256"},{"name":"minConversionRate","type":"uint256"}],"name":"swapTokenToEther","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x3bba21dc"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"srcAmount","type":"uint256"},{"name":"dest","type":"address"},{"name":"destAddress","type":"address"},{"name":"maxDestAmount","type":"uint256"},{"name":"minConversionRate","type":"uint256"},{"name":"walletId","type":"address"},{"name":"hint","type":"bytes"}],"name":"tradeWithHint","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function","signature":"0x29589f61"},{"constant":false,"inputs":[{"name":"_kyberNetworkContract","type":"address"}],"name":"setKyberNetworkContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xabd188a8"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"dest","type":"address"},{"name":"srcQty","type":"uint256"}],"name":"getExpectedRate","outputs":[{"name":"expectedRate","type":"uint256"},{"name":"slippageRate","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x809a9e55"},{"constant":true,"inputs":[{"name":"user","type":"address"}],"name":"getUserCapInWei","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x6432679f"},{"constant":true,"inputs":[{"name":"user","type":"address"},{"name":"token","type":"address"}],"name":"getUserCapInTokenWei","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x8eaaeecf"},{"constant":true,"inputs":[],"name":"maxGasPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x3de39c11"},{"constant":true,"inputs":[],"name":"enabled","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x238dafe0"},{"constant":true,"inputs":[{"name":"field","type":"bytes32"}],"name":"info","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xb64a097e"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/abi/MANA.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x05d2035b"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x06fdde03"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x095ea7b3"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x18160ddd"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x23b872dd"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x313ce567"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x40c10f19"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x42966c68"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x66188463"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x70a08231"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x715018a6"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x79cc6790"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0x7d64bcb4"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x8da5cb5b"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function","signature":"0x95d89b41"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xa9059cbb"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xd73dd623"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function","signature":"0xdd62ed3e"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function","signature":"0xf2fde38b"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor","signature":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event","signature":"0x0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event","signature":"0xae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa08"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event","signature":"0xf8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c64820"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event","signature":"0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event","signature":"0xcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca5"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event","signature":"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event","signature":"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/abi/OMG.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/abi/SALT.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/abi/ZIL.abi: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[],"name":"mintingFinished","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_subtractedValue","type":"uint256"}],"name":"decreaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_value","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"finishMinting","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_addedValue","type":"uint256"}],"name":"increaseApproval","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[],"name":"MintFinished","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"burner","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}] 2 | -------------------------------------------------------------------------------- /src/production/kyber/getExpectedRate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const fs = require('fs'); 3 | const moment = require('moment'); 4 | const Web3 = require('web3'); 5 | 6 | process.on('unhandledRejection', console.error.bind(console)); 7 | 8 | const rpcUrl = 'http://localhost:8545'; // ganache-cli 9 | const web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl)); 10 | 11 | const KyberNetworkProxyABI = JSON.parse(fs.readFileSync('./abi/KyberNetworkProxy.abi', 'utf8')); 12 | const KyberNetworkProxyAddress = '0xF6084Ad447076da0246cD28e104533f9f51dbD2F'; 13 | const NetworkProxyInstance = new web3.eth.Contract(KyberNetworkProxyABI, KyberNetworkProxyAddress); 14 | 15 | const ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; 16 | const KNC_ADDRESS = '0x8c13AFB7815f10A8333955854E6ec7503eD841B7'; 17 | const OMG_ADDRESS = '0x3750bE154260872270EbA56eEf89E78E6E21C1D9'; 18 | const MANA_ADDRESS = '0xe19Ec968c15f487E96f631Ad9AA54fAE09A67C8c'; 19 | 20 | function stdlog(input) { 21 | console.log(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}] ${input}`); 22 | } 23 | 24 | async function main() { 25 | let expectedRate; 26 | let slippageRate; 27 | 28 | stdlog('- START -'); 29 | stdlog(`KyberNetworkProxy (${KyberNetworkProxyAddress})`); 30 | 31 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 32 | ETH_ADDRESS, // srcToken 33 | KNC_ADDRESS, // destToken 34 | web3.utils.toWei('1'), // srcQty 35 | ).call()); 36 | stdlog(`ETH <-> KNC getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 37 | 38 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 39 | KNC_ADDRESS, // srcToken 40 | ETH_ADDRESS, // destToken 41 | web3.utils.toWei('1'), // srcQty 42 | ).call()); 43 | stdlog(`KNC <-> ETH getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 44 | 45 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 46 | KNC_ADDRESS, // srcToken 47 | OMG_ADDRESS, // destToken 48 | web3.utils.toWei('1'), // srcQty 49 | ).call()); 50 | stdlog(`KNC <-> OMG getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 51 | 52 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 53 | ETH_ADDRESS, // srcToken 54 | MANA_ADDRESS, // destToken 55 | web3.utils.toWei('1'), // srcQty 56 | ).call()); 57 | stdlog(`ETH <-> MANA getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 58 | 59 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 60 | MANA_ADDRESS, // srcToken 61 | ETH_ADDRESS, // destToken 62 | web3.utils.toWei('1'), // srcQty 63 | ).call()); 64 | stdlog(`MANA <-> ETH getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 65 | 66 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 67 | KNC_ADDRESS, // srcToken 68 | MANA_ADDRESS, // destToken 69 | web3.utils.toWei('1'), // srcQty 70 | ).call()); 71 | stdlog(`KNC <-> KNC getExpectedRate() = expectedRate: ${expectedRate}, slippageRate:${slippageRate}`); 72 | 73 | stdlog('- END -'); 74 | } 75 | 76 | // Start the script 77 | main(); 78 | -------------------------------------------------------------------------------- /src/production/kyber/swapEtherToToken.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable no-underscore-dangle, no-unused-vars */ 3 | 4 | const BN = require('bn.js'); 5 | const fs = require('fs'); 6 | const HDWalletProvider = require('truffle-hdwallet-provider'); 7 | const moment = require('moment'); 8 | const Web3 = require('web3'); 9 | 10 | process.on('unhandledRejection', console.error.bind(console)); 11 | 12 | const mnemonic = 'gesture rather obey video awake genuine patient base soon parrot upset lounge'; 13 | const rpcUrl = 'http://localhost:8545'; // ganache-cli 14 | const provider = new HDWalletProvider(mnemonic, rpcUrl, 0, 10); 15 | const web3 = new Web3(provider); 16 | const { addresses, wallets } = provider; 17 | const gasPrice = web3.utils.toWei(new BN(10), 'gwei'); 18 | 19 | const KyberNetworkProxyABI = JSON.parse(fs.readFileSync('./abi/KyberNetworkProxy.abi', 'utf8')); 20 | const KyberNetworkProxyAddress = '0xF6084Ad447076da0246cD28e104533f9f51dbD2F'; 21 | const NetworkProxyInstance = new web3.eth.Contract(KyberNetworkProxyABI, KyberNetworkProxyAddress); 22 | 23 | const ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; 24 | const KNC_ADDRESS = '0x8c13AFB7815f10A8333955854E6ec7503eD841B7'; 25 | const MANA_ADDRESS = '0xe19Ec968c15f487E96f631Ad9AA54fAE09A67C8c'; 26 | const KNC_ABI = JSON.parse(fs.readFileSync('./abi/KNC.abi', 'utf8')); 27 | const MANA_ABI = JSON.parse(fs.readFileSync('./abi/MANA.abi', 'utf8')); 28 | const KNCInstance = new web3.eth.Contract(KNC_ABI, KNC_ADDRESS); 29 | const MANAInstance = new web3.eth.Contract(MANA_ABI, MANA_ADDRESS); 30 | 31 | const userWallet = addresses[4]; 32 | 33 | function stdlog(input) { 34 | console.log(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}] ${input}`); 35 | } 36 | 37 | function tx(result, call) { 38 | const logs = (result.logs.length > 0) ? result.logs[0] : { address: null, event: null }; 39 | 40 | console.log(); 41 | console.log(` ${call}`); 42 | console.log(' ------------------------'); 43 | console.log(` > transaction hash: ${result.transactionHash}`); 44 | console.log(` > gas used: ${result.gasUsed}`); 45 | console.log(); 46 | } 47 | 48 | async function sendTx(txObject) { 49 | const nonce = await web3.eth.getTransactionCount(userWallet); 50 | const gas = 500 * 1000; 51 | 52 | const txData = txObject.encodeABI(); 53 | const txFrom = userWallet; 54 | const txTo = txObject._parent.options.address; 55 | 56 | const txParams = { 57 | from: txFrom, 58 | to: txTo, 59 | data: txData, 60 | value: web3.utils.toWei(new BN(1)), 61 | gas, 62 | nonce, 63 | chainId: await web3.eth.net.getId(), 64 | gasPrice, 65 | }; 66 | 67 | const signedTx = await web3.eth.signTransaction(txParams); 68 | 69 | return web3.eth.sendSignedTransaction(signedTx.raw); 70 | } 71 | 72 | async function main() { 73 | let expectedRate; 74 | let slippageRate; 75 | let result; 76 | let txObject; 77 | 78 | NetworkProxyInstance.setProvider(provider); 79 | KNCInstance.setProvider(provider); 80 | MANAInstance.setProvider(provider); 81 | 82 | stdlog('- START -'); 83 | stdlog(`KyberNetworkProxy (${KyberNetworkProxyAddress})`); 84 | 85 | stdlog(`ETH balance of ${userWallet} = ${web3.utils.fromWei(await web3.eth.getBalance(userWallet))}`); 86 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 87 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 88 | 89 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 90 | ETH_ADDRESS, // srcToken 91 | KNC_ADDRESS, // destToken 92 | web3.utils.toWei('1'), // srcQty 93 | ).call()); 94 | 95 | txObject = NetworkProxyInstance.methods.swapEtherToToken( 96 | KNC_ADDRESS, // destToken 97 | expectedRate, // minConversionRate 98 | ); 99 | result = await sendTx(txObject); 100 | tx(result, 'ETH <-> KNC swapEtherToToken()'); 101 | 102 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 103 | ETH_ADDRESS, // srcToken 104 | MANA_ADDRESS, // destToken 105 | web3.utils.toWei('1'), // srcQty 106 | ).call()); 107 | 108 | txObject = NetworkProxyInstance.methods.swapEtherToToken( 109 | MANA_ADDRESS, // destToken 110 | expectedRate, // minConversionRate 111 | ); 112 | result = await sendTx(txObject); 113 | tx(result, 'ETH <-> MANA swapEtherToToken()'); 114 | 115 | stdlog(`ETH balance of ${userWallet} = ${web3.utils.fromWei(await web3.eth.getBalance(userWallet))}`); 116 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 117 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 118 | 119 | stdlog('- END -'); 120 | } 121 | 122 | // Start the script 123 | main(); 124 | -------------------------------------------------------------------------------- /src/production/kyber/swapTokenToEther.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable no-underscore-dangle, no-unused-vars */ 3 | const BN = require('bn.js'); 4 | const fs = require('fs'); 5 | const HDWalletProvider = require('truffle-hdwallet-provider'); 6 | const moment = require('moment'); 7 | const Web3 = require('web3'); 8 | 9 | process.on('unhandledRejection', console.error.bind(console)); 10 | 11 | const mnemonic = 'gesture rather obey video awake genuine patient base soon parrot upset lounge'; 12 | const rpcUrl = 'http://localhost:8545'; // ganache-cli 13 | const provider = new HDWalletProvider(mnemonic, rpcUrl, 0, 10); 14 | const web3 = new Web3(provider); 15 | const { addresses, wallets } = provider; 16 | const gasPrice = web3.utils.toWei(new BN(10), 'gwei'); 17 | 18 | const KyberNetworkAddress = '0xA46E01606f9252fa833131648f4D855549BcE9D9'; 19 | const KyberNetworkProxyABI = JSON.parse(fs.readFileSync('./abi/KyberNetworkProxy.abi', 'utf8')); 20 | const KyberNetworkProxyAddress = '0xF6084Ad447076da0246cD28e104533f9f51dbD2F'; 21 | const NetworkProxyInstance = new web3.eth.Contract(KyberNetworkProxyABI, KyberNetworkProxyAddress); 22 | 23 | const ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'; 24 | const KNC_ADDRESS = '0x8c13AFB7815f10A8333955854E6ec7503eD841B7'; 25 | const MANA_ADDRESS = '0xe19Ec968c15f487E96f631Ad9AA54fAE09A67C8c'; 26 | const KNC_ABI = JSON.parse(fs.readFileSync('./abi/KNC.abi', 'utf8')); 27 | const MANA_ABI = JSON.parse(fs.readFileSync('./abi/MANA.abi', 'utf8')); 28 | const KNCInstance = new web3.eth.Contract(KNC_ABI, KNC_ADDRESS); 29 | const MANAInstance = new web3.eth.Contract(MANA_ABI, MANA_ADDRESS); 30 | 31 | const userWallet = addresses[4]; 32 | 33 | function stdlog(input) { 34 | console.log(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}] ${input}`); 35 | } 36 | 37 | function tx(result, call) { 38 | const logs = (result.logs.length > 0) ? result.logs[0] : { address: null, event: null }; 39 | 40 | console.log(); 41 | console.log(` ${call}`); 42 | console.log(' ------------------------'); 43 | console.log(` > transaction hash: ${result.transactionHash}`); 44 | console.log(` > gas used: ${result.gasUsed}`); 45 | console.log(); 46 | } 47 | 48 | async function sendTx(txObject) { 49 | const nonce = await web3.eth.getTransactionCount(userWallet); 50 | const gas = 500 * 1000; 51 | 52 | const txData = txObject.encodeABI(); 53 | const txFrom = userWallet; 54 | const txTo = txObject._parent.options.address; 55 | 56 | const txParams = { 57 | from: txFrom, 58 | to: txTo, 59 | data: txData, 60 | value: 0, 61 | gas, 62 | nonce, 63 | chainId: await web3.eth.net.getId(), 64 | gasPrice, 65 | }; 66 | 67 | const signedTx = await web3.eth.signTransaction(txParams); 68 | 69 | return web3.eth.sendSignedTransaction(signedTx.raw); 70 | } 71 | 72 | async function main() { 73 | let expectedRate; 74 | let slippageRate; 75 | let result; 76 | let txObject; 77 | 78 | NetworkProxyInstance.setProvider(provider); 79 | KNCInstance.setProvider(provider); 80 | MANAInstance.setProvider(provider); 81 | 82 | stdlog('- START -'); 83 | stdlog(`KyberNetworkProxy (${KyberNetworkProxyAddress})`); 84 | 85 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 86 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 87 | stdlog(`ETH balance of ${userWallet} = ${web3.utils.fromWei(await web3.eth.getBalance(userWallet))}`); 88 | 89 | // Approve the KyberNetwork contract to spend user's tokens 90 | txObject = KNCInstance.methods.approve( 91 | KyberNetworkProxyAddress, 92 | web3.utils.toWei('1000000'), 93 | ); 94 | await sendTx(txObject); 95 | txObject = MANAInstance.methods.approve( 96 | KyberNetworkProxyAddress, 97 | web3.utils.toWei('1000000'), 98 | ); 99 | await sendTx(txObject); 100 | 101 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 102 | KNC_ADDRESS, // srcToken 103 | ETH_ADDRESS, // destToken 104 | web3.utils.toWei('100'), // srcQty 105 | ).call()); 106 | 107 | txObject = NetworkProxyInstance.methods.swapTokenToEther( 108 | KNC_ADDRESS, // srcToken 109 | web3.utils.toWei('100'), // srcAmount 110 | expectedRate, // minConversionRate 111 | ); 112 | result = await sendTx(txObject); 113 | tx(result, 'KNC <-> ETH swapTokenToEther()'); 114 | 115 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 116 | MANA_ADDRESS, // srcToken 117 | ETH_ADDRESS, // destToken 118 | web3.utils.toWei('1000'), // srcQty 119 | ).call()); 120 | 121 | txObject = NetworkProxyInstance.methods.swapTokenToEther( 122 | MANA_ADDRESS, // srcToken 123 | web3.utils.toWei('1000'), // srcAmount 124 | expectedRate, // minConversionRate 125 | ); 126 | result = await sendTx(txObject); 127 | tx(result, 'MANA <-> ETH swapTokenToEther()'); 128 | 129 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 130 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 131 | stdlog(`ETH balance of ${userWallet} = ${web3.utils.fromWei(await web3.eth.getBalance(userWallet))}`); 132 | 133 | stdlog('- END -'); 134 | } 135 | 136 | // Start the script 137 | main(); 138 | -------------------------------------------------------------------------------- /src/production/kyber/swapTokenToToken.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable no-underscore-dangle, no-unused-vars */ 3 | 4 | const BN = require('bn.js'); 5 | const fs = require('fs'); 6 | const HDWalletProvider = require('truffle-hdwallet-provider'); 7 | const moment = require('moment'); 8 | const Web3 = require('web3'); 9 | 10 | process.on('unhandledRejection', console.error.bind(console)); 11 | 12 | const mnemonic = 'gesture rather obey video awake genuine patient base soon parrot upset lounge'; 13 | const rpcUrl = 'http://localhost:8545'; // ganache-cli 14 | const provider = new HDWalletProvider(mnemonic, rpcUrl, 0, 10); 15 | const web3 = new Web3(provider); 16 | const { addresses, wallets } = provider; 17 | const gasPrice = web3.utils.toWei(new BN(10), 'gwei'); 18 | 19 | const KyberNetworkAddress = '0xA46E01606f9252fa833131648f4D855549BcE9D9'; 20 | const KyberNetworkProxyABI = JSON.parse(fs.readFileSync('./abi/KyberNetworkProxy.abi', 'utf8')); 21 | const KyberNetworkProxyAddress = '0xF6084Ad447076da0246cD28e104533f9f51dbD2F'; 22 | const NetworkProxyInstance = new web3.eth.Contract(KyberNetworkProxyABI, KyberNetworkProxyAddress); 23 | 24 | const KNC_ADDRESS = '0x8c13AFB7815f10A8333955854E6ec7503eD841B7'; 25 | const OMG_ADDRESS = '0x3750bE154260872270EbA56eEf89E78E6E21C1D9'; 26 | const MANA_ADDRESS = '0xe19Ec968c15f487E96f631Ad9AA54fAE09A67C8c'; 27 | const KNC_ABI = JSON.parse(fs.readFileSync('./abi/KNC.abi', 'utf8')); 28 | const OMG_ABI = JSON.parse(fs.readFileSync('./abi/OMG.abi', 'utf8')); 29 | const MANA_ABI = JSON.parse(fs.readFileSync('./abi/MANA.abi', 'utf8')); 30 | const KNCInstance = new web3.eth.Contract(KNC_ABI, KNC_ADDRESS); 31 | const OMGInstance = new web3.eth.Contract(OMG_ABI, OMG_ADDRESS); 32 | const MANAInstance = new web3.eth.Contract(MANA_ABI, MANA_ADDRESS); 33 | 34 | const userWallet = addresses[4]; 35 | 36 | function stdlog(input) { 37 | console.log(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}] ${input}`); 38 | } 39 | 40 | function tx(result, call) { 41 | const logs = (result.logs.length > 0) ? result.logs[0] : { address: null, event: null }; 42 | 43 | console.log(); 44 | console.log(` ${call}`); 45 | console.log(' ------------------------'); 46 | console.log(` > transaction hash: ${result.transactionHash}`); 47 | console.log(` > gas used: ${result.gasUsed}`); 48 | console.log(); 49 | } 50 | 51 | async function sendTx(txObject) { 52 | const nonce = await web3.eth.getTransactionCount(userWallet); 53 | const gas = 500 * 1000; 54 | 55 | const txData = txObject.encodeABI(); 56 | const txFrom = userWallet; 57 | const txTo = txObject._parent.options.address; 58 | 59 | const txParams = { 60 | from: txFrom, 61 | to: txTo, 62 | data: txData, 63 | value: 0, 64 | gas, 65 | nonce, 66 | chainId: await web3.eth.net.getId(), 67 | gasPrice, 68 | }; 69 | 70 | const signedTx = await web3.eth.signTransaction(txParams); 71 | 72 | return web3.eth.sendSignedTransaction(signedTx.raw); 73 | } 74 | 75 | async function main() { 76 | let expectedRate; 77 | let slippageRate; 78 | let result; 79 | let txObject; 80 | 81 | NetworkProxyInstance.setProvider(provider); 82 | KNCInstance.setProvider(provider); 83 | OMGInstance.setProvider(provider); 84 | MANAInstance.setProvider(provider); 85 | 86 | stdlog('- START -'); 87 | stdlog(`KyberNetworkProxy (${KyberNetworkProxyAddress})`); 88 | 89 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 90 | stdlog(`OMG balance of ${userWallet} = ${web3.utils.fromWei(await OMGInstance.methods.balanceOf(userWallet).call())}`); 91 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 92 | 93 | // Approve the KyberNetwork contract to spend user's tokens 94 | txObject = KNCInstance.methods.approve( 95 | KyberNetworkProxyAddress, 96 | web3.utils.toWei('10000'), 97 | ); 98 | await sendTx(txObject); 99 | 100 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 101 | KNC_ADDRESS, // srcToken 102 | OMG_ADDRESS, // destToken 103 | web3.utils.toWei('100'), // srcQty 104 | ).call()); 105 | 106 | txObject = NetworkProxyInstance.methods.swapTokenToToken( 107 | KNC_ADDRESS, // srcToken 108 | web3.utils.toWei('100'), // srcAmount 109 | OMG_ADDRESS, // destToken 110 | expectedRate, // minConversionRate 111 | ); 112 | result = await sendTx(txObject); 113 | tx(result, 'KNC <-> OMG swapTokenToEther()'); 114 | 115 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 116 | KNC_ADDRESS, // srcToken 117 | MANA_ADDRESS, // destToken 118 | web3.utils.toWei('100'), // srcQty 119 | ).call()); 120 | 121 | txObject = NetworkProxyInstance.methods.swapTokenToToken( 122 | KNC_ADDRESS, // srcToken 123 | web3.utils.toWei('100'), // srcAmount 124 | MANA_ADDRESS, // destToken 125 | expectedRate, // minConversionRate 126 | ); 127 | result = await sendTx(txObject); 128 | tx(result, 'KNC <-> MANA swapTokenToEther()'); 129 | 130 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 131 | stdlog(`OMG balance of ${userWallet} = ${web3.utils.fromWei(await OMGInstance.methods.balanceOf(userWallet).call())}`); 132 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 133 | 134 | stdlog('- END -'); 135 | } 136 | 137 | // Start the script 138 | main(); 139 | -------------------------------------------------------------------------------- /src/production/kyber/trade.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* eslint-disable no-underscore-dangle, no-unused-vars */ 3 | 4 | const BN = require('bn.js'); 5 | const fs = require('fs'); 6 | const HDWalletProvider = require('truffle-hdwallet-provider'); 7 | const moment = require('moment'); 8 | const Web3 = require('web3'); 9 | 10 | process.on('unhandledRejection', console.error.bind(console)); 11 | 12 | const mnemonic = 'gesture rather obey video awake genuine patient base soon parrot upset lounge'; 13 | const rpcUrl = 'http://localhost:8545'; // ganache-cli 14 | const provider = new HDWalletProvider(mnemonic, rpcUrl, 0, 10); 15 | const web3 = new Web3(provider); 16 | const { addresses, wallets } = provider; 17 | const gasPrice = web3.utils.toWei(new BN(10), 'gwei'); 18 | 19 | const KyberNetworkAddress = '0xA46E01606f9252fa833131648f4D855549BcE9D9'; 20 | const KyberNetworkProxyABI = JSON.parse(fs.readFileSync('./abi/KyberNetworkProxy.abi', 'utf8')); 21 | const KyberNetworkProxyAddress = '0xF6084Ad447076da0246cD28e104533f9f51dbD2F'; 22 | const NetworkProxyInstance = new web3.eth.Contract(KyberNetworkProxyABI, KyberNetworkProxyAddress); 23 | 24 | const KNC_ADDRESS = '0x8c13AFB7815f10A8333955854E6ec7503eD841B7'; 25 | const OMG_ADDRESS = '0x3750bE154260872270EbA56eEf89E78E6E21C1D9'; 26 | const MANA_ADDRESS = '0xe19Ec968c15f487E96f631Ad9AA54fAE09A67C8c'; 27 | const KNC_ABI = JSON.parse(fs.readFileSync('./abi/KNC.abi', 'utf8')); 28 | const OMG_ABI = JSON.parse(fs.readFileSync('./abi/OMG.abi', 'utf8')); 29 | const MANA_ABI = JSON.parse(fs.readFileSync('./abi/MANA.abi', 'utf8')); 30 | const KNCInstance = new web3.eth.Contract(KNC_ABI, KNC_ADDRESS); 31 | const OMGInstance = new web3.eth.Contract(OMG_ABI, OMG_ADDRESS); 32 | const MANAInstance = new web3.eth.Contract(MANA_ABI, MANA_ADDRESS); 33 | 34 | const userWallet = addresses[4]; 35 | 36 | function stdlog(input) { 37 | console.log(`${moment().format('YYYY-MM-DD HH:mm:ss.SSS')}] ${input}`); 38 | } 39 | 40 | function tx(result, call) { 41 | const logs = (result.logs.length > 0) ? result.logs[0] : { address: null, event: null }; 42 | 43 | console.log(); 44 | console.log(` ${call}`); 45 | console.log(' ------------------------'); 46 | console.log(` > transaction hash: ${result.transactionHash}`); 47 | console.log(` > gas used: ${result.gasUsed}`); 48 | console.log(); 49 | } 50 | 51 | async function sendTx(txObject) { 52 | const nonce = await web3.eth.getTransactionCount(userWallet); 53 | const gas = 500 * 1000; 54 | 55 | const txData = txObject.encodeABI(); 56 | const txFrom = userWallet; 57 | const txTo = txObject._parent.options.address; 58 | 59 | const txParams = { 60 | from: txFrom, 61 | to: txTo, 62 | data: txData, 63 | value: 0, 64 | gas, 65 | nonce, 66 | chainId: await web3.eth.net.getId(), 67 | gasPrice, 68 | }; 69 | 70 | const signedTx = await web3.eth.signTransaction(txParams); 71 | 72 | return web3.eth.sendSignedTransaction(signedTx.raw); 73 | } 74 | 75 | async function main() { 76 | let expectedRate; 77 | let slippageRate; 78 | let result; 79 | let txObject; 80 | 81 | NetworkProxyInstance.setProvider(provider); 82 | KNCInstance.setProvider(provider); 83 | OMGInstance.setProvider(provider); 84 | MANAInstance.setProvider(provider); 85 | 86 | stdlog('- START -'); 87 | stdlog(`KyberNetworkProxy (${KyberNetworkProxyAddress})`); 88 | 89 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 90 | stdlog(`OMG balance of ${userWallet} = ${web3.utils.fromWei(await OMGInstance.methods.balanceOf(userWallet).call())}`); 91 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 92 | 93 | // Approve the KyberNetwork contract to spend user's tokens 94 | txObject = KNCInstance.methods.approve( 95 | KyberNetworkProxyAddress, 96 | web3.utils.toWei('10000'), 97 | ); 98 | await sendTx(txObject); 99 | 100 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 101 | KNC_ADDRESS, // srcToken 102 | OMG_ADDRESS, // destToken 103 | web3.utils.toWei('100'), // srcQty 104 | ).call()); 105 | 106 | txObject = NetworkProxyInstance.methods.trade( 107 | KNC_ADDRESS, // srcToken 108 | web3.utils.toWei('100'), // srcAmount 109 | OMG_ADDRESS, // destToken 110 | userWallet, // destAddress 111 | web3.utils.toWei('100000'), // maxDestAmount 112 | expectedRate, // minConversionRate 113 | '0x0000000000000000000000000000000000000000', // walletId 114 | ); 115 | result = await sendTx(txObject); 116 | tx(result, 'KNC <-> OMG trade()'); 117 | 118 | ({ expectedRate, slippageRate } = await NetworkProxyInstance.methods.getExpectedRate( 119 | KNC_ADDRESS, // srcToken 120 | MANA_ADDRESS, // destToken 121 | web3.utils.toWei('100'), // srcQty 122 | ).call()); 123 | 124 | txObject = NetworkProxyInstance.methods.trade( 125 | KNC_ADDRESS, // srcToken 126 | web3.utils.toWei('100'), // srcAmount 127 | MANA_ADDRESS, // destToken 128 | userWallet, // destAddress 129 | web3.utils.toWei('100000'), // maxDestAmount 130 | expectedRate, // minConversionRate 131 | '0x0000000000000000000000000000000000000000', // walletId 132 | ); 133 | result = await sendTx(txObject); 134 | tx(result, 'KNC <-> MANA trade()'); 135 | 136 | stdlog(`KNC balance of ${userWallet} = ${web3.utils.fromWei(await KNCInstance.methods.balanceOf(userWallet).call())}`); 137 | stdlog(`OMG balance of ${userWallet} = ${web3.utils.fromWei(await OMGInstance.methods.balanceOf(userWallet).call())}`); 138 | stdlog(`MANA balance of ${userWallet} = ${web3.utils.fromWei(await MANAInstance.methods.balanceOf(userWallet).call())}`); 139 | 140 | stdlog('- END -'); 141 | } 142 | 143 | // Start the script 144 | main(); 145 | -------------------------------------------------------------------------------- /src/production/secretNote.js: -------------------------------------------------------------------------------- 1 | import web3 from './web3'; 2 | import compiledSecretNote from './SecretNote.json'; 3 | const BN = require('bn.js'); 4 | const crypto = require('crypto'); 5 | 6 | // const contractAddress = compiledSecretNote.networks[5777].address; 7 | const contractAddress = '0x187dc8FF9092471A71e344C18F52Cad17e43d719' 8 | console.log('contractAddress', contractAddress) 9 | 10 | const SecretNote = new web3.eth.Contract( 11 | compiledSecretNote.abi, 12 | contractAddress 13 | ) 14 | 15 | console.log('SecretNote', SecretNote) 16 | 17 | export const getAccounts = async () => { 18 | const accounts = await web3.eth.getAccounts(); 19 | return accounts 20 | } 21 | 22 | export const getCurrentAccount = async () => { 23 | const accounts = await web3.eth.getAccounts(); 24 | return accounts[0]; 25 | } 26 | 27 | export const getNotes = async () => { 28 | const notes = []; 29 | const accounts = await getAccounts(); 30 | const userAccount = accounts[0].slice(2); 31 | 32 | const len = await SecretNote.methods.getNotesLength().call(); 33 | for (let i = 0; i < len; i++) { 34 | const cipher = await SecretNote.methods.allNotes(i).call(); 35 | console.log('cipher', cipher) 36 | const dec = await decrypt(cipher, userAccount); 37 | console.log('dec', dec) 38 | if (dec.isMine) { 39 | console.log('worked') 40 | const noteHash = getNoteHash(userAccount, dec.amount); 41 | const state = await SecretNote.methods.notes('0x' + noteHash).call() 42 | console.log('state', state) 43 | if (state == '1' || state == '2') { 44 | // needs to be displayed 45 | notes.push({ hash: '0x' + noteHash, status: state == '1' ? 'Created' : 'Spent', amount: parseInt(dec.amount, 16) }); 46 | } 47 | } 48 | } 49 | console.log('notes', notes) 50 | return notes; 51 | } 52 | 53 | export const getAllNotes = async () => { 54 | const notes = []; 55 | const len = await SecretNote.methods.getNotesLength().call(); 56 | console.log('len', len) 57 | for (let i = 0; i < len; i++) { 58 | const hash = await SecretNote.methods.allNotes(i).call(); 59 | const hash2 = await SecretNote.methods.allHashedNotes(i).call(); 60 | console.log(hash2) 61 | notes.push({ hash }) 62 | } 63 | console.log('allnotes', notes) 64 | return notes; 65 | } 66 | 67 | export const claimDAI = async (amount) => { 68 | const accounts = await getAccounts(); 69 | console.log('accounts', accounts, amount) 70 | await SecretNote.methods.claimNote(amount).send({ 71 | from: accounts[0], 72 | gasPrice: '0x' + parseInt('10000000000').toString(16) 73 | }); 74 | } 75 | 76 | function getNoteHash(address, amount) { 77 | // pad address and amount to 32bytes 78 | let _address = new BN(address, 16).toString(16, 64); 79 | let _amount = new BN(amount, 16).toString(16, 64); // 32 bytes = 64 chars in hex 80 | console.log(_address, _amount) 81 | const buf = Buffer.from(_address + _amount, 'hex'); 82 | const digest = crypto.createHash('sha256').update(buf).digest('hex'); 83 | console.log('digest', digest) 84 | return digest; 85 | } 86 | 87 | async function decrypt(cipher, userAccount) { 88 | // let payload = await web3.eth.accounts.decrypt(JSON.parse(cipher), 'vitalik').privateKey 89 | const address = cipher.slice(0, 40).toLowerCase(); 90 | const amount = cipher.slice(40); 91 | console.log(address, amount) 92 | return { isMine: address === userAccount.toLowerCase(), amount } 93 | // console.log('decrypt', address, userAccount) 94 | // return true; 95 | // payload = payload.slice(2) 96 | // const amount = payload.slice(40) 97 | // console.log(address, amount); 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/production/web3.js: -------------------------------------------------------------------------------- 1 | import Web3 from 'web3'; 2 | let web3; 3 | 4 | //optimized for server-side rendering and for absent metamask 5 | 6 | if (typeof window !== 'undefined' && typeof window.web3 !== 'undefined') { 7 | //We are in the browser and metamask in running 8 | web3 = new Web3(window.web3.currentProvider); 9 | } else { 10 | //We are either on the server or the user isn't running metamask 11 | const provider = new Web3.providers.HttpProvider( 12 | 'https://ropsten.infura.io/v3/6dfe769f94364017b82a58d6b5c3543e' 13 | ); 14 | 15 | web3 = new Web3(provider); 16 | } 17 | 18 | export default web3; 19 | 20 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read http://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit http://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See http://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl) 104 | .then(response => { 105 | // Ensure service worker exists, and that we really are getting a JS file. 106 | const contentType = response.headers.get('content-type'); 107 | if ( 108 | response.status === 404 || 109 | (contentType != null && contentType.indexOf('javascript') === -1) 110 | ) { 111 | // No service worker found. Probably a different app. Reload the page. 112 | navigator.serviceWorker.ready.then(registration => { 113 | registration.unregister().then(() => { 114 | window.location.reload(); 115 | }); 116 | }); 117 | } else { 118 | // Service worker found. Proceed as normal. 119 | registerValidSW(swUrl, config); 120 | } 121 | }) 122 | .catch(() => { 123 | console.log( 124 | 'No internet connection found. App is running in offline mode.' 125 | ); 126 | }); 127 | } 128 | 129 | export function unregister() { 130 | if ('serviceWorker' in navigator) { 131 | navigator.serviceWorker.ready.then(registration => { 132 | registration.unregister(); 133 | }); 134 | } 135 | } 136 | --------------------------------------------------------------------------------