Acebusters Nutz (NTZ): Sept 2017 on-chain poker chip. Thin ERC-20/ERC-223 proxy delegating every call to a separate Controller with bonding curve.
Historical Significance
Acebusters Nutz is one of the earliest production on-chain dapp token deployments to combine a delegating proxy pattern with a bonding curve and dual ERC-20 + ERC-223 surface in a single coherent design, in September 2017. The architecture predates the standardized proxy patterns (EIP-1822 UUPS in 2019, EIP-1967 transparent proxy in 2019) by roughly two years; Acebusters did the controller-owns-proxy split by hand.
Acebusters was a real-money poker dapp where hands ran in state channels and only settlements hit the chain. The NTZ bonding curve provided a continuous market-maker so players could redeem chips back to ETH at any time without an order book counterparty. The custom unit ladder (Babz / Jonyz / Helcz / Pascalz / Nutz) honors Babbage, von Neumann, Helmholtz, and Pascal, in the same spirit as the wei/gwei/ether naming.
Context
Compiled with Solidity v0.4.16+commit.d7661dd9, optimizer on, 200 runs. Deployed 16 September 2017 at block 4,280,239 by 0x1a4faec2f0b3e268494c140f2faafce1791f7719, one month before the Byzantium hard fork. The companion Controller at 0xe7dc501cb9ca414cf9211af214d5065ca3a30768 was deployed shortly before and is also Etherscan-verified (also Solidity 0.4.18, optimizer on).
Token Information
Key Facts
Description
Acebusters Nutz (NTZ) is the in-game currency of Acebusters, an on-chain Texas hold'em poker dapp from 2017. The deployed Nutz contract is a thin user-facing proxy: every storage-touching call (balanceOf, totalSupply, transfer, transferFrom, approve, allowance, floor, ceiling, powerPool, activeSupply) delegates to the contract's owner, which is a separate Controller at 0xe7dc501cb9ca414cf9211af214d5065ca3a30768 that also has its source verified on Etherscan. The Controller holds the actual balance map, runs the bonding-curve sell/buy logic, manages the ETH reserve, and gates an admin pause.
The token implements both ERC-20 and ERC-223. The ERC-223 path checks whether the recipient address has code (via EXTCODESIZE) and, if so, calls tokenFallback(from, value, data) on the recipient before completing the transfer. The pay-in path is a payable function purchase() (selector efef39a1) and a payable fallback that both forward msg.value to Controller.purchase, returning Nutz at the current ceiling price. The pay-out path is sell(price, amountBabz) and powerUp(amountBabz), both delegating to Controller with the caller's price guard.
Unit ladder, mirroring wei/gwei/eth: 1 NTZ = 10^12 Babz (base unit) = 10^9 Pascalz = 10^6 Helcz = 10^3 Jonyz (named for John von Neumann), 12 decimals. The base unit name 'Babz' honors Charles Babbage. As of 2026-05 the active totalSupply is approximately 647,253.4966 NTZ; the Nutz contract itself holds 0 ETH (the reserve is on the Controller, also 0 ETH, since the game wound down years ago).
Source Verified
Author-published source verified on Etherscan. Optimizer on (200 runs). The Nutz contract is a thin proxy; the implementation lives in the companion Controller at 0xe7dc501cb9ca414cf9211af214d5065ca3a30768, which is also Etherscan-verified.
Historian Categories
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Spurious Dragon Era
Continued DoS protection. State trie clearing.
Bytecode Overview
Verified Source Available
Source verified on Etherscan.
View Verification ProofShow source code (Solidity)
pragma solidity 0.4.16;
contract PullPayInterface {
function asyncSend(address _dest) public payable;
}
contract ERC223ReceivingContract {
function tokenFallback(address _from, uint _value, bytes _data);
}
contract ControllerInterface {
// State Variables
bool public paused;
address public nutzAddr;
// Nutz functions
function babzBalanceOf(address _owner) constant returns (uint256);
function activeSupply() constant returns (uint256);
function burnPool() constant returns (uint256);
function powerPool() constant returns (uint256);
function totalSupply() constant returns (uint256);
function allowance(address _owner, address _spender) constant returns (uint256);
function approve(address _owner, address _spender, uint256 _amountBabz) public;
function transfer(address _from, address _to, uint256 _amountBabz, bytes _data) public;
function transferFrom(address _sender, address _from, address _to, uint256 _amountBabz, bytes _data) public;
// Market functions
function floor() constant returns (uint256);
function ceiling() constant returns (uint256);
function purchase(address _sender, uint256 _value, uint256 _price) public returns (uint256);
function sell(address _from, uint256 _price, uint256 _amountBabz);
// Power functions
function powerBalanceOf(address _owner) constant returns (uint256);
function outstandingPower() constant returns (uint256);
function authorizedPower() constant returns (uint256);
function powerTotalSupply() constant returns (uint256);
function powerUp(address _sender, address _from, uint256 _amountBabz) public;
function downTick(address _owner, uint256 _now) public;
function createDownRequest(address _owner, uint256 _amountPower) public;
function downs(address _owner) constant public returns(uint256, uint256, uint256);
function downtime() constant returns (uint256);
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner {
require(newOwner != address(0));
owner = newOwner;
}
}
contract ERC20Basic {
function totalSupply() constant returns (uint256);
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
event Transfer(address indexed from, address indexed to, uint value);
}
contract ERC223Basic is ERC20Basic {
function transfer(address to, uint value, bytes data) returns (bool);
}
/*
* ERC20 interface
* see https://github.com/ethereum/EIPs/issues/20
*/
contract ERC20 is ERC223Basic {
// active supply of tokens
function activeSupply() constant returns (uint256);
function allowance(address _owner, address _spender) constant returns (uint256);
function transferFrom(address _from, address _to, uint _value) returns (bool);
function approve(address _spender, uint256 _value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/**
* Nutz implements a price floor and a price ceiling on the token being
* sold. It is based of the zeppelin token contract.
*/
contract Nutz is Ownable, ERC20 {
event Sell(address indexed seller, uint256 value);
string public name = "Acebusters Nutz";
// acebusters units:
// 10^12 - Nutz (NTZ)
// 10^9 - Jonyz
// 10^6 - Helcz
// 10^3 - Pascalz
// 10^0 - Babz
string public symbol = "NTZ";
uint256 public decimals = 12;
// returns balances of active holders
function balanceOf(address _owner) constant returns (uint) {
return ControllerInterface(owner).babzBalanceOf(_owner);
}
function totalSupply() constant returns (uint256) {
return ControllerInterface(owner).totalSupply();
}
function activeSupply() constant returns (uint256) {
return ControllerInterface(owner).activeSupply();
}
// return remaining allowance
// if calling return allowed[address(this)][_spender];
// returns balance of ether parked to be withdrawn
function allowance(address _owner, address _spender) constant returns (uint256) {
return ControllerInterface(owner).allowance(_owner, _spender);
}
// returns either the salePrice, or if reserve does not suffice
// for active supply, returns maxFloor
function floor() constant returns (uint256) {
return ControllerInterface(owner).floor();
}
// returns either the salePrice, or if reserve does not suffice
// for active supply, returns maxFloor
function ceiling() constant returns (uint256) {
return ControllerInterface(owner).ceiling();
}
function powerPool() constant returns (uint256) {
return ControllerInterface(owner).powerPool();
}
function _checkDestination(address _from, address _to, uint256 _value, bytes _data) internal {
// erc223: Retrieve the size of the code on target address, this needs assembly .
uint256 codeLength;
assembly {
codeLength := extcodesize(_to)
}
if(codeLength>0) {
ERC223ReceivingContract untrustedReceiver = ERC223ReceivingContract(_to);
// untrusted contract call
untrustedReceiver.tokenFallback(_from, _value, _data);
}
}
// ############################################
// ########### ADMIN FUNCTIONS ################
// ############################################
function powerDown(address powerAddr, address _holder, uint256 _amountBabz) public onlyOwner {
bytes memory empty;
_checkDestination(powerAddr, _holder, _amountBabz, empty);
// NTZ transfered from power pool to user's balance
Transfer(powerAddr, _holder, _amountBabz);
}
function asyncSend(address _pullAddr, address _dest, uint256 _amountWei) public onlyOwner {
assert(_amountWei <= this.balance);
PullPayInterface(_pullAddr).asyncSend.value(_amountWei)(_dest);
}
// ############################################
// ########### PUBLIC FUNCTIONS ###############
// ############################################
function approve(address _spender, uint256 _amountBabz) public {
ControllerInterface(owner).approve(msg.sender, _spender, _amountBabz);
Approval(msg.sender, _spender, _amountBabz);
}
function transfer(address _to, uint256 _amountBabz, bytes _data) public returns (bool) {
ControllerInterface(owner).transfer(msg.sender, _to, _amountBabz, _data);
Transfer(msg.sender, _to, _amountBabz);
_checkDestination(msg.sender, _to, _amountBabz, _data);
return true;
}
function transfer(address _to, uint256 _amountBabz) public returns (bool) {
bytes memory empty;
return transfer(_to, _amountBabz, empty);
}
function transData(address _to, uint256 _amountBabz, bytes _data) public returns (bool) {
return transfer(_to, _amountBabz, _data);
}
function transferFrom(address _from, address _to, uint256 _amountBabz, bytes _data) public returns (bool) {
ControllerInterface(owner).transferFrom(msg.sender, _from, _to, _amountBabz, _data);
Transfer(_from, _to, _amountBabz);
_checkDestination(_from, _to, _amountBabz, _data);
return true;
}
function transferFrom(address _from, address _to, uint256 _amountBabz) public returns (bool) {
bytes memory empty;
return transferFrom(_from, _to, _amountBabz, empty);
}
function () public payable {
uint256 price = ControllerInterface(owner).ceiling();
purchase(price);
require(msg.value > 0);
}
function purchase(uint256 _price) public payable {
require(msg.value > 0);
uint256 amountBabz = ControllerInterface(owner).purchase(msg.sender, msg.value, _price);
Transfer(owner, msg.sender, amountBabz);
bytes memory empty;
_checkDestination(address(this), msg.sender, amountBabz, empty);
}
function sell(uint256 _price, uint256 _amountBabz) public {
require(_amountBabz != 0);
ControllerInterface(owner).sell(msg.sender, _price, _amountBabz);
Sell(msg.sender, _amountBabz);
}
function powerUp(uint256 _amountBabz) public {
Transfer(msg.sender, owner, _amountBabz);
ControllerInterface(owner).powerUp(msg.sender, msg.sender, _amountBabz);
}
}