ApeCharts.com uses a provably fair system to ensure game outcomes cannot be manipulated:
The server keeps the actual server seed secret during the game and only reveals it after the game ends. This prevents anyone (including the operator) from knowing the outcome in advance, while still allowing for verification afterward.
To ensure transparency, the verification algorithm matches exactly what's used on the server. You can review the key portions of the code below:
// Price drift calculation
function driftPrice(
price,
DRIFT_MIN,
DRIFT_MAX,
BIG_MOVE_CHANCE,
BIG_MOVE_MIN,
BIG_MOVE_MAX,
randFn,
version = 'v2',
STARTING_PRICE = 1.0
) {
let change = 0;
if (randFn() < BIG_MOVE_CHANCE) {
const moveSize = BIG_MOVE_MIN + randFn() * (BIG_MOVE_MAX - BIG_MOVE_MIN);
change = randFn() > 0.5 ? moveSize : -moveSize;
} else {
const drift = DRIFT_MIN + randFn() * (DRIFT_MAX - DRIFT_MIN);
// Version difference is in this volatility calculation
const volatility = version === 'v1'
? 0.005 * Math.sqrt(price)
: 0.005 * Math.min(10, Math.sqrt(price));
change = drift + (volatility * (2 * randFn() - 1));
}
let newPrice = price * (1 + change);
if (newPrice < 0) {
newPrice = 0;
}
return newPrice;
}
// Game verification function
function verifyGame(serverSeed, gameId, version = 'v2') {
const combinedSeed = serverSeed + '-' + gameId;
const prng = new Math.seedrandom(combinedSeed);
let price = 1.0;
let peakMultiplier = 1.0;
let rugged = false;
for (let tick = 0; tick < 5000 && !rugged; tick++) {
if (prng() < RUG_PROB) {
rugged = true;
continue;
}
const newPrice = driftPrice(
price,
DRIFT_MIN,
DRIFT_MAX,
BIG_MOVE_CHANCE,
BIG_MOVE_MIN,
BIG_MOVE_MAX,
prng.bind(prng),
version
);
price = newPrice;
if (price > peakMultiplier) {
peakMultiplier = price;
}
}
return {
peakMultiplier: peakMultiplier,
rugged: rugged
};
}