64.64 fixed-point library: e_exp, ln, floor_log2 for an early LMSR prediction market. Deployed Aug 12, 2015 — pre-Gnosis.
Historical Significance
Deployed on August 12, 2015 in block 76,161 — twelve days after Ethereum Frontier mainnet launched on July 30, 2015 — this is, to current knowledge, the earliest Solidity library on Ethereum mainnet implementing production-quality exponential and natural-logarithm functions over a fixed-point number representation. It is the math layer of a three-contract logarithmic-market-scoring-rule (LMSR) prediction-market system whose other components — a difficulty resolution oracle at 0x33cA8b5377c9776eb59863Fb63814dc00a5CB10D and an LMSR market-maker contract at 0xdb7c577b93baeb56dab50af4d6f86f99a06b96a2 — were deployed by the same wallet 0x77b97786b0fb73e55d9e92d4b182befbf346f979 in the same week. To our knowledge it predates every other on-chain LMSR or continuous-pricing prediction-market deployment on Ethereum, including those of Augur, Gnosis, and Polymarket.
Context
The contract exposes three constant pure-math functions over 64.64 fixed-point inputs: e_exp(x) for the natural exponential, ln(x) for the natural logarithm, and floor_log2(x) as a binary-search helper. Plus three ownership-guarded admin entry points — MarketsContract, changeCreator, and deleteContract — sharing a single creator address slot. The exponential is computed by splitting the argument as qln(2)+r with r in [0, ln(2)), then evaluating 2^q multiplied by a six-term Taylor expansion of e^r with a small Pade-style correction of +97423649007 added at the end. The logarithm normalises x to a mantissa in [1, 2) using floor_log2, evaluates a fifteen-term Chebyshev polynomial seeded with a 102^64 bias, and converts log2 to ln by dividing by log2(e) shifted left by 64 bits. These are the same algorithmic shapes that reappear, refined, in the later production LMSRMarketMaker contracts shipped by Gnosis from 2017 onward; the deployer at 0x77b97786b0fb73e55d9e92d4b182befbf346f979 is associated with the pre-Gnosis prediction-market team of Stefan George, who co-founded Gnosis in 2017. The contract was compiled with the native C++ solc 0.1.0 build (no soljson distribution exists for that version) with the optimizer disabled. The runtime is 1913 bytes; the creation bytecode is 1932 bytes; both verify byte-for-byte against the on-chain bytecode at 0x258c09146b7a28Dde8d3e230030e27643F91115F. Companion contracts: difficulty oracle at 0x33cA8b5377c9776eb59863Fb63814dc00a5CB10D (deployed four blocks later, runtime 477 bytes, byte-for-byte verified) and the LMSR market-maker contract at 0xdb7c577b93baeb56dab50af4d6f86f99a06b96a2 whose deployment transaction ran out of gas before any code was written — the LMSRMarketMaker source for that target therefore could not be deployed at that address.
Key Facts
Description
64.64 fixed-point math library providing e_exp (natural exponential) and ln (natural logarithm) plus the floor_log2 binary-search helper. Used by an early-Frontier LMSR prediction market deployed by the same wallet (0x77b97786b0fb73e55d9e92d4b182befbf346f979) one week after Ethereum mainnet launch.
Source Verified
Byte-for-byte match. Compiler: solc 0.1.0 (frontier-jul29 native C++ build), optimizer OFF. Creation bytecode 1932 bytes and runtime bytecode 1913 bytes both reproduce exactly. Reproducible verification at github.com/cartoonitunes/frontier-math-library-verification.
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology and exact bytecode matching.
View Verification ProofShow source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
contract Math {
address creator;
function MarketsContract() {
creator = msg.sender;
}
function changeCreator(address newCreator) {
if (creator == msg.sender) creator = newCreator;
}
function deleteContract() {
if (creator == msg.sender) suicide(msg.sender);
}
function e_exp(uint x) constant returns (uint) {
uint ln2 = 12786308645202655660;
uint quot = x * 2**64 / ln2;
uint mult = 2 ** (quot / 2**64);
uint r = quot % 2**64;
uint xk = r;
uint acc = 2**64;
acc = acc + 12786308848809676358 * xk / 2**64;
xk = xk * r / 2**64;
acc = acc + 4431393213333354933 * xk / 2**64;
xk = xk * r / 2**64;
acc = acc + 1023895807607063857 * xk / 2**64;
xk = xk * r / 2**64;
acc = acc + 177331293418178780 * xk / 2**64;
xk = xk * r / 2**64;
acc = acc + 24779311982669544 * xk / 2**64;
xk = xk * r / 2**64;
acc = acc + 2636551292259273 * xk / 2**64;
acc = acc + 97423649007;
return mult * acc;
}
function ln(uint x) constant returns (uint) {
uint log2_e = 26613026195688644983;
uint log2x = floor_log2(x);
uint mant = x / 2**log2x;
uint pow = 2**64;
uint k = 2**64 * uint(10);
uint acc = k;
acc = acc - 78667125315852878943 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 277444915915471133247 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 672797865977353252899 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 1342495486912798362956 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 2079982050276078403724 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 2513117219478940937138 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 2388947274873244002805 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 1796495340862302170357 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 1069452193429189189773 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 501541584095099868767 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 183176043153313066814 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 51045426652184553460 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 10488088993333923171 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 1498020070724751224 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc - 132863869502364569 * pow / 2**64;
pow = pow * mant / 2**64;
acc = acc + 5511900345305548 * pow / 2**64;
return ((log2x * 2**64 + acc) - k) * 2**64 / log2_e;
}
function floor_log2(uint x) constant returns (uint) {
uint v = x / 2**64;
uint lo = 0;
uint hi = 191;
uint mid = (hi + lo) / 2;
while (lo + 1 != hi) {
if (v < 2**mid) hi = mid;
else lo = mid;
mid = (hi + lo) / 2;
}
return lo;
}
}