Created
September 26, 2018 01:01
-
-
Save 0age/d55d8315c2119adfba3cc90b3f5c15df to your computer and use it in GitHub Desktop.
Calculate the reward for creating an upgradeable proxy contract with a given efficient address.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
var Decimal = require('decimal.js') // $ yarn add decimal.js | |
// pulling out the big guns (maybe a tad excessive...) | |
Decimal.config( | |
{ | |
precision: 500, | |
toExpNeg: -500 | |
} | |
) | |
// set up factorial function with a lookup table from 0! to 21! | |
function factorial(n) { | |
results = [ | |
'1', '1', '2', '6', '24', '120', '720', '5040', '40320', '362880', | |
'3628800', '39916800', '479001600', '6227020800', '87178291200', | |
'1307674368000', '20922789888000', '355687428096000', '6402373705728000', | |
'121645100408832000', '2432902008176640000', '51090942171709440000' | |
] | |
result = results[n] | |
return new Decimal(result) | |
} | |
// calculate reward for proxy address with z zero bytes & s starting zero bytes. | |
function calculateReward(zeroBytes, startingZeroBytes) { | |
// let's get the impossible stuff out of the way first. | |
if (startingZeroBytes > zeroBytes) {return '0'} | |
if (zeroBytes === 20 && startingZeroBytes !== 20) {return '0'} | |
if (zeroBytes !== 20 && startingZeroBytes === 20) {return '0'} | |
// set the length of the address segment. | |
const addressLength = 20 - startingZeroBytes | |
// calculate the number of extra zero bytes after the starting sequence. | |
const extraZeroBytes = zeroBytes - startingZeroBytes | |
// get BigNumber (actually "Decimal") versions of inputs. | |
let bn_zeroBytes = new Decimal(zeroBytes) | |
let bn_startingZeroBytes = new Decimal(startingZeroBytes) | |
let bn_extraZeroBytes = new Decimal(extraZeroBytes) | |
// get BigNumber (actually "Decimal") versions of constants. | |
let bn_one = new Decimal(1) | |
let bn_addressLength = new Decimal(addressLength) | |
let bn_twoFiftyFive = new Decimal(255) | |
let bn_twoFiftySix = new Decimal(256) | |
// set up a counter for getting the sum of the survival function components. | |
let bn_survivalFunctionSum = new Decimal(0) | |
// calculate inverse of the survival function, given # starting zero bytes. | |
for (zeroBytes = 0; zeroBytes < extraZeroBytes; zeroBytes++) { | |
// get BigNumber (actually "Decimal") version of extra zero bytes. | |
let bn_zeroBytes = Decimal(zeroBytes) | |
// calculate the component part of the sum and add it to the counter. | |
bn_survivalFunctionSum = bn_survivalFunctionSum.add( | |
// numerator | |
Decimal( | |
// (20 - s)! | |
factorial(addressLength) | |
).mul( | |
// * 255^(20 - n) | |
bn_twoFiftyFive.pow(bn_addressLength.sub(zeroBytes)) | |
).div( | |
// denominator | |
Decimal( | |
// (n - s)! | |
factorial(zeroBytes) | |
).mul( | |
// * (20 - n)! | |
Decimal(factorial(addressLength - zeroBytes)) | |
).mul( | |
// * 256^(20 - s) | |
bn_twoFiftySix.pow(bn_addressLength) | |
) | |
) | |
) | |
} | |
// compute leading zero reward multiplied by scaling factor: 256 ^ (s -3) | |
let twoFiftySixTopExp = bn_twoFiftySix.pow(bn_startingZeroBytes.sub(3)) | |
// return round((scaling factor) / (1 - survival function)) | |
return ( | |
twoFiftySixTopExp.div( | |
bn_one.sub( | |
bn_survivalFunctionSum | |
) | |
).toFixed(0).toString() | |
) | |
} | |
// let's do this thing. | |
function main() { | |
// catch all non-zero rewards in an array. | |
let rewards = [] | |
// iterate through each combo of zero bytes. | |
for (z = 0; z < 21; z++) { | |
// iterate through each combo of leading zero bytes. | |
for (s = 0; s < 21; s++) { | |
// get the reward and add it to the array if it's not zero. | |
const reward = calculateReward(z, s) | |
if (reward !== '0') { | |
rewards.push([z, s, reward]) | |
} | |
} | |
} | |
// sort the non-zero rewards by reward size. | |
rewards.sort((a, b) => {return a[2] - b[2]}) | |
// print the total number of possible reward combos. | |
console.log('total reward combinations:', rewards.length) | |
// dump the rewards for each combination. | |
console.log('\ns\tz\treward') | |
rewards.forEach(r => { | |
console.log(`${r[1]}\t${r[0]}\t${r[2]}`) | |
}) | |
} | |
main() | |
process.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment