Skip to content

Instantly share code, notes, and snippets.

@banteg
Created December 19, 2018 03:38
Show Gist options
  • Select an option

  • Save banteg/d8f2d6514ecf20af0a9d365c907f304f to your computer and use it in GitHub Desktop.

Select an option

Save banteg/d8f2d6514ecf20af0a9d365c907f304f to your computer and use it in GitHub Desktop.
recover makerdao governance votes
import json
from collections import Counter, defaultdict
from dataclasses import dataclass, field
from decimal import Decimal
from eth_abi import encode_single
from eth_utils import function_signature_to_4byte_selector, decode_hex, encode_hex
from itertools import count
from web3.auto import w3
@dataclass
class Voter:
yays: list = field(default_factory=list)
weight: Decimal = Decimal()
def get_chief():
return w3.eth.contract(
'0x8E2a84D6adE1E7ffFEe039A35EF5F19F13057152',
abi=json.load(open('chief.json'))
)
def get_slates(chief):
etches = chief.events.Etch().createFilter(fromBlock=4749331).get_all_entries()
slates = {encode_hex(etch['args']['slate']) for etch in etches}
return slates
def slate_to_addresses(chief, slate):
addresses = []
for i in count():
try:
addresses.append(chief.functions.slates(slate, i).call())
except ValueError:
break
return addresses
def func_topic(func):
return encode_hex(encode_single('bytes32', function_signature_to_4byte_selector(func)))
def get_notes(chief):
# get yays and slate votes
return w3.eth.getLogs({
'address': chief.address,
'topics': [
[func_topic('vote(address[])'), func_topic('vote(bytes32)')]
],
'fromBlock': 4749331,
})
def notes_to_voters(chief, notes, slates_yays):
voters = defaultdict(Voter)
for note in notes:
data = decode_hex(note['data'])[96:]
try:
func, args = chief.decode_function_input(data)
except:
continue
sender = w3.toChecksumAddress(note['topics'][1][-20:])
v = voters[sender]
v.yays = slates_yays[encode_hex(args['slate'])] if 'slate' in args else args['yays']
for v in voters:
voters[v].weight = w3.fromWei(chief.functions.deposits(v).call(), 'ether')
return voters
def voters_to_results(voters):
proposals = Counter()
for addr in voters:
for yay in voters[addr].yays:
proposals[yay] += voters[addr].weight
return proposals.most_common()
def votes_for_proposal(proposal, voters):
votes = Counter()
for addr in voters:
if proposal in voters[addr].yays and voters[addr].weight > 0:
votes[addr] = voters[addr].weight
return votes.most_common()
def main():
chief = get_chief()
slates = get_slates(chief)
slates_yays = {slate: slate_to_addresses(chief, slate) for slate in slates}
notes = get_notes(chief)
voters = notes_to_voters(chief, notes, slates_yays)
for proposal, votes in voters_to_results(voters):
print(proposal, votes)
for voter, weight in votes_for_proposal(proposal, voters):
print(' ', voter, weight)
print()
if __name__ == '__main__':
main()
@banteg
Copy link
Copy Markdown
Author

banteg commented Dec 19, 2018

how to read the output:

proposal votes
  voter weight

example output:

0x6091295974c12C4305b8bF6D2062bF48f37A3b36 70000.137555366034829019
  0xd48d3462C5e5A5d568c8F8ec3366241ed8b46BD1 70000
  0xeCc04C3B80FF24384dE130002c5B694bB497F1E8 0.137555366034829018
  0x22E86ab483084053562cE713e94431C29D1Adb8b 1E-18

0x9D67476aC572570d81027ea8B6efbe8f6fD25a42 58826.087620055985569559
  0x12Bd4da28d88c81aC60ed02EE5CC9245660649fA 11479.77921185529623093
  0xccA74093B7b5d554fe68b1412c627C01718C010E 10875.338596
  0x263169Ddd7284702B5af09230B7b83476582A91a 10526
  0xbC7C4bFeeF2Eb38502b49A549C6823A4b738ad3D 7954.84615
  0xE974222900B15D680De41278f1b1622C8c436D87 6563.240242381520400334
  0x7Ed50946f0CF426154EBf19e91fB0B86880Df018 3072.886594260209526068
  0xA4e78744C3F92a6Ed5993C90ac09897ee94942BE 2255
  0x8ecb0a8fe7649f7ec79ab50EF74CEFA38343b0D4 1223
  0xdfCA7C13555620cfEe8d5597336D4c79F65608cc 1000
  0xb3b26197C28A6A9D196404bc396437eD979AB854 1000
  0xCFCa13139DfE5C297023854C94B84d5A864e1804 975.7716701137724
  0x084A459b801a046fAB311ad03A43F02F58855AF0 450.45672943968749059
  0x7BEB4CE862A529313d1c7732D3246c5a87d8e938 369.95283018867923
  0x22D9BE7B015A29bC31d579F0C91187ef7399B833 270
  0xCCA986fbf1050382A266B6e9D805eb7AC7A48669 125
  0x9F407f60B68E22756d5bFa86f8F872584EDda5BC 124.9
  0xFc54faF414F92577f72C604e6646D224E531E31E 101
  0x335D320aB84dFb92fFdcf3F6800e13b9751e9d99 100.55
  0x4872bA8e4E7912eE297b9336204aaB9104ebD16F 74.74519589645976
  0x99ade299B61fe10dfe3f7deC0523EB4461ce3d4e 65
  0x9e6316Bf2A72311b8DeFd8Eb951d462C95819F49 61.703037869377006404
  0x7A181B8b135B5B2281EF124a42ac008Cf8d36240 27.404372365608398743
  0xA0E28B7A6Aa4327f5EC7A34ceDDd404216E600c7 24.258010613423154518
  0x5a82Cf85fFf66F15B119Eb5eE4ad93AFd3EA8aBf 15.5
  0x55e18dCdBaFe7a598dE2c786648C2602efBBC200 12.29
  0x0De43110a2B467C4F99a3628555D51E48870676A 11.018104589460136799
  0x68bA03a1520d2f800b9452f3102D823eac0F94BA 7.7
  0x1a0d8D271e70C7cf45a4B8d79Ac59956755b5080 6.4191350206171199
  0x91C7890b28382bA27752ac5ACca8a5BfC76dbED4 6.349937670403995
  0x5508870e2e47Ece5284E2C51360f591D820Fd1D5 6
  0xe16b878cfC3D303896786f2512683C9282aF2D9E 5.590020080665286634
  0x57291A69E65a0d163C8BC23Bf01369A8BFbaE731 5.174316
  0x9e1826CA0Ed2c98241540b2eC772dE34D385936E 3.48165678107771304
  0xCAb6cA25F1f7edb5502b57578848337174BE6aD9 3.378652197235310331
  0x2466A9EF5E1249881110DBDeFf7fba0d2f4C66D5 3.0303644012497197
  0x467690a96F7e0040a82A48F6258b0bC24C1F6500 3
  0x594ADCcE7D147695A27ea5a7E14AC26E912b5535 2.675119434735525
  0xC0f24029291964f9E3F68c3B3252968beDfd92Ff 2.5
  0x761cb8589549B75dBf6459A027950E9bCa880B95 2.233097923651311267
  0x55470a997e05c384276535422C316030f168367D 1.584321301775147929
  0x539C4e82B9091BE54452431f9373ad28434F9690 1.4698444588822994
  0xE7a90149F3B25CBAD616517e6dc4e4ec2f1Df517 1.159454973229834626
  0x47fE8623F07cd424f90CD6e5d1c6d022FAC4d8bB 1.059784917080469547
  0xEDEFf7FCf66d041Faa5713C1095dD2A866A16004 1
  0xdC2c106e915fe148DcECe1Bc967fe45E19279cf4 1
  0xb83aD9683EB1831391f59c4106652B9d5B0a379c 1
  0x04044277c80418470326abBfD9F629Bb707ef171 0.501265695882102308
  0x12a325612f6561e1e22b621643D56730Ec2770C3 0.1
  0xf4C5bD4afe311a25A8fc807c70C008984F3ED926 0.037398811981309133
  0xc90Be111d781d4F29E1f4DAc91F4E74a0E9AD069 0.0025
  0xbBed408b1a6f44E617F4C11E57a2E013Af69DC34 0.000004814024691358

0x0000000000000000000000000000000000000000 21500
  0x7D0BaFf140158432086173cF01De3977fa2f3ffF 10000
  0x703039B1731aACdE98667a4074cB68F10eB0852c 5000
  0xCcf7F1345891a5b1Eb781d086Ca298222220B759 5000
  0x7C5F6fFaD368dBf1a83E6D66b5aCE792fac2E7C0 1500

0x8ffb52208c08D4254E06737BE0e1f0fE271B76b2 11819.039326333070616463
  0xCcf7F1345891a5b1Eb781d086Ca298222220B759 5000
  0xf02203Dd666D79d9924aC1C387553CA140A3F4AA 4700
  0x1d8Aa18cD769971439FEf1A7b0abCE8b83f114fa 1708.320743898555978491
  0xb08E622f208992A0fC0f5DB57E291d8c97CFFb38 300
  0x12958035F5D05D4E8aCDa1264CCa55937A4AfAE8 100
  0x6979039759EA5f6AD1d86261ad3f33d4Cec83e8A 10
  0x0cAF24C0747F24E2167765f5BDD0d35acAd3ABab 0.718582434514637972

0xCa6F79983baD5450a6257e20b6e0B766c3d0c654 5000
  0x703039B1731aACdE98667a4074cB68F10eB0852c 5000

0x305505C8C9D51602f3Ebe0CE984aB2AEb0df3172 48.2830
  0x2660f1d5EF5b00D6Ee4e03731Bf49F0Fec1edfcd 21
  0x0BD9EFb56c91A6AD9c3d09844bCB4ccceBB37aD2 19.2722
  0x2214C53fA762E4f33E0D78D7aef27d3Af8BC623D 4
  0xe2fEBbA1352A1f0c3886407390d0585Bfc7880b9 3
  0xB11592C116920A85EFe42BD5e44E9080819ACD91 1.0008
  0x72E337227a1418feCfdeF9d551a91bC919B909FB 0.01

0x8314d1Aaee9C0804A00AF704a7f713003aEF6F0c 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment