Coder Social home page Coder Social logo

shazow / whatsabi Goto Github PK

View Code? Open in Web Editor NEW
948.0 13.0 59.0 913 KB

Extract the ABI (and other metadata) from Ethereum bytecode, even without source code.

License: MIT License

Makefile 0.30% Nix 0.45% JavaScript 0.14% TypeScript 99.11%
bytecode ethereum evm web3

whatsabi's Introduction

WhatsABI

WhatsABI

Guess an ABI and detect proxies from an Ethereum bytecode, even if it's unverified.

WhatsABI is perfect for building procedural frontends, embedding in wallets, block explorers, or doing bytecode analysis.

Features

What can WhatsABI do?

  • Return selectors from bytecode.
  • Look up function signatures from selectors.
  • Helpers for looking up ABI and signatures from public databases (like Sourcify, Etherscan, OpenChain, 4Byte).
  • ✨ Resolve proxy contracts!
  • Small bundle (less than 15 KB) that works with Ethers.js, Viem, and others.

WhatsABI is different from other EVM analysis tools in some important ways:

  • Built in Typescript with minimal dependencies, so that it is runnable in the browser and embeddable in wallets.
  • Algorithms used are limited to O(instructions) with a small constant factor, so that complex contracts don't cause it to time out or use unbounded memory.
  • Does not rely on source code, so it works with unverified contracts.
  • Does not assume the source language, so it can work for source languages other than Solidity (Vyper, or even hand-written assembly).
  • Permissive open source (MIT-licensed), so that anyone can use it.

Usage

Generated docs: https://tsdocs.dev/docs/@shazow/whatsabi

Quick start:

import { ethers } from "ethers";
import { whatsabi } from "@shazow/whatsabi";

const provider = ethers.getDefaultProvider(); // substitute with your fav provider
const address = "0x00000000006c3852cbEf3e08E8dF289169EdE581"; // Or your fav contract address

// Quick-start:

const result = await whatsabi.autoload(address, { provider });
console.log(result.abi);
// -> [ ... ]

Breaking it down:

const code = await provider.getCode(address); // Load the bytecode

// Get just the callable selectors
const selectors = whatsabi.selectorsFromBytecode(code);
console.log(selectors); // -> ["0x06fdde03", "0x46423aa7", "0x55944a42", ...]

// Get an ABI-like list of interfaces
const abi = whatsabi.abiFromBytecode(code);
console.log(abi);
// -> [
//  {"type": "event", "hash": "0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f"},
//  {"type": "function", "payable": true, "selector": "0x06fdde03", ...},
//  {"type": "function", "payable": true, "selector": "0x46423aa7", ...},
//   ...

// We also have a suite of database loaders for convenience
const signatureLookup = new whatsabi.loaders.OpenChainSignatureLookup();
console.log(await signatureLookup.loadFunctions("0x06fdde03"));
// -> ["name()"]);
console.log(await signatureLookup.loadFunctions("0x46423aa7"));
// -> ["getOrderStatus(bytes32)"]);

// We also have event loaders!
console.log(await signatureLookup.loadEvents("0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f"));
// -> ["CounterIncremented(uint256,address)"]

// There are more fancy loaders in whatsabi.loaders.*, take a look!

// Here's a multiloader with an Etherscan API key, it can be used with autoload below.
// Each source will be attempted until a result is found.
const loader = new whatsabi.loaders.MultiABILoader([
  new whatsabi.loaders.SourcifyABILoader(),
  new whatsabi.loaders.EtherscanABILoader({
    apiKey: "...", // Replace the value with your Etherscan API key
  }),
]);
const { abi, name, /* ... other metadata */ } = await loader.getContract(address));

All together with our do-all-the-things helper:

...

let result = await whatsabi.autoload(address, {
  provider: provider,

  // * Optional loaders:
  // abiLoader: whatsabi.loaders.defaultABILoader,
  // signatureLoader: whatsabi.loaders.defaultSignatureLookup,

  // There is a handy helper for adding the default loaders but with your own settings
  ... whatsabi.loaders.defaultsWithEnv({
    SOURCIFY_CHAIN_ID: 42161,
    ETHERSCAN_BASE_URL: "https://api.arbiscan.io/api",
    ETHERSCAN_API_KEY: "MYSECRETAPIKEY",
  }),

  // * Optional hooks:
  // onProgress: (phase: string) => { ... }
  // onError: (phase: string, context: any) => { ... }

  onProgress: (phase) => console.log("autoload progress", phase),
  onError: (phase, context) => console.log("autoload error", phase, context),

  // * Optional settings:
  // followProxies: false,
  // enableExperimentalMetadata: false,
});

console.log(result.abi);

// Detail will vary depending on whether `address` source code was available,
// or if bytecode-loaded selector signatures were available, or
// if WhatsABI had to guess everything from just bytecode.

// We can even detect and resolve proxies!
if (result.followProxies) {
    console.log("Proxies detected:", result.proxies);

    result = await result.followProxies();
    console.log(result.abi);
}

Or we can auto-follow resolved proxies, and expand parts of the result object:

const { abi, address } = await whatsabi.autoload(
    "0x4f8AD938eBA0CD19155a835f617317a6E788c868",
    {
        provider,
        followProxies: true,
    },
});

console.log("Resolved to:", address);
// -> "0x964f84048f0d9bb24b82413413299c0a1d61ea9f"

See Also

Some Cool People Said...

Omg WhatsABI by @shazow is so good that it can solve CTFs.
In one of my CTFs, students are supposed to find calldata that doesn’t revert
WhatsABI just spits out the solution automatically😂 I’m impressed!👏

🗣️ Nazar Ilamanov, creator of monobase.xyz

WhatsABI by @shazow takes contract bytecode, disassembled it into a set of EVM instructions, and then looks for the common Solidity's dispatch pattern.
Check out the source, it's actually very elegant!

🗣️ WINTΞR, creator of abi.w1nt3r.xyz

really cool stuff from @shazow
deduce a contract's ABI purely from bytecode

🗣️ t11s, from Paradigm

Caveats

  • Finding valid function selectors works great!
  • Detecting Solidity-style function modifiers (view, payable, etc) is still unreliable.
  • There's some minimal attempts at guessing the presence of arguments, but also unreliable.
  • Call graph traversal only supports static jumps right now. Dynamic jumps are skipped until we add abstract stack tracing, this is the main cause of above's unreliability.
  • Event parsing is janky, haven't found a reliable pattern so assume it's best effort. Feel free to open an issue with good failure examples, especially false negatives.

Development

$ cat .env  # Write an .env file with your keys, or `cp .env.example .env`
export INFURA_API_KEY="..."
export ETHERSCAN_API_KEY="..."
$ nix develop  # Or use your system's package manager to install node/ts/etc
[dev] $ npm install
[dev] $ ONLINE=1 make test

Thanks

  • ethers.js for being excellent, and having a helpful assembler sub-package was inspiring.
  • @jacobdehart for the library name and logo that is totally a wasabi and not a green poop!

License

MIT

whatsabi's People

Contributors

autosaida avatar jfschwarz avatar jxom avatar kuzdogan avatar onetxpunch avatar shazow avatar sonofmosiah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

whatsabi's Issues

Accuracy and speed results from EVMole benchmark

Hi,
I've added your project to the accuracy and speed benchmark of cdump/evmole

I think you may be interested in that results, to examine errors of whatsabi you can run:

$ sudo apt install git-lfs
$ git clone https://github.com/cdump/evmole 
$ cd evmole/

# you need GNU Make, https://formulae.brew.sh/formula/make - if you are using macos

$ PROVIDERS="etherscan whatsabi" make -C benchmark
$ poetry run python3 benchmark/compare.py --providers etherscan whatsabi --web-listen 0.0.0.0:8080 

# skip PROVIDERS/--providers to compare with other tools, like evm-hound-rs & evmole

Open http://127.0.0.1:8080 after that and you'll see the results:
20231202_10h28m29s_grim

P.S. if you believe I am using your project incorrectly, please feel free to submit a pull request with fixes.

disasm: Abstract Stack Tracing

To handle dynamic jumps, we need to keep track of the abstract stack, and we need to do this within the computational complexity goals of this project (which could be challenging).

Overall this would substantially improve the accuracy of our extracted metadata. Right now we're losing a lot of call flows by only tracking static jumps.

EVM bytecode to ABI improvements

  • Detect internal function selectors
  • Detect if function is payable
  • Detect fallback receivers
  • Detect zero-value selectors
  • Detect event signatures
  • Detect number of function arguments
  • Detect sizes of function arguments
  • Detect external calls

Some proxies failed to resolve.

After analyzing a lot of data, most of the addresses are doing a good job of detection. The address below belongs to a proxy, but there is no way to resolve it, I don't know if I'm using the wrong method or what?

TransparentUpgradeableProxy?
"""
Error processing proxy resolver EIP1967Proxy: missing revert data (action="call", data=null, reason=null, transaction={ "data": "0x5c60da1b", "to": "0x3E135c3E981fAe3383A5aE0d323860a34CfAB893" }, invocation=null, revert=null, code=CALL_EXCEPTION, version=6.7.1)
"""

Create2BeaconProxy?
"""
Failed to resolve proxy for address: 0x581acd618ba7ef6d3585242423867adc09e8ed60
Failed to resolve proxy for address: 0xa6a3448ea5f5f15ee6c089279712f720c0e16a7f
Failed to resolve proxy for address: 0xb6fc082fdc4dbe19e85d50bde82214919526cb2a
Failed to resolve proxy for address: 0xc088661f2703e5c011612d6a7ff960ee669f8b56
Failed to resolve proxy for address: 0x9b9278c8eb1e49eb3ced22a2d4e144479f07c7df
Failed to resolve proxy for address: 0x9608b7496838e7e00a57cb681b469666a33d8b20
Failed to resolve proxy for address: 0xe5f74b8e5ece57ef1c129523133b5d19ddf8f19d
Failed to resolve proxy for address: 0x5faf6a2d186448dfa667c51cb3d695c7a6e52d8e
Failed to resolve proxy for address: 0x1b80250c32d5b5e278d03e9843475c56bf0a439e
Failed to resolve proxy for address: 0xb9e068ea140511175b6e487b5b48e993bf11838d
Failed to resolve proxy for address: 0xe1aef926b8c94a3fbbeade65afc94dc02803ed40
Failed to resolve proxy for address: 0x8217772e6fe703f18c5c08ea04ab962395f62aa6
Failed to resolve proxy for address: 0x4af84cfb08b484cd32e4378a4b627a5f009b5117
Failed to resolve proxy for address: 0xcca916ff964fdc93cfbe7d34cd888ff28142e645
Failed to resolve proxy for address: 0xdff8bad97aae5995ba0c8d4bdd36f8b5d577e9e4
Failed to resolve proxy for address: 0xbaf6c73a06afd9e02a4af28901698e52fe3cc973
Failed to resolve proxy for address: 0xb8945c69aeb8ad8e16f1e49eaef5c7e48011d178
Failed to resolve proxy for address: 0x0f7c258ef6abd872dd5481785116556a85856ada
Failed to resolve proxy for address: 0x29f033720d84d0f85c1beccf80e51449c06ca2d2
Failed to resolve proxy for address: 0xeb07c09a72f40818704a70f059d1d2c82cc54327
Failed to resolve proxy for address: 0x574cce720237a9d2e679d9093c508e0cceeb2535
Failed to resolve proxy for address: 0xbd2861c0f43f6e8d571fcfa5a7c77d13d5695ebf
Failed to resolve proxy for address: 0x5cd5623aa41a139021645765cebfb4a82a43f029
Failed to resolve proxy for address: 0xd4108bb1185a5c30ea3f4264fd7783473018ce17
Failed to resolve proxy for address: 0x67b9f46bcba2df84ecd41cc6511ca33507c9f4e9
Failed to resolve proxy for address: 0x64c24088de9c5c9197ced6ce9adce16c802fd844
Failed to resolve proxy for address: 0xbf9b32dae8c5267c9295e875f8943b1224d12975
Failed to resolve proxy for address: 0x29b145edfa80b20a3f6f79b57ef4b1ca33ad2777
Failed to resolve proxy for address: 0x471de8beadecd171de505a707bdf0e783a794126
Failed to resolve proxy for address: 0x60a80cbd47e738c88ff414f304fc9b116be37b92
Failed to resolve proxy for address: 0x2e4c82b9f5aa477aba5594ecf5412e4f42c56b7f
Failed to resolve proxy for address: 0x902cf5373317bb3e42660e9f4e85aa21532c0e44
Failed to resolve proxy for address: 0x490d19e4cca09e552c5b1844410e9163182b44d4
Failed to resolve proxy for address: 0xdacf926c6ed25232db5d64288659784147335f5e
Failed to resolve proxy for address: 0xec3c709993f5deda568d6dab09c90bf533021171
Failed to resolve proxy for address: 0x50ace5c459bc3ba3bc1aad7dfb62f88bb94afa06
Failed to resolve proxy for address: 0x5868125220188b260b31e0b4f7a53d3e965a0907
Failed to resolve proxy for address: 0x88ee509e02cfa939430cb8452e63c296be770f96
Failed to resolve proxy for address: 0x8aab6f7f32f9da2c5efb6ab62d76130aeaa5cf69
Failed to resolve proxy for address: 0x35822eaf02cae69e97f5fa36f0188686fa544e21
Failed to resolve proxy for address: 0xa9e1f9c1ec6ecb103c260c3eda0fa28e2785c57a
Failed to resolve proxy for address: 0x5c0a86a32c129538d62c106eb8115a8b02358d57
Failed to resolve proxy for address: 0x5d1c5dee420004767d3e2fb7aa7c75aa92c33117
Failed to resolve proxy for address: 0x829b97a6218d320e97c0a915eb8a07c4dd408cd5
Failed to resolve proxy for address: 0xd1e9a67c7e0558b55341ffdbbef9d34b9db6f235
Failed to resolve proxy for address: 0xf8f815859a6b3447cbeb04301fa35a86c5272f0d
Failed to resolve proxy for address: 0x7f30476e51d7f6286a74b3b314fff51bc7cead92
Failed to resolve proxy for address: 0x1d47322cddbb832b74d8b584aa42ece998498ebe
Failed to resolve proxy for address: 0xa8d412f570401eaad3059d3d4df6336fb37e17e0
Failed to resolve proxy for address: 0x614a03f9db294c7def83423f9719d22410c1abef
Failed to resolve proxy for address: 0x14d1551e734a324ba148158de9981f17f9de73c4
Failed to resolve proxy for address: 0xc58ad9817a324aafa489d30eaf53376b28a9641e
Failed to resolve proxy for address: 0x8c3ab8544b32d0181d53f0004cc51793101e9536
Failed to resolve proxy for address: 0x28cad0a218d15b7b651a06b444f39e7186b52fcb
Failed to resolve proxy for address: 0x3dfc321b714262902468b024d704f6039b650570
Failed to resolve proxy for address: 0xa813f02f95228642a60f6e3cf5ac0273c4160613
Failed to resolve proxy for address: 0x3e7d590b398a8bd7a12fb6071af197bf74248895
Failed to resolve proxy for address: 0x4723df875d4bfdfe4190236b307ec4a65b00002e
Failed to resolve proxy for address: 0x7f44bb621bd9ddceb02540ea2b51c60d6cc4b430
Failed to resolve proxy for address: 0x4c9725cd7db182d5b23e99855e357e3f4742c137
Failed to resolve proxy for address: 0x8eb40c1805ae6a6ce8e8b09ca0e5bbad5a2af7ca
Failed to resolve proxy for address: 0x2c7a424fc64a78cd263ff767d7af875647fcd3b0
Failed to resolve proxy for address: 0x555cccf378b01c550cc7cc7aa138eec70e4c4f33
Failed to resolve proxy for address: 0x9fcb13e8563fb8954b64d50074be596a651a67f5
Failed to resolve proxy for address: 0xb05827f130d2aac67081d9ca84742a6d199a5d9d
Failed to resolve proxy for address: 0x790a60024bc3aea28385b60480f15a0771f26d09
Failed to resolve proxy for address: 0x366834589352937c88aaad8be569e606d58a3f81
Failed to resolve proxy for address: 0xf6fa4cf51258c21cb94918b1100c99968f32f6e0
Failed to resolve proxy for address: 0xa2999e886a9f4d1bae6ecfec614edfce5d8e06c2
Failed to resolve proxy for address: 0xf78b9bae2f7968918deeda37551b7dd83b6dffea
Failed to resolve proxy for address: 0xba63baffcebb44aa560e5f0671d1049ffa05c1c9
Failed to resolve proxy for address: 0x70f79de002b434ee033ea7e9349c310e18f7eb46
Failed to resolve proxy for address: 0xa183014cef1dfc81cb3fd1dd2ce2ea1380fd983d
Failed to resolve proxy for address: 0xe53e3d446a2ac0d19f6481a2462dd43309f341d7
Failed to resolve proxy for address: 0xd4d5f210a1c6acf2a5d2f7f6ab3158711236c417
Failed to resolve proxy for address: 0xd30dd3b2804d4a41b2c796a4b5ac307b2672e2f3
Failed to resolve proxy for address: 0x8363713fe51ad37a113a1aa1ae61b20e42414e5c
Failed to resolve proxy for address: 0xd7df60f0857cfb0003f389ff338df50ba5c17fde
Failed to resolve proxy for address: 0x663134dc10acac6a5f5ad9d3231c51d71de0f0da
Failed to resolve proxy for address: 0xa07c7cebcd136a5c255ad20534d31cd1afba42e6
Failed to resolve proxy for address: 0x7472fbf0130a71d1241890cf5d068be4778c6154
Failed to resolve proxy for address: 0x2b39eceafe795cd4debca0721f2f68409e3b7df2
Failed to resolve proxy for address: 0x48672352e191b2e78bbc319e1d3e751ffc64439d
Failed to resolve proxy for address: 0x04e037787a6e79e6aaea79dbb7a7c4109f49d4bd
Failed to resolve proxy for address: 0x4a7a4c6cf6f0d0e9542df29974e40b4de2178ebc
Failed to resolve proxy for address: 0x804bc39d5670ca176203556dac06fcd7ed37ddb1
Failed to resolve proxy for address: 0xf80ffb0699b8d97e9fd198ccbc367a47b77a9d1c
Failed to resolve proxy for address: 0xcb48144a9fd2c4fa23905762d4e4257d6136adbc
Failed to resolve proxy for address: 0x164a468709bc32f826979fd20322a3ea676a3481
Failed to resolve proxy for address: 0x08765c76c758da951dc73d3a8863b34752dd76fb
Failed to resolve proxy for address: 0xb91bca4c6a607448a093803b3b2a9a4ed3e9f71e
Failed to resolve proxy for address: 0x7e94fb2a0d2db1ff9c85ac818fd28b8bcb799a8b
Failed to resolve proxy for address: 0x4e4a158159e35cce9c94344d503091d8b2a90952
Failed to resolve proxy for address: 0x90b9162018be1b4b09073eca5925b08d19b63541
Failed to resolve proxy for address: 0xe61186dea096349eb5652d45c16079d56d2c2b22
Failed to resolve proxy for address: 0x7229e4e13dd6668c34026f4baa2e44a704bfa5ae
Failed to resolve proxy for address: 0xc60af90a13173353565832f02a2a48222b97ab15
Failed to resolve proxy for address: 0xb31858b8a49dd6099869b034da14a7a9cad1382b
Failed to resolve proxy for address: 0xbf5c04491638bbb3912092e9e9427e376b6554cb
Failed to resolve proxy for address: 0x3451b4c5395b3fe06aa629af73207cfaa28131d1
Failed to resolve proxy for address: 0x4786d62edf0dc42d905107f8b04bbc2779afe90d
Failed to resolve proxy for address: 0x9251e59b053d9407a16f1bd53a3136f4897d7c06
Failed to resolve proxy for address: 0x66d461ba3f1da2b32bf5b8dca3a40b905ab7c639
Failed to resolve proxy for address: 0xcb784233855c97d8532f8eefa094ba876187a150
Failed to resolve proxy for address: 0xabbdbb92cd58fd2f7dba953855b88ed2a2be1465
Failed to resolve proxy for address: 0x929fd5879847f41f05b6cf3746b4343f38b8741b
Failed to resolve proxy for address: 0x96ad7aee7cf43ae2165c485b40c18cae0eba98b4
Failed to resolve proxy for address: 0x1ea1ccfecc55938a71c67150c41e7eba0743e94c
Failed to resolve proxy for address: 0x11df658567e615f69d23289be8a27a9c260ce297
Failed to resolve proxy for address: 0xcbc439fbb8ef91f64631d13187c8d4c96410e8ca
Failed to resolve proxy for address: 0x65879e73aecfc8a1cc7fe44a2ffb3392721e5652
Failed to resolve proxy for address: 0x47be8559ecbaeb84c759c215497d40334f97d754
Failed to resolve proxy for address: 0x3d21b6f588428fcb9091ebd799feabe3eaf4977f
Failed to resolve proxy for address: 0xaeb780ca1b17e9429f84e15a375491cb5372b4ca
Failed to resolve proxy for address: 0x573f76519bb7fd10c95b38f4ffd569d9a3989c39
Failed to resolve proxy for address: 0x4500dcdcb468979f859c56cfcb1040173c69dde8
Failed to resolve proxy for address: 0xa48f2713a0c92b0395ba964e68079d8b07da729d
"""

Vyper_contract?
"""
Failed to resolve proxy for address: 0x2d5d4869381c4fce34789bc1d38acce747e295ae
Failed to resolve proxy for address: 0x84ca3bf4822a342e9c1ad27bd5fbcf5fc5e37128
Failed to resolve proxy for address: 0xff8f8a38c80b9899a928152d58f219fdccd4306c
Failed to resolve proxy for address: 0xd1a075c806e40d79e32ea09553e7080d5d9d4b29
Failed to resolve proxy for address: 0xf59d66c1d593fb10e2f8c2a6fd2c958792434b9c
Failed to resolve proxy for address: 0xd070f6216ef1f2609dfae2ae7e3d7208b1e993d5
Failed to resolve proxy for address: 0x378cb52b00f9d0921cb46dfc099cff73b42419dc
Failed to resolve proxy for address: 0x16825039dfe2a5b01f3e1e6a2bbf9a576c6f95c4
Failed to resolve proxy for address: 0xd8c620991b8e626c099eaab29b1e3eea279763bb
Failed to resolve proxy for address: 0x6fafca7f49b4fd9dc38117469cd31a1e5aec91f5
Failed to resolve proxy for address: 0x4fdd1b06ef986238446be0f3ea163c1b6fe28cc1
Failed to resolve proxy for address: 0x7f7df0e9a040dda05fc609143cc8da7cc6c59587
Failed to resolve proxy for address: 0xa72ad1293b253522fde41f1104aa432d7669b299
Failed to resolve proxy for address: 0x2807387f1212cb2852ab97cdaa3627daca5e4661
Failed to resolve proxy for address: 0xb85e3fe36a6084985e66d704abd4be4ea51e06ce
Failed to resolve proxy for address: 0xafb6c80ff3cfdae5977df0196f3d35cd65e3c7a3
Failed to resolve proxy for address: 0xba3cfea6514cf5acddeff3167df0b7a4337751bc
Failed to resolve proxy for address: 0x5dc81697fc0b3752c1277d260064374e95e8a18b
Failed to resolve proxy for address: 0xfc1cf3dc111981ea4372e91f437581524f3721be
Failed to resolve proxy for address: 0xe02c8114b66e838e028ae743fee915ba530b24e6
Failed to resolve proxy for address: 0xe4174e39beeebb85c7c36cba68f316a5144e7d08
Failed to resolve proxy for address: 0x817fe0d7935170dc91ccbe4aa3450abde302bf10
Failed to resolve proxy for address: 0x528d50dc9a333f01544177a924893fa1f5b9f748
Failed to resolve proxy for address: 0x59518884eebfb03e90a18adbaaab770d4666471e
Failed to resolve proxy for address: 0x7158c1bee7a0fa5bd6affc77b2309991d7adcdd4
Failed to resolve proxy for address: 0x1f8ad2cec4a2595ff3cda9e8a39c0b1be1a02014
Failed to resolve proxy for address: 0x5120feabd5c21883a4696dbcc5d123d6270637e9
Failed to resolve proxy for address: 0x2dfb14e32e2f8156ec15a2c21c3a6c053af52be8
Failed to resolve proxy for address: 0xdf5110ef6bc751cbaf76d35b8a3f312b581b5173
Failed to resolve proxy for address: 0x8472e9914c0813c4b465927f82e213ea34839173
Failed to resolve proxy for address: 0xfd0877d9095789caf24c98f7cce092fa8e120775
Failed to resolve proxy for address: 0xf11b141be4d1985e41c3aea99417e27603f67c4c
Failed to resolve proxy for address: 0x6d765cbe5bc922694afe112c140b8878b9fb0390
Failed to resolve proxy for address: 0x497590d2d57f05cf8b42a36062fa53ebae283498
Failed to resolve proxy for address: 0x4962b6c40b5e9433e029c5c423f6b1ce7ff28b0f
Failed to resolve proxy for address: 0x2147935d9739da4e691b8ae2e1437492a394ebf5
Failed to resolve proxy for address: 0x63739d137eefab1001245a8bd1f3895ef3e186e7
Failed to resolve proxy for address: 0xce0f1ef5aaab82547acc699d3ab93c069bb6e547
Failed to resolve proxy for address: 0xf962b098ecc4352aa2ad1d4164bd2b8367fd94c3
Failed to resolve proxy for address: 0x71955515adf20cbdc699b8bc556fc7fd726b31b0
Failed to resolve proxy for address: 0x4856a7efbbfcae92ab13c5e2e322fc77647bb856
Failed to resolve proxy for address: 0xa2619fdfb99abeb533a1147461f3f1109c5ade75
Failed to resolve proxy for address: 0xb98df7163e61bf053564bde010985f67279bbcec
Failed to resolve proxy for address: 0xd2c65e20c3fde3f18097e7414e65596e0c83b1a9
Failed to resolve proxy for address: 0x477faf103dadc5fe5baa40951cf7512dcbc18126
Failed to resolve proxy for address: 0x2f194da57aa855caa02ea3ab991fa5d38178b9e6
Failed to resolve proxy for address: 0x49b3e44e54b6220af892dba48ae45f1ea6bc4ae9
Failed to resolve proxy for address: 0xaf322a2edf31490250fdeb0d712621484b09abb6
Failed to resolve proxy for address: 0xac1c90b9c76d56ba2e24f3995f7671c745f8f308
Failed to resolve proxy for address: 0xb32747b4045479b77a8b8eb44029ba12580214f8
Failed to resolve proxy for address: 0x1ae8ccd120a05080d9a01c3b4f627f865685d091
Failed to resolve proxy for address: 0x56a5fd5104a4956898753dfb060ff32882ae0eb4
Failed to resolve proxy for address: 0x3466c90017f82dda939b01e8dbd9b0f97aef8dfc
Failed to resolve proxy for address: 0x7356f09c294cb9c6428ac7327b24b0f29419c181
Failed to resolve proxy for address: 0x0e880118c29f095143dda28e64d95333a9e75a47
Failed to resolve proxy for address: 0x0e8a7717a4fd7694682e7005957dd5d7598bf14a
Failed to resolve proxy for address: 0x314f951d144b397a088ea9eac5218bdc7db2ed4a
Failed to resolve proxy for address: 0xfcf8eda095e37a41e002e266daad7efc1579bc0a
Failed to resolve proxy for address: 0xed0244b688cf059f32f45e38a6ac6e479d6755f6
Failed to resolve proxy for address: 0x8e666277c3de28df68a78ede1274603eeea02d34
Failed to resolve proxy for address: 0x5dcd2999ff0685f6165938ec717b26b48998921c
Failed to resolve proxy for address: 0xa5ed287499e3c192c444336342bc4b0e25f51d88
Failed to resolve proxy for address: 0xa5588426040db2c83db16f640f64c7fb265974d4
Failed to resolve proxy for address: 0x83c8df34c6a9d31b97516791f85bac51ed37d49e
Failed to resolve proxy for address: 0xab2ccd6652a170f8fafff115b03ceb30fe855daf
Failed to resolve proxy for address: 0x0bacea14e683e42059c069bc96187520cb282cb9
Failed to resolve proxy for address: 0x8174bff3c861ef667b5f911884f4f7324b2b9c4f
Failed to resolve proxy for address: 0xda82b333a79cb07ddcec69580088f3d8b8f62915
Failed to resolve proxy for address: 0x23d737c8836977739b9a8dc6ddaf64c67bc936f7
Failed to resolve proxy for address: 0x386af2b835d90bc3c5d4e7ae3b1d27ba0f1d0724
Failed to resolve proxy for address: 0x56c218d200247cc7687b4fac31a371e38f6c8b55
Failed to resolve proxy for address: 0x9df9d1d176702bded106149f29005a9be1277ab4
Failed to resolve proxy for address: 0x6a072ff54db0a61476c53d829cd4ad8c91739825
Failed to resolve proxy for address: 0x4264c78898744167a26f886da6ce763965e4bba1
"""

Failed to resolve proxy for address: 0x9e9404849b9a6dd520bd6199aee5ce7f76c09245

Fix online tests/CI

There's some online tests relying on SELFDESTRUCT contracts that keep changing their code... not ideal.

Detect interfaces and common contract mixins

A convenient way to describe what a contract could be doing (especially if it's unverified) is by summarizing which interfaces it complies with.

We can do this either by using ERC-165 and looking for hardcoded interface IDs, or by comparing against known hashes of selectors in interfaces (https://github.com/shazow/eip-sighashes could be helpful for this).

Some common interfaces/functionality we want to look for:

bin/dot.ts: Remove selector assumption

Right now we start traversing the decompiled program with the assumption that the selector jump tables are the "entry points" into the call graph.

If it's a non-standard program without selectors, we should still be able to render some kind of interesting call graph.

Example: 0x4870525eae23fceb31df613d179ef6275e1b93a9

Bonus points for rendering all potential call graphs, even those that are disjoint from the entry points (the disjointedness will improve once we handle dynamic jumps better).

Port to other EVM compatible protocols

Is it possible to allow user input of the abi, instead of an ethereum smart contract address so that it might be compatible with Avalanche for example?

disasm: Guess function arguments

... without just looking up the sighash on a 4byte database. 😅

I don't have a great idea of how to do this without symbolic execution. I'd like to keep whatsabi to static analysis in O(nlogn) runtime per number of instructions.

My gut feel is that the process to approach this:

  1. Try to guess the total expected calldata size, or even number of arguments
  2. Might help if we can figure out the bytecode boundaries for each function? (are JUMPI table to JUMPDEST mappings contiguous?)
  3. Figure out the expected byte size of each argument, if any?

I think that's as far as we can get without tracking a non-fixed stack depth.

Related project: ethb3rlin/find-a-team#32

disasm: Allow different static analysis backends?

There's a few disassemblers out there with varying constraints/features.

It could be a nice short-term approach to support third-party backends behind a unified whatsabi API. It would also help detect discrepancies across implementations, allow for comparative benchmarking, and help iteration/finding bugs.

Or if another backend is made to be good enough, whatsabi could cut some unnecessary code and replace maintenance burden with upstream collaboration. :)

Was recently pointed to https://github.com/acuarica/evm which seems quite nice (currently under heavy development), and possible a good compliment for a whatsabi backend.

Invalid JSON output: keys and values missing double quotes

I'm running whatsabi on a Macbook Air with M2 chip, node v18.13.0, ethers v6.7.1 and whatsabi v0.7.0.

From the README:

import { ethers } from "ethers";
import { whatsabi } from "@shazow/whatsabi";

const provider = new ethers.getDefaultProvider(); // substitute with your fav provider
const address = "0x00000000006c3852cbEf3e08E8dF289169EdE581"; // Or your fav contract address
const code = await provider.getCode(address); // Load the bytecode

// Get just the callable selectors
const selectors = whatsabi.selectorsFromBytecode(code);
console.log(selectors); // -> ["0x06fdde03", "0x46423aa7", "0x55944a42", ...]

// Get an ABI-like list of interfaces
const abi = whatsabi.abiFromBytecode(code);
console.log(abi);
// -> [
//  {"type": "event", "hash": "0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f"},

Instead, this same code produces the following invalid JSON:

[
  '0x06fdde03', '0x46423aa7',
  '0x55944a42', '0x5b34b966',
  ...
]

[
  {
    type: 'function',
    selector: '0x06fdde03',
    ...
  }
]

release: v0.3

Major internal changes merged from #14:

  • stateMutability included in the ABI, which is reliable in detecting payable functions, but not reliable in distinguishing nonpayable vs view yet (no attemps to detect pure yet, probably too dangerous to be wrong?).
    [Fixes #17 to some extent, probably need another issue to track improvements]
  • In some cases, it manages to successfully guess whether there are inputs or outputs (not super reliable, I'd say like... 60%?), but there have been major changes behind the scenes with how the static analysis works so we can do more advanced things moving forward. I think we can do better next release.

Things I'd like to do before doing a release:

  • More testing against contracts that worked well with v0.2.x
  • Write a "combining" metadata function that merges loader-based ABIs (which have names but no stateMutability/return values) with disasm-based ABIs (which have stateMutability and return values)
  • Update README about debugging tools in src.ts/bin? (Maybe rename to src.ts/scripts?)
  • Bonus: Finish writing autoloaders? Just need some final touches on #8

disasm: Return values

Unfortunately selector hashes don't include the return value, so none of the 4byte databases include return types.

Questions:

  1. How do we detect whether a function has a return value at all?
  2. If it does, can we do anything to guess the type or size?

What we have:

  • Function selectors with instruction pointers
  • Boundaries for selectors' functions (they seem to be assembled contiguously based on a few anecdotal examinations).

Updated challenges:

  • Old Solidity (e.g. WETH compiled with 0.4.x) assembles functions with simple return macros, so those are fairly easily detectable by looking back for RETURN from the end of each selector function's boundary.
  • Modern Solidity assembles returns through chains of helper branches that prepare the data. I can't think of a way to resolve these in a ~single pass. Anyone have ideas?
    • One of the helper branches is a STOP branch, which shouldn't be too hard to find in isolation (basically JUMPDEST STOP, sometimes there are multiples, not sure why). Could we just use the absence of a STOP or JUMP to a STOP offset as an indicator whether there is a return value of somekind?
  • In either case, I'm having trouble finding a reliable pattern for extracting the size of the return values, even in the old-Solidity simple case.

disasm: Improve stateMutability, payable, and other modifier metadata reliability

When using abiFromBytecode many pure/view functions are returning payable: true stateMutability: 'payable' when tested on different addresses.

Similarly, many non-payable (but state changing) functions are returning payable: false stateMutability: 'view'

I haven't been able to narrow down why this occurs yet - it seems to behave differently depending on the bytecode it checks.

It will either return ALL functions as payable: true stateMutability: 'payable' or it will return all functions as payable: false stateMutability: 'view'

For example the 'name()' selector 0x06fdde03.

On some contracts this will return:

{
  type: 'function',
  selector: '0x06fdde03',
  payable: false,
  stateMutability: 'view',
  outputs: [ { type: 'bytes' } ]
}

Whereas on others it will return:

{
  type: 'function',
  selector: '0x06fdde03',
  payable: true,
  stateMutability: 'payable'
}

A state changing function such as 'transfer(address,uint256)' - selector 0xa9059cbb

On some contracts this will return:

{
  type: 'function',
  selector: '0xa9059cbb',
  payable: true,
  stateMutability: 'payable',
  inputs: [ { type: 'bytes' } ]
}

Whereas on others it will return:

{
  type: 'function',
  selector: '0xa9059cbb',
  payable: false,
  stateMutability: 'view',
  outputs: [ { type: 'bytes' } ],
  inputs: [ { type: 'bytes' } ]
}

Example contracts returning all payable: true stateMutability: 'payable' functions:
WETH https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
USDT - https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#code
Uniswap V2 Pairs - https://etherscan.io/address/0xd6c6c8f05856dc0a9dad7e69d0a704481447bf15#code
1Inch - https://etherscan.io/token/0x111111111117dc0aa78b770fa6a738034120c302
BLUR - https://etherscan.io/token/0x5283D291DBCF85356A21bA090E6db59121208b44

Example random contracts returning all payable: false stateMutability: 'view' functions:
https://etherscan.io/address/0x98497389acc3014148352f1a01fb9cf0caf44d91
https://etherscan.io/token/0x54cf61c200985678456824f46d4e5125d6f6b440

Code used to test with the 'name()' function (provider is an ethers JSON RPC Provider):

const bytecode = await provider.getCode(address)

const abi = whatsabi.abiFromBytecode(bytecode)

const nameFunction Only = abi.find((res) => res.selector === "0x06fdde03");

console.log(nameFunction)

Add cli tool to package

Thx for creating such an incredibly useful tool. I'm hoping if it's possible to have a command line version?

feature req: pull addresses from bytecode

just found this repo so gonna see if i can help with a PR but it would be awesome if this tool could also pull addresses from bytecode. im guessing we need the PUSH20 opcode and maybe some other jazz.

thanks :)

Add an example env

Would be helpful to have an example env file for running the tests during development.

refactor: Add more types and make peer library agnostic

We could benefit from an Address type, Selector type, and maybe a Bytecode type.

Would also love to make ethers.js dependency optional (related: #36), but this means using import { keccak_256 } from "@noble/hashes/sha3" directly for hashing, and would need write our own hexlify and such. Not a huge amount of work, probably worth it to reduce barrier to adoption.

Should do this before v1.0.

Some contracts return [0x00000001, 0x00000002] selectors

Ie this one 0xD5D1FB5835651C80Ead387A75bD04611e8B3aD52

const { whatsabi } = require("@shazow/whatsabi");

const selectors = whatsabi.selectorsFromBytecode("0x....");
console.log(JSON.stringify(selectors))

Prints
["0x00000001","0x00000002"]

feature: Add stateMutability

is there any way to get the stateMutability of a function whether it is view or nonpayable just like in standard abi?

buffer does not contain relative step

I'm getting this error:buffer does not contain relative step when trying to get selectors for Ethereum contract at 0x37c6e59e1ae39d81828db1a8e8233d6b2afcb9a8

Minimal code to reproduce the problem:

const whatsabi = require("@shazow/whatsabi")
let bytecode = '0x5b602960346000f073032be5d2772329c11a72dadb32ce03806bb26f0a3160005760006000600060003031335af15060006000f36000600060206000600073032be5d2772329c11a72dadb32ce03806bb26f0a5a6069600052f15033ff'
let selectors = whatsabi.selectorsFromBytecode(bytecode)

Errors:

> let selectors = whatsabi.selectorsFromBytecode(bytecode)
Uncaught Error: buffer does not contain relative step
    at BytecodeIter.asPos (/root/go/src/github.com/colorfulnotion/evm-etl/node_modules/@shazow/whatsabi/lib/disasm.js:67:23)
    at BytecodeIter.at (/root/go/src/github.com/colorfulnotion/evm-etl/node_modules/@shazow/whatsabi/lib/disasm.js:76:26)
    at disasm (/root/go/src/github.com/colorfulnotion/evm-etl/node_modules/@shazow/whatsabi/lib/disasm.js:213:44)
    at abiFromBytecode (/root/go/src/github.com/colorfulnotion/evm-etl/node_modules/@shazow/whatsabi/lib/disasm.js:136:15)
    at Object.selectorsFromBytecode (/root/go/src/github.com/colorfulnotion/evm-etl/node_modules/@shazow/whatsabi/lib/selectors.js:22:46)
> 

Any helps?

Two bugs we encountered during our usage

  1. ethers V6 doesn't have getStorageAt function, need to change it to getStorage;
  2. ethers V6 doesn't have the ethers.providers.InfuraProvider class, it has been moved to ethers.InfuraProvider.

disasm: Consider using evmole as an optional backend?

evmole is doing great work at extracting selectors and guessing arguments.

  • The implementation is fairly small and efficient, so it wouldn't add a lot of overhead to whatsabi. (Much smaller impact than sevm, #31)
  • It has a minimal EVM implementation focused specifically for extracting the data we care about, which was out of scope for whatsabi's approach (though I'm increasingly more convinced it's not a bad idea).
  • Could start as an optional peer dependency, and if it works well we can make it the main backend over time, reduce the maintenance burden on whatsabi, allowing us to focus more on other developer UX (proxies, loaders, etc).
  • I'm not sure we can entirely abandon whatsabi's static analysis, since we still need parts of it for proxy detection and other analysis I want to do in the future, maybe some upstream changes would be possible. Not sure yet.

cc @cdump -- do you have any thoughts/feelings about this?

Improve selector detection

There are some cases where we fail to capture a selector:

One possible approach is to detect the "jump table" section of the bytecode, which is (always?) at the beginning, possibly before the first JUMPDEST (is that true?) and after the constructor section (runtime offset is near the beginning too).

At minimum this would be much more efficient at getting the initial jump table without the JUMPDEST verification.

autoload: Don't override verified results

Right now there's a dumb merge function that combines bytecode results with API-fetched results (when available). Would be better to just leave the API-fetched results alone when available.

disasm: Track dynamic jumps

Right now we're only tracking static jumps (ie. where arguments to JUMP/JUMPI are hardcoded in the immediately preceding instructions, rather than ones that exist on the stack from earlier contexts).

Blocked by #26

Option to call etherscan's `getsourcecode` instead of `getabi`

Would love to see an option to call getsourcecode in the Etherscan loader. Helpful for retrieving the contract name + other metadata (as well as the abi).

Happy to contribute to a PR if this is a welcomed feature.

Sample response for getsourcecode:

{
   "status":"1",
   "message":"OK",
   "result":[
      {
         "SourceCode":"/*\n\n- Bytecode Verification performed was compared on second iteration -\n\nThis file is part of the DAO.\n\nThe DAO is free software: you can redistribute it and/or modify\nit under the terms of the GNU lesser General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThe DAO is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU lesser General Public License for more details.\n\nYou should have received a copy of the GNU lesser General Public License\nalong with the DAO.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*\nBasic, standardized Token contract with no \"premine\". Defines the functions to\ncheck token balances, send tokens, send tokens on behalf of a 3rd party and the\ncorresponding approval process. Tokens need to be created by a derived\ncontract (e.g. TokenCreation.sol).\n\nThank you ConsenSys, this contract originated from:\nhttps://github.com/ConsenSys/Tokens/blob/master/Token_Contracts/contracts/Standard_Token.sol\nWhich is itself based on the Ethereum standardized contract APIs:\nhttps://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs\n*/\n\n/// @title Standard Token Contract.\n\ncontract TokenInterface {\n    mapping (address => uint256) balances;\n    mapping (address => mapping (address => uint256)) allowed;\n\n    /// Total amount of tokens\n    uint256 public totalSupply;\n\n    /// @param _owner The address from which the balance will be retrieved\n    /// @return The balance\n    function balanceOf(address _owner) constant returns (uint256 balance);\n\n    /// @notice Send `_amount` tokens to `_to` from `msg.sender`\n    /// @param _to The address of the recipient\n    /// @param _amount The amount of tokens to be transferred\n    /// @return Whether the transfer was successful or not\n    function transfer(address _to, uint256 _amount) returns (bool success);\n\n    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it\n    /// is approved by `_from`\n    /// @param _from The address of the origin of the transfer\n    /// @param _to The address of the recipient\n    /// @param _amount The amount of tokens to be transferred\n    /// @return Whether the transfer was successful or not\n    function transferFrom(address _from, address _to, uint256 _amount) returns (bool success);\n\n    /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on\n    /// its behalf\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @param _amount The amount of tokens to be approved for transfer\n    /// @return Whether the approval was successful or not\n    function approve(address _spender, uint256 _amount) returns (bool success);\n\n    /// @param _owner The address of the account owning tokens\n    /// @param _spender The address of the account able to transfer the tokens\n    /// @return Amount of remaining tokens of _owner that _spender is allowed\n    /// to spend\n    function allowance(\n        address _owner,\n        address _spender\n    ) constant returns (uint256 remaining);\n\n    event Transfer(address indexed _from, address indexed _to, uint256 _amount);\n    event Approval(\n        address indexed _owner,\n        address indexed _spender,\n        uint256 _amount\n    );\n}\n\n\ncontract Token is TokenInterface {\n    // Protects users by preventing the execution of method calls that\n    // inadvertently also transferred ether\n    modifier noEther() {if (msg.value > 0) throw; _}\n\n    function balanceOf(address _owner) constant returns (uint256 balance) {\n        return balances[_owner];\n    }\n\n    function transfer(address _to, uint256 _amount) noEther returns (bool success) {\n        if (balances[msg.sender] >= _amount && _amount > 0) {\n            balances[msg.sender] -= _amount;\n            balances[_to] += _amount;\n            Transfer(msg.sender, _to, _amount);\n            return true;\n        } else {\n           return false;\n        }\n    }\n\n    function transferFrom(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) noEther returns (bool success) {\n\n        if (balances[_from] >= _amount\n            && allowed[_from][msg.sender] >= _amount\n            && _amount > 0) {\n\n            balances[_to] += _amount;\n            balances[_from] -= _amount;\n            allowed[_from][msg.sender] -= _amount;\n            Transfer(_from, _to, _amount);\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    function approve(address _spender, uint256 _amount) returns (bool success) {\n        allowed[msg.sender][_spender] = _amount;\n        Approval(msg.sender, _spender, _amount);\n        return true;\n    }\n\n    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {\n        return allowed[_owner][_spender];\n    }\n}\n\n\n/*\nThis file is part of the DAO.\n\nThe DAO is free software: you can redistribute it and/or modify\nit under the terms of the GNU lesser General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThe DAO is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU lesser General Public License for more details.\n\nYou should have received a copy of the GNU lesser General Public License\nalong with the DAO.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*\nBasic account, used by the DAO contract to separately manage both the rewards \nand the extraBalance accounts. \n*/\n\ncontract ManagedAccountInterface {\n    // The only address with permission to withdraw from this account\n    address public owner;\n    // If true, only the owner of the account can receive ether from it\n    bool public payOwnerOnly;\n    // The sum of ether (in wei) which has been sent to this contract\n    uint public accumulatedInput;\n\n    /// @notice Sends `_amount` of wei to _recipient\n    /// @param _amount The amount of wei to send to `_recipient`\n    /// @param _recipient The address to receive `_amount` of wei\n    /// @return True if the send completed\n    function payOut(address _recipient, uint _amount) returns (bool);\n\n    event PayOut(address indexed _recipient, uint _amount);\n}\n\n\ncontract ManagedAccount is ManagedAccountInterface{\n\n    // The constructor sets the owner of the account\n    function ManagedAccount(address _owner, bool _payOwnerOnly) {\n        owner = _owner;\n        payOwnerOnly = _payOwnerOnly;\n    }\n\n    // When the contract receives a transaction without data this is called. \n    // It counts the amount of ether it receives and stores it in \n    // accumulatedInput.\n    function() {\n        accumulatedInput += msg.value;\n    }\n\n    function payOut(address _recipient, uint _amount) returns (bool) {\n        if (msg.sender != owner || msg.value > 0 || (payOwnerOnly && _recipient != owner))\n            throw;\n        if (_recipient.call.value(_amount)()) {\n            PayOut(_recipient, _amount);\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n/*\nThis file is part of the DAO.\n\nThe DAO is free software: you can redistribute it and/or modify\nit under the terms of the GNU lesser General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThe DAO is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU lesser General Public License for more details.\n\nYou should have received a copy of the GNU lesser General Public License\nalong with the DAO.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*\n * Token Creation contract, used by the DAO to create its tokens and initialize\n * its ether. Feel free to modify the divisor method to implement different\n * Token Creation parameters\n*/\n\n\ncontract TokenCreationInterface {\n\n    // End of token creation, in Unix time\n    uint public closingTime;\n    // Minimum fueling goal of the token creation, denominated in tokens to\n    // be created\n    uint public minTokensToCreate;\n    // True if the DAO reached its minimum fueling goal, false otherwise\n    bool public isFueled;\n    // For DAO splits - if privateCreation is 0, then it is a public token\n    // creation, otherwise only the address stored in privateCreation is\n    // allowed to create tokens\n    address public privateCreation;\n    // hold extra ether which has been sent after the DAO token\n    // creation rate has increased\n    ManagedAccount public extraBalance;\n    // tracks the amount of wei given from each contributor (used for refund)\n    mapping (address => uint256) weiGiven;\n\n    /// @dev Constructor setting the minimum fueling goal and the\n    /// end of the Token Creation\n    /// @param _minTokensToCreate Minimum fueling goal in number of\n    ///        Tokens to be created\n    /// @param _closingTime Date (in Unix time) of the end of the Token Creation\n    /// @param _privateCreation Zero means that the creation is public.  A\n    /// non-zero address represents the only address that can create Tokens\n    /// (the address can also create Tokens on behalf of other accounts)\n    // This is the constructor: it can not be overloaded so it is commented out\n    //  function TokenCreation(\n        //  uint _minTokensTocreate,\n        //  uint _closingTime,\n        //  address _privateCreation\n    //  );\n\n    /// @notice Create Token with `_tokenHolder` as the initial owner of the Token\n    /// @param _tokenHolder The address of the Tokens's recipient\n    /// @return Whether the token creation was successful\n    function createTokenProxy(address _tokenHolder) returns (bool success);\n\n    /// @notice Refund `msg.sender` in the case the Token Creation did\n    /// not reach its minimum fueling goal\n    function refund();\n\n    /// @return The divisor used to calculate the token creation rate during\n    /// the creation phase\n    function divisor() constant returns (uint divisor);\n\n    event FuelingToDate(uint value);\n    event CreatedToken(address indexed to, uint amount);\n    event Refund(address indexed to, uint value);\n}\n\n\ncontract TokenCreation is TokenCreationInterface, Token {\n    function TokenCreation(\n        uint _minTokensToCreate,\n        uint _closingTime,\n        address _privateCreation) {\n\n        closingTime = _closingTime;\n        minTokensToCreate = _minTokensToCreate;\n        privateCreation = _privateCreation;\n        extraBalance = new ManagedAccount(address(this), true);\n    }\n\n    function createTokenProxy(address _tokenHolder) returns (bool success) {\n        if (now < closingTime && msg.value > 0\n            && (privateCreation == 0 || privateCreation == msg.sender)) {\n\n            uint token = (msg.value * 20) / divisor();\n            extraBalance.call.value(msg.value - token)();\n            balances[_tokenHolder] += token;\n            totalSupply += token;\n            weiGiven[_tokenHolder] += msg.value;\n            CreatedToken(_tokenHolder, token);\n            if (totalSupply >= minTokensToCreate && !isFueled) {\n                isFueled = true;\n                FuelingToDate(totalSupply);\n            }\n            return true;\n        }\n        throw;\n    }\n\n    function refund() noEther {\n        if (now > closingTime && !isFueled) {\n            // Get extraBalance - will only succeed when called for the first time\n            if (extraBalance.balance >= extraBalance.accumulatedInput())\n                extraBalance.payOut(address(this), extraBalance.accumulatedInput());\n\n            // Execute refund\n            if (msg.sender.call.value(weiGiven[msg.sender])()) {\n                Refund(msg.sender, weiGiven[msg.sender]);\n                totalSupply -= balances[msg.sender];\n                balances[msg.sender] = 0;\n                weiGiven[msg.sender] = 0;\n            }\n        }\n    }\n\n    function divisor() constant returns (uint divisor) {\n        // The number of (base unit) tokens per wei is calculated\n        // as `msg.value` * 20 / `divisor`\n        // The fueling period starts with a 1:1 ratio\n        if (closingTime - 2 weeks > now) {\n            return 20;\n        // Followed by 10 days with a daily creation rate increase of 5%\n        } else if (closingTime - 4 days > now) {\n            return (20 + (now - (closingTime - 2 weeks)) / (1 days));\n        // The last 4 days there is a constant creation rate ratio of 1:1.5\n        } else {\n            return 30;\n        }\n    }\n}\n/*\nThis file is part of the DAO.\n\nThe DAO is free software: you can redistribute it and/or modify\nit under the terms of the GNU lesser General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThe DAO is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU lesser General Public License for more details.\n\nYou should have received a copy of the GNU lesser General Public License\nalong with the DAO.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n\n/*\nStandard smart contract for a Decentralized Autonomous Organization (DAO)\nto automate organizational governance and decision-making.\n*/\n\n\ncontract DAOInterface {\n\n    // The amount of days for which people who try to participate in the\n    // creation by calling the fallback function will still get their ether back\n    uint constant creationGracePeriod = 40 days;\n    // The minimum debate period that a generic proposal can have\n    uint constant minProposalDebatePeriod = 2 weeks;\n    // The minimum debate period that a split proposal can have\n    uint constant minSplitDebatePeriod = 1 weeks;\n    // Period of days inside which it's possible to execute a DAO split\n    uint constant splitExecutionPeriod = 27 days;\n    // Period of time after which the minimum Quorum is halved\n    uint constant quorumHalvingPeriod = 25 weeks;\n    // Period after which a proposal is closed\n    // (used in the case `executeProposal` fails because it throws)\n    uint constant executeProposalPeriod = 10 days;\n    // Denotes the maximum proposal deposit that can be given. It is given as\n    // a fraction of total Ether spent plus balance of the DAO\n    uint constant maxDepositDivisor = 100;\n\n    // Proposals to spend the DAO's ether or to choose a new Curator\n    Proposal[] public proposals;\n    // The quorum needed for each proposal is partially calculated by\n    // totalSupply / minQuorumDivisor\n    uint public minQuorumDivisor;\n    // The unix time of the last time quorum was reached on a proposal\n    uint  public lastTimeMinQuorumMet;\n\n    // Address of the curator\n    address public curator;\n    // The whitelist: List of addresses the DAO is allowed to send ether to\n    mapping (address => bool) public allowedRecipients;\n\n    // Tracks the addresses that own Reward Tokens. Those addresses can only be\n    // DAOs that have split from the original DAO. Conceptually, Reward Tokens\n    // represent the proportion of the rewards that the DAO has the right to\n    // receive. These Reward Tokens are generated when the DAO spends ether.\n    mapping (address => uint) public rewardToken;\n    // Total supply of rewardToken\n    uint public totalRewardToken;\n\n    // The account used to manage the rewards which are to be distributed to the\n    // DAO Token Holders of this DAO\n    ManagedAccount public rewardAccount;\n\n    // The account used to manage the rewards which are to be distributed to\n    // any DAO that holds Reward Tokens\n    ManagedAccount public DAOrewardAccount;\n\n    // Amount of rewards (in wei) already paid out to a certain DAO\n    mapping (address => uint) public DAOpaidOut;\n\n    // Amount of rewards (in wei) already paid out to a certain address\n    mapping (address => uint) public paidOut;\n    // Map of addresses blocked during a vote (not allowed to transfer DAO\n    // tokens). The address points to the proposal ID.\n    mapping (address => uint) public blocked;\n\n    // The minimum deposit (in wei) required to submit any proposal that is not\n    // requesting a new Curator (no deposit is required for splits)\n    uint public proposalDeposit;\n\n    // the accumulated sum of all current proposal deposits\n    uint sumOfProposalDeposits;\n\n    // Contract that is able to create a new DAO (with the same code as\n    // this one), used for splits\n    DAO_Creator public daoCreator;\n\n    // A proposal with `newCurator == false` represents a transaction\n    // to be issued by this DAO\n    // A proposal with `newCurator == true` represents a DAO split\n    struct Proposal {\n        // The address where the `amount` will go to if the proposal is accepted\n        // or if `newCurator` is true, the proposed Curator of\n        // the new DAO).\n        address recipient;\n        // The amount to transfer to `recipient` if the proposal is accepted.\n        uint amount;\n        // A plain text description of the proposal\n        string description;\n        // A unix timestamp, denoting the end of the voting period\n        uint votingDeadline;\n        // True if the proposal's votes have yet to be counted, otherwise False\n        bool open;\n        // True if quorum has been reached, the votes have been counted, and\n        // the majority said yes\n        bool proposalPassed;\n        // A hash to check validity of a proposal\n        bytes32 proposalHash;\n        // Deposit in wei the creator added when submitting their proposal. It\n        // is taken from the msg.value of a newProposal call.\n        uint proposalDeposit;\n        // True if this proposal is to assign a new Curator\n        bool newCurator;\n        // Data needed for splitting the DAO\n        SplitData[] splitData;\n        // Number of Tokens in favor of the proposal\n        uint yea;\n        // Number of Tokens opposed to the proposal\n        uint nay;\n        // Simple mapping to check if a shareholder has voted for it\n        mapping (address => bool) votedYes;\n        // Simple mapping to check if a shareholder has voted against it\n        mapping (address => bool) votedNo;\n        // Address of the shareholder who created the proposal\n        address creator;\n    }\n\n    // Used only in the case of a newCurator proposal.\n    struct SplitData {\n        // The balance of the current DAO minus the deposit at the time of split\n        uint splitBalance;\n        // The total amount of DAO Tokens in existence at the time of split.\n        uint totalSupply;\n        // Amount of Reward Tokens owned by the DAO at the time of split.\n        uint rewardToken;\n        // The new DAO contract created at the time of split.\n        DAO newDAO;\n    }\n\n    // Used to restrict access to certain functions to only DAO Token Holders\n    modifier onlyTokenholders {}\n\n    /// @dev Constructor setting the Curator and the address\n    /// for the contract able to create another DAO as well as the parameters\n    /// for the DAO Token Creation\n    /// @param _curator The Curator\n    /// @param _daoCreator The contract able to (re)create this DAO\n    /// @param _proposalDeposit The deposit to be paid for a regular proposal\n    /// @param _minTokensToCreate Minimum required wei-equivalent tokens\n    ///        to be created for a successful DAO Token Creation\n    /// @param _closingTime Date (in Unix time) of the end of the DAO Token Creation\n    /// @param _privateCreation If zero the DAO Token Creation is open to public, a\n    /// non-zero address means that the DAO Token Creation is only for the address\n    // This is the constructor: it can not be overloaded so it is commented out\n    //  function DAO(\n        //  address _curator,\n        //  DAO_Creator _daoCreator,\n        //  uint _proposalDeposit,\n        //  uint _minTokensToCreate,\n        //  uint _closingTime,\n        //  address _privateCreation\n    //  );\n\n    /// @notice Create Token with `msg.sender` as the beneficiary\n    /// @return Whether the token creation was successful\n    function () returns (bool success);\n\n\n    /// @dev This function is used to send ether back\n    /// to the DAO, it can also be used to receive payments that should not be\n    /// counted as rewards (donations, grants, etc.)\n    /// @return Whether the DAO received the ether successfully\n    function receiveEther() returns(bool);\n\n    /// @notice `msg.sender` creates a proposal to send `_amount` Wei to\n    /// `_recipient` with the transaction data `_transactionData`. If\n    /// `_newCurator` is true, then this is a proposal that splits the\n    /// DAO and sets `_recipient` as the new DAO's Curator.\n    /// @param _recipient Address of the recipient of the proposed transaction\n    /// @param _amount Amount of wei to be sent with the proposed transaction\n    /// @param _description String describing the proposal\n    /// @param _transactionData Data of the proposed transaction\n    /// @param _debatingPeriod Time used for debating a proposal, at least 2\n    /// weeks for a regular proposal, 10 days for new Curator proposal\n    /// @param _newCurator Bool defining whether this proposal is about\n    /// a new Curator or not\n    /// @return The proposal ID. Needed for voting on the proposal\n    function newProposal(\n        address _recipient,\n        uint _amount,\n        string _description,\n        bytes _transactionData,\n        uint _debatingPeriod,\n        bool _newCurator\n    ) onlyTokenholders returns (uint _proposalID);\n\n    /// @notice Check that the proposal with the ID `_proposalID` matches the\n    /// transaction which sends `_amount` with data `_transactionData`\n    /// to `_recipient`\n    /// @param _proposalID The proposal ID\n    /// @param _recipient The recipient of the proposed transaction\n    /// @param _amount The amount of wei to be sent in the proposed transaction\n    /// @param _transactionData The data of the proposed transaction\n    /// @return Whether the proposal ID matches the transaction data or not\n    function checkProposalCode(\n        uint _proposalID,\n        address _recipient,\n        uint _amount,\n        bytes _transactionData\n    ) constant returns (bool _codeChecksOut);\n\n    /// @notice Vote on proposal `_proposalID` with `_supportsProposal`\n    /// @param _proposalID The proposal ID\n    /// @param _supportsProposal Yes/No - support of the proposal\n    /// @return The vote ID.\n    function vote(\n        uint _proposalID,\n        bool _supportsProposal\n    ) onlyTokenholders returns (uint _voteID);\n\n    /// @notice Checks whether proposal `_proposalID` with transaction data\n    /// `_transactionData` has been voted for or rejected, and executes the\n    /// transaction in the case it has been voted for.\n    /// @param _proposalID The proposal ID\n    /// @param _transactionData The data of the proposed transaction\n    /// @return Whether the proposed transaction has been executed or not\n    function executeProposal(\n        uint _proposalID,\n        bytes _transactionData\n    ) returns (bool _success);\n\n    /// @notice ATTENTION! I confirm to move my remaining ether to a new DAO\n    /// with `_newCurator` as the new Curator, as has been\n    /// proposed in proposal `_proposalID`. This will burn my tokens. This can\n    /// not be undone and will split the DAO into two DAO's, with two\n    /// different underlying tokens.\n    /// @param _proposalID The proposal ID\n    /// @param _newCurator The new Curator of the new DAO\n    /// @dev This function, when called for the first time for this proposal,\n    /// will create a new DAO and send the sender's portion of the remaining\n    /// ether and Reward Tokens to the new DAO. It will also burn the DAO Tokens\n    /// of the sender.\n    function splitDAO(\n        uint _proposalID,\n        address _newCurator\n    ) returns (bool _success);\n\n    /// @dev can only be called by the DAO itself through a proposal\n    /// updates the contract of the DAO by sending all ether and rewardTokens\n    /// to the new DAO. The new DAO needs to be approved by the Curator\n    /// @param _newContract the address of the new contract\n    function newContract(address _newContract);\n\n\n    /// @notice Add a new possible recipient `_recipient` to the whitelist so\n    /// that the DAO can send transactions to them (using proposals)\n    /// @param _recipient New recipient address\n    /// @dev Can only be called by the current Curator\n    /// @return Whether successful or not\n    function changeAllowedRecipients(address _recipient, bool _allowed) external returns (bool _success);\n\n\n    /// @notice Change the minimum deposit required to submit a proposal\n    /// @param _proposalDeposit The new proposal deposit\n    /// @dev Can only be called by this DAO (through proposals with the\n    /// recipient being this DAO itself)\n    function changeProposalDeposit(uint _proposalDeposit) external;\n\n    /// @notice Move rewards from the DAORewards managed account\n    /// @param _toMembers If true rewards are moved to the actual reward account\n    ///                   for the DAO. If not then it's moved to the DAO itself\n    /// @return Whether the call was successful\n    function retrieveDAOReward(bool _toMembers) external returns (bool _success);\n\n    /// @notice Get my portion of the reward that was sent to `rewardAccount`\n    /// @return Whether the call was successful\n    function getMyReward() returns(bool _success);\n\n    /// @notice Withdraw `_account`'s portion of the reward from `rewardAccount`\n    /// to `_account`'s balance\n    /// @return Whether the call was successful\n    function withdrawRewardFor(address _account) internal returns (bool _success);\n\n    /// @notice Send `_amount` tokens to `_to` from `msg.sender`. Prior to this\n    /// getMyReward() is called.\n    /// @param _to The address of the recipient\n    /// @param _amount The amount of tokens to be transfered\n    /// @return Whether the transfer was successful or not\n    function transferWithoutReward(address _to, uint256 _amount) returns (bool success);\n\n    /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it\n    /// is approved by `_from`. Prior to this getMyReward() is called.\n    /// @param _from The address of the sender\n    /// @param _to The address of the recipient\n    /// @param _amount The amount of tokens to be transfered\n    /// @return Whether the transfer was successful or not\n    function transferFromWithoutReward(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) returns (bool success);\n\n    /// @notice Doubles the 'minQuorumDivisor' in the case quorum has not been\n    /// achieved in 52 weeks\n    /// @return Whether the change was successful or not\n    function halveMinQuorum() returns (bool _success);\n\n    /// @return total number of proposals ever created\n    function numberOfProposals() constant returns (uint _numberOfProposals);\n\n    /// @param _proposalID Id of the new curator proposal\n    /// @return Address of the new DAO\n    function getNewDAOAddress(uint _proposalID) constant returns (address _newDAO);\n\n    /// @param _account The address of the account which is checked.\n    /// @return Whether the account is blocked (not allowed to transfer tokens) or not.\n    function isBlocked(address _account) internal returns (bool);\n\n    /// @notice If the caller is blocked by a proposal whose voting deadline\n    /// has exprired then unblock him.\n    /// @return Whether the account is blocked (not allowed to transfer tokens) or not.\n    function unblockMe() returns (bool);\n\n    event ProposalAdded(\n        uint indexed proposalID,\n        address recipient,\n        uint amount,\n        bool newCurator,\n        string description\n    );\n    event Voted(uint indexed proposalID, bool position, address indexed voter);\n    event ProposalTallied(uint indexed proposalID, bool result, uint quorum);\n    event NewCurator(address indexed _newCurator);\n    event AllowedRecipientChanged(address indexed _recipient, bool _allowed);\n}\n\n// The DAO contract itself\ncontract DAO is DAOInterface, Token, TokenCreation {\n\n    // Modifier that allows only shareholders to vote and create new proposals\n    modifier onlyTokenholders {\n        if (balanceOf(msg.sender) == 0) throw;\n            _\n    }\n\n    function DAO(\n        address _curator,\n        DAO_Creator _daoCreator,\n        uint _proposalDeposit,\n        uint _minTokensToCreate,\n        uint _closingTime,\n        address _privateCreation\n    ) TokenCreation(_minTokensToCreate, _closingTime, _privateCreation) {\n\n        curator = _curator;\n        daoCreator = _daoCreator;\n        proposalDeposit = _proposalDeposit;\n        rewardAccount = new ManagedAccount(address(this), false);\n        DAOrewardAccount = new ManagedAccount(address(this), false);\n        if (address(rewardAccount) == 0)\n            throw;\n        if (address(DAOrewardAccount) == 0)\n            throw;\n        lastTimeMinQuorumMet = now;\n        minQuorumDivisor = 5; // sets the minimal quorum to 20%\n        proposals.length = 1; // avoids a proposal with ID 0 because it is used\n\n        allowedRecipients[address(this)] = true;\n        allowedRecipients[curator] = true;\n    }\n\n    function () returns (bool success) {\n        if (now < closingTime + creationGracePeriod && msg.sender != address(extraBalance))\n            return createTokenProxy(msg.sender);\n        else\n            return receiveEther();\n    }\n\n\n    function receiveEther() returns (bool) {\n        return true;\n    }\n\n\n    function newProposal(\n        address _recipient,\n        uint _amount,\n        string _description,\n        bytes _transactionData,\n        uint _debatingPeriod,\n        bool _newCurator\n    ) onlyTokenholders returns (uint _proposalID) {\n\n        // Sanity check\n        if (_newCurator && (\n            _amount != 0\n            || _transactionData.length != 0\n            || _recipient == curator\n            || msg.value > 0\n            || _debatingPeriod < minSplitDebatePeriod)) {\n            throw;\n        } else if (\n            !_newCurator\n            && (!isRecipientAllowed(_recipient) || (_debatingPeriod <  minProposalDebatePeriod))\n        ) {\n            throw;\n        }\n\n        if (_debatingPeriod > 8 weeks)\n            throw;\n\n        if (!isFueled\n            || now < closingTime\n            || (msg.value < proposalDeposit && !_newCurator)) {\n\n            throw;\n        }\n\n        if (now + _debatingPeriod < now) // prevents overflow\n            throw;\n\n        // to prevent a 51% attacker to convert the ether into deposit\n        if (msg.sender == address(this))\n            throw;\n\n        _proposalID = proposals.length++;\n        Proposal p = proposals[_proposalID];\n        p.recipient = _recipient;\n        p.amount = _amount;\n        p.description = _description;\n        p.proposalHash = sha3(_recipient, _amount, _transactionData);\n        p.votingDeadline = now + _debatingPeriod;\n        p.open = true;\n        //p.proposalPassed = False; // that's default\n        p.newCurator = _newCurator;\n        if (_newCurator)\n            p.splitData.length++;\n        p.creator = msg.sender;\n        p.proposalDeposit = msg.value;\n\n        sumOfProposalDeposits += msg.value;\n\n        ProposalAdded(\n            _proposalID,\n            _recipient,\n            _amount,\n            _newCurator,\n            _description\n        );\n    }\n\n\n    function checkProposalCode(\n        uint _proposalID,\n        address _recipient,\n        uint _amount,\n        bytes _transactionData\n    ) noEther constant returns (bool _codeChecksOut) {\n        Proposal p = proposals[_proposalID];\n        return p.proposalHash == sha3(_recipient, _amount, _transactionData);\n    }\n\n\n    function vote(\n        uint _proposalID,\n        bool _supportsProposal\n    ) onlyTokenholders noEther returns (uint _voteID) {\n\n        Proposal p = proposals[_proposalID];\n        if (p.votedYes[msg.sender]\n            || p.votedNo[msg.sender]\n            || now >= p.votingDeadline) {\n\n            throw;\n        }\n\n        if (_supportsProposal) {\n            p.yea += balances[msg.sender];\n            p.votedYes[msg.sender] = true;\n        } else {\n            p.nay += balances[msg.sender];\n            p.votedNo[msg.sender] = true;\n        }\n\n        if (blocked[msg.sender] == 0) {\n            blocked[msg.sender] = _proposalID;\n        } else if (p.votingDeadline > proposals[blocked[msg.sender]].votingDeadline) {\n            // this proposal's voting deadline is further into the future than\n            // the proposal that blocks the sender so make it the blocker\n            blocked[msg.sender] = _proposalID;\n        }\n\n        Voted(_proposalID, _supportsProposal, msg.sender);\n    }\n\n\n    function executeProposal(\n        uint _proposalID,\n        bytes _transactionData\n    ) noEther returns (bool _success) {\n\n        Proposal p = proposals[_proposalID];\n\n        uint waitPeriod = p.newCurator\n            ? splitExecutionPeriod\n            : executeProposalPeriod;\n        // If we are over deadline and waiting period, assert proposal is closed\n        if (p.open && now > p.votingDeadline + waitPeriod) {\n            closeProposal(_proposalID);\n            return;\n        }\n\n        // Check if the proposal can be executed\n        if (now < p.votingDeadline  // has the voting deadline arrived?\n            // Have the votes been counted?\n            || !p.open\n            // Does the transaction code match the proposal?\n            || p.proposalHash != sha3(p.recipient, p.amount, _transactionData)) {\n\n            throw;\n        }\n\n        // If the curator removed the recipient from the whitelist, close the proposal\n        // in order to free the deposit and allow unblocking of voters\n        if (!isRecipientAllowed(p.recipient)) {\n            closeProposal(_proposalID);\n            p.creator.send(p.proposalDeposit);\n            return;\n        }\n\n        bool proposalCheck = true;\n\n        if (p.amount > actualBalance())\n            proposalCheck = false;\n\n        uint quorum = p.yea + p.nay;\n\n        // require 53% for calling newContract()\n        if (_transactionData.length >= 4 && _transactionData[0] == 0x68\n            && _transactionData[1] == 0x37 && _transactionData[2] == 0xff\n            && _transactionData[3] == 0x1e\n            && quorum < minQuorum(actualBalance() + rewardToken[address(this)])) {\n\n                proposalCheck = false;\n        }\n\n        if (quorum >= minQuorum(p.amount)) {\n            if (!p.creator.send(p.proposalDeposit))\n                throw;\n\n            lastTimeMinQuorumMet = now;\n            // set the minQuorum to 20% again, in the case it has been reached\n            if (quorum > totalSupply / 5)\n                minQuorumDivisor = 5;\n        }\n\n        // Execute result\n        if (quorum >= minQuorum(p.amount) && p.yea > p.nay && proposalCheck) {\n            if (!p.recipient.call.value(p.amount)(_transactionData))\n                throw;\n\n            p.proposalPassed = true;\n            _success = true;\n\n            // only create reward tokens when ether is not sent to the DAO itself and\n            // related addresses. Proxy addresses should be forbidden by the curator.\n            if (p.recipient != address(this) && p.recipient != address(rewardAccount)\n                && p.recipient != address(DAOrewardAccount)\n                && p.recipient != address(extraBalance)\n                && p.recipient != address(curator)) {\n\n                rewardToken[address(this)] += p.amount;\n                totalRewardToken += p.amount;\n            }\n        }\n\n        closeProposal(_proposalID);\n\n        // Initiate event\n        ProposalTallied(_proposalID, _success, quorum);\n    }\n\n\n    function closeProposal(uint _proposalID) internal {\n        Proposal p = proposals[_proposalID];\n        if (p.open)\n            sumOfProposalDeposits -= p.proposalDeposit;\n        p.open = false;\n    }\n\n    function splitDAO(\n        uint _proposalID,\n        address _newCurator\n    ) noEther onlyTokenholders returns (bool _success) {\n\n        Proposal p = proposals[_proposalID];\n\n        // Sanity check\n\n        if (now < p.votingDeadline  // has the voting deadline arrived?\n            //The request for a split expires XX days after the voting deadline\n            || now > p.votingDeadline + splitExecutionPeriod\n            // Does the new Curator address match?\n            || p.recipient != _newCurator\n            // Is it a new curator proposal?\n            || !p.newCurator\n            // Have you voted for this split?\n            || !p.votedYes[msg.sender]\n            // Did you already vote on another proposal?\n            || (blocked[msg.sender] != _proposalID && blocked[msg.sender] != 0) )  {\n\n            throw;\n        }\n\n        // If the new DAO doesn't exist yet, create the new DAO and store the\n        // current split data\n        if (address(p.splitData[0].newDAO) == 0) {\n            p.splitData[0].newDAO = createNewDAO(_newCurator);\n            // Call depth limit reached, etc.\n            if (address(p.splitData[0].newDAO) == 0)\n                throw;\n            // should never happen\n            if (this.balance < sumOfProposalDeposits)\n                throw;\n            p.splitData[0].splitBalance = actualBalance();\n            p.splitData[0].rewardToken = rewardToken[address(this)];\n            p.splitData[0].totalSupply = totalSupply;\n            p.proposalPassed = true;\n        }\n\n        // Move ether and assign new Tokens\n        uint fundsToBeMoved =\n            (balances[msg.sender] * p.splitData[0].splitBalance) /\n            p.splitData[0].totalSupply;\n        if (p.splitData[0].newDAO.createTokenProxy.value(fundsToBeMoved)(msg.sender) == false)\n            throw;\n\n\n        // Assign reward rights to new DAO\n        uint rewardTokenToBeMoved =\n            (balances[msg.sender] * p.splitData[0].rewardToken) /\n            p.splitData[0].totalSupply;\n\n        uint paidOutToBeMoved = DAOpaidOut[address(this)] * rewardTokenToBeMoved /\n            rewardToken[address(this)];\n\n        rewardToken[address(p.splitData[0].newDAO)] += rewardTokenToBeMoved;\n        if (rewardToken[address(this)] < rewardTokenToBeMoved)\n            throw;\n        rewardToken[address(this)] -= rewardTokenToBeMoved;\n\n        DAOpaidOut[address(p.splitData[0].newDAO)] += paidOutToBeMoved;\n        if (DAOpaidOut[address(this)] < paidOutToBeMoved)\n            throw;\n        DAOpaidOut[address(this)] -= paidOutToBeMoved;\n\n        // Burn DAO Tokens\n        Transfer(msg.sender, 0, balances[msg.sender]);\n        withdrawRewardFor(msg.sender); // be nice, and get his rewards\n        totalSupply -= balances[msg.sender];\n        balances[msg.sender] = 0;\n        paidOut[msg.sender] = 0;\n        return true;\n    }\n\n    function newContract(address _newContract){\n        if (msg.sender != address(this) || !allowedRecipients[_newContract]) return;\n        // move all ether\n        if (!_newContract.call.value(address(this).balance)()) {\n            throw;\n        }\n\n        //move all reward tokens\n        rewardToken[_newContract] += rewardToken[address(this)];\n        rewardToken[address(this)] = 0;\n        DAOpaidOut[_newContract] += DAOpaidOut[address(this)];\n        DAOpaidOut[address(this)] = 0;\n    }\n\n\n    function retrieveDAOReward(bool _toMembers) external noEther returns (bool _success) {\n        DAO dao = DAO(msg.sender);\n\n        if ((rewardToken[msg.sender] * DAOrewardAccount.accumulatedInput()) /\n            totalRewardToken < DAOpaidOut[msg.sender])\n            throw;\n\n        uint reward =\n            (rewardToken[msg.sender] * DAOrewardAccount.accumulatedInput()) /\n            totalRewardToken - DAOpaidOut[msg.sender];\n        if(_toMembers) {\n            if (!DAOrewardAccount.payOut(dao.rewardAccount(), reward))\n                throw;\n            }\n        else {\n            if (!DAOrewardAccount.payOut(dao, reward))\n                throw;\n        }\n        DAOpaidOut[msg.sender] += reward;\n        return true;\n    }\n\n    function getMyReward() noEther returns (bool _success) {\n        return withdrawRewardFor(msg.sender);\n    }\n\n\n    function withdrawRewardFor(address _account) noEther internal returns (bool _success) {\n        if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])\n            throw;\n\n        uint reward =\n            (balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply - paidOut[_account];\n        if (!rewardAccount.payOut(_account, reward))\n            throw;\n        paidOut[_account] += reward;\n        return true;\n    }\n\n\n    function transfer(address _to, uint256 _value) returns (bool success) {\n        if (isFueled\n            && now > closingTime\n            && !isBlocked(msg.sender)\n            && transferPaidOut(msg.sender, _to, _value)\n            && super.transfer(_to, _value)) {\n\n            return true;\n        } else {\n            throw;\n        }\n    }\n\n\n    function transferWithoutReward(address _to, uint256 _value) returns (bool success) {\n        if (!getMyReward())\n            throw;\n        return transfer(_to, _value);\n    }\n\n\n    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {\n        if (isFueled\n            && now > closingTime\n            && !isBlocked(_from)\n            && transferPaidOut(_from, _to, _value)\n            && super.transferFrom(_from, _to, _value)) {\n\n            return true;\n        } else {\n            throw;\n        }\n    }\n\n\n    function transferFromWithoutReward(\n        address _from,\n        address _to,\n        uint256 _value\n    ) returns (bool success) {\n\n        if (!withdrawRewardFor(_from))\n            throw;\n        return transferFrom(_from, _to, _value);\n    }\n\n\n    function transferPaidOut(\n        address _from,\n        address _to,\n        uint256 _value\n    ) internal returns (bool success) {\n\n        uint transferPaidOut = paidOut[_from] * _value / balanceOf(_from);\n        if (transferPaidOut > paidOut[_from])\n            throw;\n        paidOut[_from] -= transferPaidOut;\n        paidOut[_to] += transferPaidOut;\n        return true;\n    }\n\n\n    function changeProposalDeposit(uint _proposalDeposit) noEther external {\n        if (msg.sender != address(this) || _proposalDeposit > (actualBalance() + rewardToken[address(this)])\n            / maxDepositDivisor) {\n\n            throw;\n        }\n        proposalDeposit = _proposalDeposit;\n    }\n\n\n    function changeAllowedRecipients(address _recipient, bool _allowed) noEther external returns (bool _success) {\n        if (msg.sender != curator)\n            throw;\n        allowedRecipients[_recipient] = _allowed;\n        AllowedRecipientChanged(_recipient, _allowed);\n        return true;\n    }\n\n\n    function isRecipientAllowed(address _recipient) internal returns (bool _isAllowed) {\n        if (allowedRecipients[_recipient]\n            || (_recipient == address(extraBalance)\n                // only allowed when at least the amount held in the\n                // extraBalance account has been spent from the DAO\n                && totalRewardToken > extraBalance.accumulatedInput()))\n            return true;\n        else\n            return false;\n    }\n\n    function actualBalance() constant returns (uint _actualBalance) {\n        return this.balance - sumOfProposalDeposits;\n    }\n\n\n    function minQuorum(uint _value) internal constant returns (uint _minQuorum) {\n        // minimum of 20% and maximum of 53.33%\n        return totalSupply / minQuorumDivisor +\n            (_value * totalSupply) / (3 * (actualBalance() + rewardToken[address(this)]));\n    }\n\n\n    function halveMinQuorum() returns (bool _success) {\n        // this can only be called after `quorumHalvingPeriod` has passed or at anytime\n        // by the curator with a delay of at least `minProposalDebatePeriod` between the calls\n        if ((lastTimeMinQuorumMet < (now - quorumHalvingPeriod) || msg.sender == curator)\n            && lastTimeMinQuorumMet < (now - minProposalDebatePeriod)) {\n            lastTimeMinQuorumMet = now;\n            minQuorumDivisor *= 2;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    function createNewDAO(address _newCurator) internal returns (DAO _newDAO) {\n        NewCurator(_newCurator);\n        return daoCreator.createDAO(_newCurator, 0, 0, now + splitExecutionPeriod);\n    }\n\n    function numberOfProposals() constant returns (uint _numberOfProposals) {\n        // Don't count index 0. It's used by isBlocked() and exists from start\n        return proposals.length - 1;\n    }\n\n    function getNewDAOAddress(uint _proposalID) constant returns (address _newDAO) {\n        return proposals[_proposalID].splitData[0].newDAO;\n    }\n\n    function isBlocked(address _account) internal returns (bool) {\n        if (blocked[_account] == 0)\n            return false;\n        Proposal p = proposals[blocked[_account]];\n        if (now > p.votingDeadline) {\n            blocked[_account] = 0;\n            return false;\n        } else {\n            return true;\n        }\n    }\n\n    function unblockMe() returns (bool) {\n        return isBlocked(msg.sender);\n    }\n}\n\ncontract DAO_Creator {\n    function createDAO(\n        address _curator,\n        uint _proposalDeposit,\n        uint _minTokensToCreate,\n        uint _closingTime\n    ) returns (DAO _newDAO) {\n\n        return new DAO(\n            _curator,\n            DAO_Creator(this),\n            _proposalDeposit,\n            _minTokensToCreate,\n            _closingTime,\n            msg.sender\n        );\n    }\n}\n",
         "ABI":"[{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"proposals\",\"outputs\":[{\"name\":\"recipient\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"votingDeadline\",\"type\":\"uint256\"},{\"name\":\"open\",\"type\":\"bool\"},{\"name\":\"proposalPassed\",\"type\":\"bool\"},{\"name\":\"proposalHash\",\"type\":\"bytes32\"},{\"name\":\"proposalDeposit\",\"type\":\"uint256\"},{\"name\":\"newCurator\",\"type\":\"bool\"},{\"name\":\"yea\",\"type\":\"uint256\"},{\"name\":\"nay\",\"type\":\"uint256\"},{\"name\":\"creator\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minTokensToCreate\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rewardAccount\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"daoCreator\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"divisor\",\"outputs\":[{\"name\":\"divisor\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"extraBalance\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"},{\"name\":\"_transactionData\",\"type\":\"bytes\"}],\"name\":\"executeProposal\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unblockMe\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalRewardToken\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"actualBalance\",\"outputs\":[{\"name\":\"_actualBalance\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"closingTime\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowedRecipients\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferWithoutReward\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"refund\",\"outputs\":[],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\"},{\"name\":\"_amount\",\"type\":\"uint256\"},{\"name\":\"_description\",\"type\":\"string\"},{\"name\":\"_transactionData\",\"type\":\"bytes\"},{\"name\":\"_debatingPeriod\",\"type\":\"uint256\"},{\"name\":\"_newCurator\",\"type\":\"bool\"}],\"name\":\"newProposal\",\"outputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"DAOpaidOut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"minQuorumDivisor\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_newContract\",\"type\":\"address\"}],\"name\":\"newContract\",\"outputs\":[],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_recipient\",\"type\":\"address\"},{\"name\":\"_allowed\",\"type\":\"bool\"}],\"name\":\"changeAllowedRecipients\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"halveMinQuorum\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"paidOut\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"},{\"name\":\"_newCurator\",\"type\":\"address\"}],\"name\":\"splitDAO\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"DAOrewardAccount\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"proposalDeposit\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"numberOfProposals\",\"outputs\":[{\"name\":\"_numberOfProposals\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"lastTimeMinQuorumMet\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_toMembers\",\"type\":\"bool\"}],\"name\":\"retrieveDAOReward\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"receiveEther\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isFueled\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_tokenHolder\",\"type\":\"address\"}],\"name\":\"createTokenProxy\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"}],\"name\":\"getNewDAOAddress\",\"outputs\":[{\"name\":\"_newDAO\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"},{\"name\":\"_supportsProposal\",\"type\":\"bool\"}],\"name\":\"vote\",\"outputs\":[{\"name\":\"_voteID\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"getMyReward\",\"outputs\":[{\"name\":\"_success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardToken\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFromWithoutReward\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_proposalDeposit\",\"type\":\"uint256\"}],\"name\":\"changeProposalDeposit\",\"outputs\":[],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"blocked\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"curator\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_proposalID\",\"type\":\"uint256\"},{\"name\":\"_recipient\",\"type\":\"address\"},{\"name\":\"_amount\",\"type\":\"uint256\"},{\"name\":\"_transactionData\",\"type\":\"bytes\"}],\"name\":\"checkProposalCode\",\"outputs\":[{\"name\":\"_codeChecksOut\",\"type\":\"bool\"}],\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"privateCreation\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"type\":\"function\"},{\"inputs\":[{\"name\":\"_curator\",\"type\":\"address\"},{\"name\":\"_daoCreator\",\"type\":\"address\"},{\"name\":\"_proposalDeposit\",\"type\":\"uint256\"},{\"name\":\"_minTokensToCreate\",\"type\":\"uint256\"},{\"name\":\"_closingTime\",\"type\":\"uint256\"},{\"name\":\"_privateCreation\",\"type\":\"address\"}],\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"FuelingToDate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"CreatedToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Refund\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"proposalID\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"newCurator\",\"type\":\"bool\"},{\"indexed\":false,\"name\":\"description\",\"type\":\"string\"}],\"name\":\"ProposalAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"proposalID\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"position\",\"type\":\"bool\"},{\"indexed\":true,\"name\":\"voter\",\"type\":\"address\"}],\"name\":\"Voted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"proposalID\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"result\",\"type\":\"bool\"},{\"indexed\":false,\"name\":\"quorum\",\"type\":\"uint256\"}],\"name\":\"ProposalTallied\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_newCurator\",\"type\":\"address\"}],\"name\":\"NewCurator\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_recipient\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_allowed\",\"type\":\"bool\"}],\"name\":\"AllowedRecipientChanged\",\"type\":\"event\"}]",
         "ContractName":"DAO",
         "CompilerVersion":"v0.3.1-2016-04-12-3ad5e82",
         "OptimizationUsed":"1",
         "Runs":"200",
         "ConstructorArguments":"000000000000000000000000da4a4626d3e16e094de3225a751aab7128e965260000000000000000000000004a574510c7014e4ae985403536074abe582adfc80000000000000000000000000000000000000000000000001bc16d674ec80000000000000000000000000000000000000000000000000a968163f0a57b4000000000000000000000000000000000000000000000000000000000000057495e100000000000000000000000000000000000000000000000000000000000000000",
         "EVMVersion":"Default",
         "Library":"",
         "LicenseType":"",
         "Proxy":"0",
         "Implementation":"",
         "SwarmSource":""
      }
   ]
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.