Back to Home
GavCoin logo

GavCoin

Token
0x0b8d56c26d8c...3503d974de06
Tangerine WhistleContract #25KSource VerifiedEdit this contract
Deployed October 19, 2016 (9 years ago)Block 2,468,249

Token created by Gavin Wood (Ethereum co-founder), with a buyin/refund Dutch auction mechanism. ABI matches the official gavofyork/gavcoin GitHub repository.

Token Information

Logo
GavCoin logo
via RPC
Token Name
GavCoin

Key Facts

Deployment Block
2,468,249
Deployment Date
Oct 19, 2016, 01:50 PM
Code Size
1.9 KB
Gas at Deploy
603,510
Transactions by Year
2016108
2017159
201836
20191
202162
20222
20231
202426
202550
20261

Description

The contract defines a token with subdivisible units and a dynamic issuance model based on tranches. Tokens are sold in fixed-size tranches at increasing prices, with each tranche raising the token price by a fixed increment. Purchases generate on-chain receipts that become refundable after a defined activation period, allowing holders to return tokens for ether at their purchase price. Transfers, approvals, and allowances follow an ERC-20–style interface, while issuance and refunds are handled directly by the contract.

GavCoin was deployed by Gavin Wood (gavofyork on GitHub) as part of the early Parity ecosystem. The contract implements a basic token with a continuous sale mechanism — users could send ETH to the contract and receive GavCoin tokens at a price that increases with total supply. The contract includes standard token functions (transfer, approve, transferFrom) plus a built-in buy mechanism.

The token was created after Wood left the Ethereum Foundation in January 2016 and co-founded Ethcore (later Parity Technologies) with Jutta Steiner. GavCoin was used as a reference dapp in the Parity wallet interface, demonstrating how Parity could display and interact with token contracts. The source code was published on GitHub under the gavofyork/gavcoin repository.

GavCoin is notable as a personal experiment from one of Ethereum's most influential architects — the person who designed the EVM, proposed the Solidity language, and wrote the Ethereum Yellow Paper.

Source Verified

Etherscan verified

Heuristic Analysis

The following characteristics were detected through bytecode analysis and may not be accurate.

Detected Type: Token
Has ERC-20-like patterns

Tangerine Whistle Era

Emergency fork to address DoS attacks. Repriced IO-heavy opcodes.

Block span: 2,463,0002,674,999
October 18, 2016November 22, 2016

Bytecode Overview

Opcodes1,915
Unique Opcodes178
Jump Instructions75
Storage Operations66

Verified Source Available

Source verified on Etherscan.

Show source code (Solidity)
contract Token {
    /// Get the total amount of tokens in the system.
    function totalSupply() constant returns (uint256 total);

    /// @param _owner The address from which the balance will be retrieved
    /// @return The balance
    function balanceOf(address _owner) constant returns (uint256 balance);

    /// @notice send `_value` token to `_to` from `msg.sender`
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transfer(address _to, uint256 _value) returns (bool success);

    /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
    /// @param _from The address of the sender
    /// @param _to The address of the recipient
    /// @param _value The amount of token to be transferred
    /// @return Whether the transfer was successful or not
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);

    /// @notice `msg.sender` approves `_addr` to spend `_value` tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @param _value The amount of wei to be approved for transfer
    /// @return Whether the approval was successful or not
    function approve(address _spender, uint256 _value) returns (bool success);

    /// @param _owner The address of the account owning tokens
    /// @param _spender The address of the account able to transfer the tokens
    /// @return Amount of remaining tokens allowed to spent
    function allowance(address _owner, address _spender) constant returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract GavCoin {
    struct Receipt {
        uint units;
        uint32 activation;
    }
    struct Account {
        uint balance;
        mapping (uint => Receipt) receipt;
        mapping (address => uint) allowanceOf;
    }
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Buyin(address indexed buyer, uint indexed price, uint indexed amount);
    event Refund(address indexed buyer, uint indexed price, uint indexed amount);
    event NewTranch(uint indexed price);
    
    modifier when_owns(address _owner, uint _amount) { if (accounts[_owner].balance < _amount) return; _ }
    modifier when_has_allowance(address _owner, address _spender, uint _amount) { if (accounts[_owner].allowanceOf[_spender] < _amount) return; _ }
    modifier when_have_active_receipt(uint _price, uint _units) { if (accounts[msg.sender].receipt[_price].units < _units || now < accounts[msg.sender].receipt[_price].activation) return; _ }

    function balanceOf(address _who) constant returns (uint) { return accounts[_who].balance; }
    
    function transfer(address _to, uint256 _value) when_owns(msg.sender, _value) returns (bool success) {
        Transfer(msg.sender, _to, _value);
        accounts[msg.sender].balance -= _value;
        accounts[_to].balance += _value;
    }
    function transferFrom(address _from, address _to, uint256 _value) when_owns(_from, _value) when_has_allowance(_from, msg.sender, _value) returns (bool success) {
        Transfer(_from, _to, _value);
        accounts[_from].allowanceOf[msg.sender] -= _value;
        accounts[_from].balance -= _value;
        accounts[_to].balance += _value;
        return true;
    }
    function approve(address _spender, uint256 _value) returns (bool success) {
        Approval(msg.sender, _spender, _value);
        accounts[msg.sender].allowanceOf[_spender] += _value;
        return true;
    }
    function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
        return accounts[_owner].allowanceOf[_spender];
    }
    
    /// Simple buyin.
    function() { buyinInternal(msg.sender, 2 ** 255); }

    /// Extended buyin.
    function buyin(address _who, uint _maxPrice) { buyinInternal(_who, _maxPrice); }

    function refund(uint _price, uint _units) when_have_active_receipt(_price, _units) when_owns(msg.sender, _units) returns (bool) {
        Refund(msg.sender, _price, _units);
        accounts[msg.sender].balance -= _units;
        totalSupply += _units;
        accounts[msg.sender].receipt[_price].units -= _units;
        if (accounts[msg.sender].receipt[_price].units == 0)
            delete accounts[msg.sender].receipt[_price];
        if (!msg.sender.send(_units * _price / base))
            throw;
        return true;
    }

    function buyinInternal(address _who, uint _maxPrice) internal {
        var leftToSpend = msg.value;
        while (leftToSpend > 0 && price <= _maxPrice) {
            // How much the remaining tokens of this tranch cost to buy
            var maxCanSpend = price * remaining / base;
            // How much we will spend - the mininum of what's left in the tranch
            // to buy and what we have remaining
            var spend = leftToSpend > maxCanSpend ? maxCanSpend : leftToSpend;
            // The number of units we get for spending that
            var units = spend * base / price;

            // Provide tokens and a purchase receipt
            accounts[msg.sender].balance += units;
            accounts[msg.sender].receipt[price].units += units;
            accounts[msg.sender].receipt[price].activation = uint32(now) + refundActivationPeriod;
            totalSupply += units;
            Buyin(msg.sender, price, units);

            // Reduce the amounts remaining
            leftToSpend -= spend;
            remaining -= units;
            
            // If this is the end of the tranch...
            if (remaining == 0) {
                // ...Increment price and reset remaining
                price += tranchStep;
                remaining = tokensPerTranch * base;
                NewTranch(price);
            }
        }
    }
    
    uint public totalSupply;
    mapping (address => Account) accounts;
    
    uint constant base = 1000000;               // tokens are subdivisible by 1000000
    uint constant tranchStep = 1 finney;        // raise price by 1 finney / tranch
    uint constant tokensPerTranch = 100;        // 100 tokens per tranch
    uint public price = 1 finney;               // begin at 1 finney / token
    uint public remaining = tokensPerTranch * base;
    uint32 constant refundActivationPeriod = 7 days;
}

External Links