Curio Cards art token for Card #10 (Future), art by Phneep.
Historical Significance
Part of Curio Cards, the first art show NFT collection on Ethereum and an early model for fixed-supply digital art ownership.
Context
Curio Cards launched as an online Ethereum art gallery in May 2017, before ERC-721 was widely adopted. This contract belongs to the original release set and was deployed by Rhett Creighton (@rhett_creighton), Curio Cards co-founder and Solidity developer. Published May-30-2017 03:16:51 AM +UTC.
Token Information
Key Facts
Description
Curio Card #10 (Future) is an original 2017 Curio Cards art token with artwork by Phneep. Future closes Phneep's Cards 1-10 sequence about mankind and art. The artwork shows a winding road through a green landscape, pointing from early human needs and tools toward the future of art.
The contract uses ERC-20-style token functions with symbol CRO10, 0 decimals, and on-chain totalSupply 100000. The card token is locked, so no additional cards can be minted. Final card supply is 2000.
Source Verified
Contract source is verified on Etherscan; sourceCode is included so EthereumHistory can display verified status.
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.8;
contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); }
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 CardToken is owned {
string public standard = 'Token 0.1';
string public name;
string public symbol;
string public ipfs_hash;
string public description;
bool public isLocked;
uint8 public decimals;
uint256 public totalSupply;
/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
/* This generates a public event on the blockchain that will notify clients */
event Transfer(address indexed from, address indexed to, uint256 value);
/* Initializes contract with initial supply tokens to the creator of the contract */
function CardToken(
uint256 initialSupply,
string tokenName,
string tokenSymbol,
string tokenDescription,
string ipfsHash
) {
balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens
totalSupply = initialSupply; // Update total supply
name = tokenName; // Set the name for display purposes
symbol = tokenSymbol; // Set the symbol for display purposes (first three as name or three char combo)
description = tokenDescription; //Description in gallery
ipfs_hash = ipfsHash;
decimals = 0; // Amount of decimals for display purposes
}
/* Send coins */
function transfer(address _to, uint256 _value) {
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
}
/* Allow another contract to spend some tokens in your behalf */
function approve(address _spender, uint256 _value)
returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
/* Approve and then comunicate the approved contract in a single tx */
function approveAndCall(address _spender, uint256 _value, bytes _extraData)
returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
/* A contract attempts to get the coins */
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (balanceOf[_from] < _value) throw; // Check if the sender has enough
if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
if (_value > allowance[_from][msg.sender]) throw; // Check allowance
balanceOf[_from] -= _value; // Subtract from the sender
balanceOf[_to] += _value; // Add the same to the recipient
allowance[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
}
function mintToken(address target, uint256 mintedAmount) onlyOwner {
if (isLocked) { throw; }
balanceOf[target] += mintedAmount;
totalSupply += mintedAmount;
Transfer(0, this, mintedAmount);
Transfer(this, target, mintedAmount);
}
function lock() onlyOwner {
isLocked = true;
}
function setDescription(string desc) onlyOwner {
description = desc;
}
/* This unnamed function is called whenever someone tries to send ether to it */
function () {
throw; // Prevents accidental sending of ether
}
}
contract CardFactory {
address[] public Cards;
uint256 public CardCount;
function CardFactory() {
CardCount = 0;
}
function CreateCard(uint256 _initialAmount, string _name, string _symbol, string _desc,string _ipfshash) returns (address) {
CardToken newToken = (new CardToken(_initialAmount, _name,_symbol, _desc,_ipfshash));
Cards.push(address(newToken));
CardCount++;
newToken.transferOwnership(msg.sender);
newToken.transfer(msg.sender, _initialAmount); //the factory will own the created tokens. You must transfer them.
return address(newToken);
}
function () {
throw; // Prevents accidental sending of ether
}
}