Welcome to Eveem.org
Redesign, new features. Let me know if anything breaks.
kolinko@gmail.com
Some fun stuff after 2,513,589 decompiled contracts...
[0]what's new [1]transfers [2]selfdestruct piniata [3]stats
New frontend version # 19 Nov 2019
Switched to a new frontend server. It should work
faster, and hang up less.
Let me know if you see anything break.
Brand new version! # 26th Apr 2019
After two months of intense work, there is now a new
decompiler version, with some heavy changes to the
architecture.
If you notice any new bugs - especially things that
used to work before, but don't now, please e-mail kolinko@gmail.com.
Friday afternoon, pushed to production, now it's time for rest :D
Bugfixes etc # 4th Mar 2019
Busy two weeks, preparing a new architecture that
will handle many functions that fail to decompile now.
As for the small stuff:
- fixed error 500s on website and in API
- better mobile view
- deployed custom bytecode decompiler
- slides on detecting underflows in contracts
Thanks for all the positive feedback everyone,
and for the coverage in Smart Contract Security Newsletter,
Ethereum Weekly, IEEE Spectrum, and all the tweets!
Cool new things # 11th Feb 2019
The biggest web update so far:
- a lot of decompiler fixes (see 6th Feb news)
- support for Ropsten/Rinkeby/Kovan addresses
- a nice display of the JSON format that's geared for automated analysis
- 'Data' section - showing storages that have no getters.
Is Eveem seriously the only place this is easily accessible? :)
- experimental ABI file auto-generation
- disassembly view, because why not
- integrated ~1300 token metadata from the Methadata project
Thanks Namanyay Goel for the design/typography cleanup, and
Ivan On Tech for the coverage!
New version coming soon # 6th Feb 2019
A lot of small fixes coming up. Tested already,
and re-decompiling contracts now.
- better 'while' loop detection
- fixed folder issues
- clean up unnecessary mem writes display
- show calldatacopy etc mem writes when necessary
- various small improvements to prettifier
Support for Ropsten/Rinkeby/Kovan coming soon.
Also, thank you to Michael del Castillo for the Forbes coverage!
Decompiler bugfixes # 24th Jan 2019
- slightly better storage display
- fixed 'create' parsing
- 'call' readability improvements
- code cleanup for open-sourcing Panoramix
- switched website hosting into Google App Engine
- decompiled the remaining contracts, so it's 2.2M altogether now
Binance SAFU hackathon win # 20th Jan 2019
Alexey & Nirmal won Binance SAFU hackathon, using - among other things - Eveem's
bytecode analysis and API to figure out which mainnet contracts are Ponzi schemes.
Eveem's help with Constantinopole # 16th Jan 2019
- received a wonderful 'thank you' in the ChainSecurity article
- found the first contracts that would be affected by the bug
- released a list of contracts that may-be-but-probably-aren't affected
Eveem/BigQuery announcement # 3rd Jan 2019
All the 1.2M decompiled contracts are now in a public BigQuery dataset,
which makes it easy for people to analyse them in bulk and find interesting
patterns.
- Article - Analysing 1.2M mainnet contracts in 20 seconds
- Asterix - example analysis script
Update:
The above was used by ChainSecurity in looking for contracts
potentially affected by the Constantinopole EVM changes.
- A fork of Asterix checking for Reentracy
- Constantinople enables new Reentrancy Attack by ChainSecurity
ShowMe at EthSingapore # 10th Dec 2018
Along with Alexey from Bloxy.info we built a cool tool using Eveem's API.
It uses source codes from Eveem to show fun facts about the smart contracts:
- who are the owners/admins
- who can change them, using which functionality
- what functions can owners/admins call
- what other contracts are referenced by a given one
You can play with the tool here, but above all - check out the sources on GitHub
and build some other analysis tools yourself.
Eveem premiere at Devcon Prague # 30th Oct 2018
This is the day the site has launched.
A first line of decompiler code written # 5th Oct 2018
Most of what you see on this site was created in 4 weeks of crunch-programming :)
Speed stats:
Decompilation speed: 80.04 contracts/second
on AWS c5d.18xlarge instance
running 100 concurrent threads
Kitten Index: 2.18s to decompile CryptoKitties main contract
on a home laptop, single-threaded
MixGenes Index: Cannot decompile yet.
ZRX Index: 31s, 16 failed functions
Some of the ways you can write a transfer function.
def transfer(address _to, uint256 _value) : # not payable
require addr(_to)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require addr(_to) != 0
require balanceOf[caller] >= _value
require balanceOf[addr(_to)] + _value >= balanceOf[addr(_to)]
balanceOf[caller] = balanceOf[caller] - _value
balanceOf[addr(_to)] = balanceOf[addr(_to)] + _value
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require not stor1.160.uint8
require addr(_to)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log 0xddf252ad, caller, addr(_to), _value
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log 0xddf252ad, ORIGIN, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require CALLDATASIZE >= 68
require addr(_to) != 0
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require balanceOf[addr(_to)] + _value >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = balanceOf[addr(_to)] + _value
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require caller == ownerAddress
require _value < eth.balance(this.address)
call addr(_to) with: # withdraw / default function
gas 2300 * not _value wei
value _value wei
require call_ret_code
STOP
def transfer(address _to, uint256 _value) : # not payable
require addr(_to)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log 0xddf252ad, caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require _value <= balanceOf[caller]
require addr(_to)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log 0xddf252ad, caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require not stor1.160
require addr(_to)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require balanceOf[caller] >= _value
balanceOf[caller] = balanceOf[caller] - _value
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require _value <= balanceOf[caller].uint256
require addr(_to)
require _value <= balanceOf[caller].uint256
balanceOf[caller].uint256 = balanceOf[caller].uint256 - _value
require _value + balanceOf[addr(_to)].uint256 >= balanceOf[addr(_to)].uint256
balanceOf[addr(_to)].uint256 = _value + balanceOf[addr(_to)].uint256
log 0x69ddf252, caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require not stor3[caller].0.uint8
if stor5:
return with bool(0)
require addr(_to)
if _value > balanceOf[caller]:
return with bool(0)
if _value <= 0 OR (addr(_to) == caller):
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
require _value <= balanceOf[caller]
balanceOf[caller] = balanceOf[caller] - _value
require _value + balanceOf[addr(_to)] >= balanceOf[addr(_to)]
balanceOf[addr(_to)] = _value + balanceOf[addr(_to)]
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require allowed[caller] >= _value
if caller == addr(_to):
allowed[caller] = allowed[caller] - _value
allowed[addr(_to)] = allowed[addr(_to)] + _value
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
require allowed[addr(_to)] <= -_value - 1
allowed[caller] = allowed[caller] - _value
allowed[addr(_to)] = allowed[addr(_to)] + _value
log Transfer(address,address,uint256), caller, addr(_to), _value
return with bool(1)
def transfer(address _to, uint256 _value) : # not payable
require caller == stor1.0.addr
require _value <= licensesOf[caller].uint256
require licensesOf[addr(_to)].uint256 + _value >= licensesOf[addr(_to)].uint256
licensesOf[caller].uint256 = licensesOf[caller].uint256 - _value
licensesOf[addr(_to)].uint256 = _value + licensesOf[addr(_to)].uint256
return with bool(1)
Functions that have self-destruct open to public*
* - conditions may apply
Stake : 1312 finney
Condition : (storage(160, 0, 0) != 0 AND bool(call_ret_code)) AND bool(return_data)
» storage(160, 0, 0) == 0xce81bc335ec2818b5926299ab65b7f2a7d882208
def remove() payable:
if stor0.0.addr == 0:
STOP
call stor0.0.addr.hasRelation(bytes32,bytes32,address) with:
gas gas_remaining - 25050 wei
args stor1, owner, caller
require call_ret_code
if not return_data:
STOP
SELFDESTRUCT caller
Stake : 500 finney
Condition : TIMESTAMP > storage(256, 0, 10)
» now == 1541078137
» storage(256, 0, 10) == 1529193601
def suicide() : # not payable
if TIMESTAMP <= unlockTime:
STOP
SELFDESTRUCT ownerAddress
Stake : 3317 finney
Condition : (storage(160, 0, 0) != 0 AND bool(call_ret_code)) AND bool(return_data)
» storage(160, 0, 0) == 0xce81bc335ec2818b5926299ab65b7f2a7d882208
def remove() payable:
if stor0.0.addr == 0:
STOP
call stor0.0.addr.hasRelation(bytes32,bytes32,address) with:
gas gas_remaining - 25050 wei
args stor1, owner, caller
require call_ret_code
if not return_data:
STOP
SELFDESTRUCT caller
Stake : 4220 finney
Condition : []
def admin() : # not payable
SELFDESTRUCT 0x8948e4b00deb0a5adb909f4dc5789d20d0851d71
Stake : 10 finney
Condition : not storage(8, 0, 5) AND bool(call_ret_code)
» storage(8, 0, 5) == 1
def destroyDeed() : # not payable
require not stor5
call ownerAddress with: # withdraw / default function
gas 2300 * not eth.balance(this.address) wei
value eth.balance(this.address) wei
if not call_ret_code:
STOP
SELFDESTRUCT 57005
Stake : 500 finney
Condition : storage(256, 0, 2) != 0 AND (TIMESTAMP > storage(256, 0, 2) + 604800)
» now == 1541078136
» storage(256, 0, 2) == 0
def reward() : # not payable
require stor2.length != 0
require TIMESTAMP > stor2.length + 604800
SELFDESTRUCT stor6
Stake : 1000 finney
Condition : (ext_code.size(storage(160, 0, 1)) AND bool(bool(call_ret_code))) AND bool(bool(return_data))
» storage(160, 0, 1) == 0xcf1f116947ba657dcc9fbab294d2d8cd4b12c362
def kill_and_withdraw(address _withdraw_to) : # not payable
require ext_code.size(dbAddress)
call dbAddress.get_sale_owner(address) with:
gas gas_remaining wei
args caller
if not call_ret_code:
revert with 0
require return_data
log 0xb4f624e4, addr(_withdraw_to)
SELFDESTRUCT addr(_withdraw_to)
Stake : 14491 finney
Condition : (ext_code.size(storage(160, 0, 1)) AND bool(bool(call_ret_code))) AND bool(bool(return_data))
» storage(160, 0, 1) == 0xcf1f116947ba657dcc9fbab294d2d8cd4b12c362
def kill_and_withdraw(address _withdraw_to) : # not payable
require ext_code.size(dbAddress)
call dbAddress.get_sale_owner(address) with:
gas gas_remaining wei
args caller
if not call_ret_code:
revert with 0
require return_data
log 0xb4f624e4, addr(_withdraw_to)
SELFDESTRUCT addr(_withdraw_to)
Stake : 40 finney
Condition : (TIMESTAMP > 1534359600)
» now == 1541078137
def closeHouse() : # not payable
if TIMESTAMP > 1534359600:
SELFDESTRUCT ownerAddress
revert with Error(string), 'you can not close the house before the end of the withdrawal period'
Stake : 500 finney
Condition : (storage(256, 0, 3) != 0 AND (TIMESTAMP > storage(256, 0, 3) + 604800)) AND bool((storage(160, 0, 7) == 0))
» now == 1541078137
» storage(256, 0, 3) == 0
» storage(160, 0, 7) == 0
def reward() : # not payable
require stor3 != 0
require TIMESTAMP > stor3 + 604800
if stor7 != 0:
SELFDESTRUCT stor7
SELFDESTRUCT bipedaljoeAddress