Skip to content

Instantly share code, notes, and snippets.

@sorpaas
Last active August 11, 2018 13:16
Show Gist options
  • Save sorpaas/27b8026c40e4777ede889c40e3824a04 to your computer and use it in GitHub Desktop.
Save sorpaas/27b8026c40e4777ede889c40e3824a04 to your computer and use it in GitHub Desktop.
Brute Force Approach to EIP-1087/EIP-1283 Equivalence "Proof"
#[derive(Debug)]
struct Consumption {
used: usize,
refund: usize,
}
impl Consumption {
pub fn absolute(&self) -> isize {
self.used as isize - self.refund as isize
}
}
fn eip1283(chain: &[usize]) -> Consumption {
let mut consumption = Consumption {
used: 0,
refund: 0,
};
let original = chain[0];
for i in 0..(chain.len()-1) {
let current = chain[i];
let new = chain[i+1];
if current == new {
consumption.used += 200;
} else {
if original == current {
if original == 0 {
consumption.used += 20000;
} else {
consumption.used += 5000;
if new == 0 {
consumption.refund += 15000;
}
}
} else {
consumption.used += 200;
if original != 0 {
if current == 0 {
consumption.refund -= 15000;
} else if new == 0 {
consumption.refund += 15000;
}
}
if original == new {
if original == 0 {
consumption.refund += 19800;
} else {
consumption.refund += 4800;
}
}
}
}
}
consumption
}
fn eip1087(chain: &[usize]) -> Consumption {
let mut consumption = Consumption {
used: 0,
refund: 0,
};
let original = chain[0];
let mut dirty = false;
for i in 0..(chain.len()-1) {
let current = chain[i];
let new = chain[i+1];
if current == new {
consumption.used += 200;
continue;
}
if dirty {
consumption.used += 200;
} else {
dirty = true;
if original == 0 {
consumption.used += 20000;
} else {
consumption.used += 5000;
}
}
}
let last = chain[chain.len()-1];
if dirty {
if original == 0 && last == 0 {
consumption.refund += 19800;
} else if original != 0 && original == last {
consumption.refund += 4800;
} else if original != 0 && last == 0 {
consumption.refund += 15000;
}
}
consumption
}
fn current(chain: &[usize]) -> Consumption {
let mut consumption = Consumption {
used: 0,
refund: 0,
};
for i in 0..(chain.len()-1) {
let current = chain[i];
let new = chain[i+1];
consumption.used += if new != 0 && current == 0 {
20000
} else {
5000
};
consumption.refund += if new == 0 && current != 0 {
15000
} else {
0
};
}
consumption
}
fn build_chain(mut index: usize) -> [usize; 10] {
let mut chain = [0; 10];
let mut chain_index = 0;
while index > 0 {
chain[chain_index] = index % 4;
index = index / 4;
chain_index += 1;
}
chain
}
fn main() {
println!("eip1283: {:?}", eip1283(&[0, 1, 0, 1, 0]));
println!("eip1087: {:?}", eip1087(&[0, 1, 0, 1, 0]));
println!("current: {:?}", current(&[0, 1, 0, 1, 0]));
for i in 0..(4usize.pow(10)-1) {
let chain = build_chain(i);
// println!("{:?}, eip1283: {:?}, eip1087: {:?}", chain, eip1283(&chain), eip1087(&chain));
assert_eq!(eip1283(&chain).absolute(), eip1087(&chain).absolute());
// Check that in all cases, we never cost most gases compared
// to what we have right now.
assert!(eip1283(&chain).used <= current(&chain).used);
if i % 1000 == 0 {
println!("Tested {} cases to be matching!", i);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment