Skip to content

Instantly share code, notes, and snippets.

@0age
Created September 26, 2018 01:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0age/d55d8315c2119adfba3cc90b3f5c15df to your computer and use it in GitHub Desktop.
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.
#!/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