Z≡N Coin (symbol Z≡N), an early 2016 ERC-20-style token with built-in buy/sell marketplace at a 10× spread. Uses the ConsenSys MyAdvancedToken extended template
Token Information
Key Facts
Description
Z≡N Coin is an extended ConsenSys MyAdvancedToken deployment (Mar 28, 2016, deployer 0x5c883b78). The contract has decimals=2 and a 10× spread between its built-in buy and sell prices (buyPrice 0.01 ETH, sellPrice 0.1 ETH). It carries the full MyAdvancedToken admin surface plus three less-common extensions also seen in the ConsenSys 'centrally issued asset' tutorial: spentAllowance accounting (cumulative spend tracked vs. approval, instead of decrementing allowance), giveBlockReward() (mints 1 unit to block.coinbase), and an auto-sell branch in transfer() that tops up the sender's ETH balance to minBalanceForAccounts. 990 of the 1,000-unit initial supply (99%) was assigned to the deployer.
Source Verified
Source-reconstructed via dispatcher and storage-layout matching. All 22 dispatch selectors and all 11 storage slots match the on-chain runtime. The first 238 bytes of the runtime (entire dispatcher) are byte-identical to the rebuild compiled with soljson v0.3.1+commit.c492d9be (optimizer ON). The 64-byte size delta is concentrated inside sell() and the post-dispatcher trailer — a body-placement difference in early-2016 solc inlining of the final Transfer event emission. Dispatcher selectors include the canonical MyAdvancedToken set plus three extended functions: spentAllowance(address,address) [0xdc3080f2], setMinBalance(uint256) [0xc91d956c], and giveBlockReward() [0xfcd6e339]. See github.com/cartoonitunes/zencoin-verification for the verify.sh reproduction script.
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Homestead Era
The first planned hard fork. Removed the canary contract, adjusted gas costs.
Bytecode Overview
Verified Source Available
This contract has verified source code.
View Verification ProofShow source code (Solidity)
contract owned {
address public owner;
function owned() {
owner = msg.sender;
}
modifier onlyOwner {
if (msg.sender != owner) throw;
_
}
function transferOwnership(address newOwner) onlyOwner {
owner = newOwner;
}
}
contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token); }
contract MyAdvancedToken is owned {
/* Public variables of the token */
string public name;
string public symbol;
uint8 public decimals;
uint256 public sellPrice;
uint256 public buyPrice;
uint256 public totalSupply;
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
mapping (address => bool) public frozenAccount;
mapping (address => mapping (address => uint256)) public allowance;
mapping (address => mapping (address => uint256)) public spentAllowance;
uint minBalanceForAccounts;
/* This generates a public event on the blockchain that will notify clients */
event Transfer(address indexed from, address indexed to, uint256 value);
event FrozenFunds(address target, bool frozen);
/* Initializes contract with initial supply tokens to the creator of the contract */
function MyAdvancedToken(
uint256 initialSupply,
string tokenName,
uint8 decimalUnits,
string tokenSymbol,
address centralMinter
) {
if(centralMinter != 0 ) owner = centralMinter; // Sets the owner as specified (if centralMinter is not specified the owner is msg.sender)
balanceOf[owner] = initialSupply; // Give the owner all initial tokens
totalSupply = initialSupply; // Update total supply
name = tokenName; // Set the name for display purposes
symbol = tokenSymbol; // Set the symbol for display purposes
decimals = decimalUnits; // Amount of decimals for display purposes
}
/* Send coins */
function transfer(address _to, uint256 _value) {
if (frozenAccount[msg.sender]) throw; // Check if frozen
if (balanceOf[msg.sender] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
balanceOf[msg.sender] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
if(msg.sender.balance < minBalanceForAccounts) sell((minBalanceForAccounts - msg.sender.balance) / sellPrice);
Transfer(msg.sender, _to, _value); // Notify anyone listening that this transfer took place
}
/* Allow another contract to spend some tokens in your behalf */
function approveAndCall(address _spender, uint256 _value)
returns (bool success) {
allowance[msg.sender][_spender] = _value;
tokenRecipient spender = tokenRecipient(_spender);
spender.receiveApproval(msg.sender, _value, this);
return true;
}
/* A contract attempts to get the coins */
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (frozenAccount[_from]) throw; // Check if frozen
if (balanceOf[_from] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
if (_value + spentAllowance[_from][msg.sender] > allowance[_from][msg.sender]) throw; // Check allowance
balanceOf[_from] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
spentAllowance[_from][msg.sender] += _value;
Transfer(_from, _to, _value);
return true;
}
function mintToken(address target, uint256 mintedAmount) onlyOwner {
balanceOf[target] += mintedAmount;
totalSupply += mintedAmount;
Transfer(0, this, mintedAmount);
Transfer(this, target, mintedAmount);
}
function freezeAccount(address target, bool freeze) onlyOwner {
frozenAccount[target] = freeze;
FrozenFunds(target, freeze);
}
function giveBlockReward() {
balanceOf[block.coinbase] += 1;
}
function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
sellPrice = newSellPrice;
buyPrice = newBuyPrice;
}
function setMinBalance(uint minimumBalanceInFinney) onlyOwner {
minBalanceForAccounts = minimumBalanceInFinney * 1 finney;
}
function buy() returns (uint amount){
amount = msg.value / buyPrice; // calculates the amount
if (balanceOf[this] < amount) throw; // checks if it has enough to sell
balanceOf[msg.sender] += amount; // adds the amount to buyer's balance
balanceOf[this] -= amount; // subtracts amount from seller's balance
Transfer(this, msg.sender, amount); // execute an event reflecting the change
}
function sell(uint amount) returns (uint revenue){
if (balanceOf[msg.sender] < amount ) throw; // checks if the sender has enough to sell
balanceOf[this] += amount; // adds the amount to owner's balance
balanceOf[msg.sender] -= amount; // subtracts the amount from seller's balance
if (!msg.sender.send(amount * sellPrice)) throw; // sends ether to the seller. throws if fails
Transfer(msg.sender, this, amount); // executes an event reflecting on the change
revenue = amount * sellPrice; // ends function and returns
}
/* This unnamed function is called whenever someone tries to send ether to it */
function () {
throw; // Prevents accidental sending of ether
}
}