Contract Source Code:
File 1 of 1 : Token
pragma solidity ^0.4.19;
/// @title Contract Resolver Interface
/// @author Digix Holdings Pte Ltd
contract ResolverClient {
/// The address of the resolver contract for this project
address public resolver;
/// The key to identify this contract
bytes32 public key;
/// Make our own address available to us as a constant
address public CONTRACT_ADDRESS;
/// Function modifier to check if msg.sender corresponds to the resolved address of a given key
/// @param _contract The resolver key
modifier if_sender_is(bytes32 _contract) {
require(msg.sender == ContractResolver(resolver).get_contract(_contract));
_;
}
/// Function modifier to check resolver's locking status.
modifier unless_resolver_is_locked() {
require(is_locked() == false);
_;
}
/// @dev Initialize new contract
/// @param _key the resolver key for this contract
/// @return _success if the initialization is successful
function init(bytes32 _key, address _resolver)
internal
returns (bool _success)
{
bool _is_locked = ContractResolver(_resolver).locked();
if (_is_locked == false) {
CONTRACT_ADDRESS = address(this);
resolver = _resolver;
key = _key;
require(ContractResolver(resolver).init_register_contract(key, CONTRACT_ADDRESS));
_success = true;
} else {
_success = false;
}
}
/// @dev Destroy the contract and unregister self from the ContractResolver
/// @dev Can only be called by the owner of ContractResolver
function destroy()
public
returns (bool _success)
{
bool _is_locked = ContractResolver(resolver).locked();
require(!_is_locked);
address _owner_of_contract_resolver = ContractResolver(resolver).owner();
require(msg.sender == _owner_of_contract_resolver);
_success = ContractResolver(resolver).unregister_contract(key);
require(_success);
selfdestruct(_owner_of_contract_resolver);
}
/// @dev Check if resolver is locked
/// @return _locked if the resolver is currently locked
function is_locked()
private
constant
returns (bool _locked)
{
_locked = ContractResolver(resolver).locked();
}
/// @dev Get the address of a contract
/// @param _key the resolver key to look up
/// @return _contract the address of the contract
function get_contract(bytes32 _key)
public
constant
returns (address _contract)
{
_contract = ContractResolver(resolver).get_contract(_key);
}
}
contract ContractResolver {
address public owner;
bool public locked;
function init_register_contract(bytes32 _key, address _contract_address)
public
returns (bool _success) {}
/// @dev Unregister a contract. This can only be called from the contract with the key itself
/// @param _key the bytestring of the contract name
/// @return _success if the operation is successful
function unregister_contract(bytes32 _key)
public
returns (bool _success) {}
/// @dev Get address of a contract
/// @param _key the bytestring name of the contract to look up
/// @return _contract the address of the contract
function get_contract(bytes32 _key)
public
constant
returns (address _contract) {}
}
contract DigixConstants {
/// general constants
uint256 constant SECONDS_IN_A_DAY = 24 * 60 * 60;
/// asset events
uint256 constant ASSET_EVENT_CREATED_VENDOR_ORDER = 1;
uint256 constant ASSET_EVENT_CREATED_TRANSFER_ORDER = 2;
uint256 constant ASSET_EVENT_CREATED_REPLACEMENT_ORDER = 3;
uint256 constant ASSET_EVENT_FULFILLED_VENDOR_ORDER = 4;
uint256 constant ASSET_EVENT_FULFILLED_TRANSFER_ORDER = 5;
uint256 constant ASSET_EVENT_FULFILLED_REPLACEMENT_ORDER = 6;
uint256 constant ASSET_EVENT_MINTED = 7;
uint256 constant ASSET_EVENT_MINTED_REPLACEMENT = 8;
uint256 constant ASSET_EVENT_RECASTED = 9;
uint256 constant ASSET_EVENT_REDEEMED = 10;
uint256 constant ASSET_EVENT_FAILED_AUDIT = 11;
uint256 constant ASSET_EVENT_ADMIN_FAILED = 12;
uint256 constant ASSET_EVENT_REMINTED = 13;
/// roles
uint256 constant ROLE_ZERO_ANYONE = 0;
uint256 constant ROLE_ROOT = 1;
uint256 constant ROLE_VENDOR = 2;
uint256 constant ROLE_XFERAUTH = 3;
uint256 constant ROLE_POPADMIN = 4;
uint256 constant ROLE_CUSTODIAN = 5;
uint256 constant ROLE_AUDITOR = 6;
uint256 constant ROLE_MARKETPLACE_ADMIN = 7;
uint256 constant ROLE_KYC_ADMIN = 8;
uint256 constant ROLE_FEES_ADMIN = 9;
uint256 constant ROLE_DOCS_UPLOADER = 10;
uint256 constant ROLE_KYC_RECASTER = 11;
uint256 constant ROLE_FEES_DISTRIBUTION_ADMIN = 12;
/// states
uint256 constant STATE_ZERO_UNDEFINED = 0;
uint256 constant STATE_CREATED = 1;
uint256 constant STATE_VENDOR_ORDER = 2;
uint256 constant STATE_TRANSFER = 3;
uint256 constant STATE_CUSTODIAN_DELIVERY = 4;
uint256 constant STATE_MINTED = 5;
uint256 constant STATE_AUDIT_FAILURE = 6;
uint256 constant STATE_REPLACEMENT_ORDER = 7;
uint256 constant STATE_REPLACEMENT_DELIVERY = 8;
uint256 constant STATE_RECASTED = 9;
uint256 constant STATE_REDEEMED = 10;
uint256 constant STATE_ADMIN_FAILURE = 11;
/// interactive contracts
bytes32 constant CONTRACT_INTERACTIVE_ASSETS_EXPLORER = "i:asset:explorer";
bytes32 constant CONTRACT_INTERACTIVE_DIGIX_DIRECTORY = "i:directory";
bytes32 constant CONTRACT_INTERACTIVE_MARKETPLACE = "i:mp";
bytes32 constant CONTRACT_INTERACTIVE_MARKETPLACE_ADMIN = "i:mpadmin";
bytes32 constant CONTRACT_INTERACTIVE_POPADMIN = "i:popadmin";
bytes32 constant CONTRACT_INTERACTIVE_PRODUCTS_LIST = "i:products";
bytes32 constant CONTRACT_INTERACTIVE_TOKEN = "i:token";
bytes32 constant CONTRACT_INTERACTIVE_BULK_WRAPPER = "i:bulk-wrapper";
bytes32 constant CONTRACT_INTERACTIVE_TOKEN_CONFIG = "i:token:config";
bytes32 constant CONTRACT_INTERACTIVE_TOKEN_INFORMATION = "i:token:information";
bytes32 constant CONTRACT_INTERACTIVE_MARKETPLACE_INFORMATION = "i:mp:information";
bytes32 constant CONTRACT_INTERACTIVE_IDENTITY = "i:identity";
/// controller contracts
bytes32 constant CONTRACT_CONTROLLER_ASSETS = "c:asset";
bytes32 constant CONTRACT_CONTROLLER_ASSETS_RECAST = "c:asset:recast";
bytes32 constant CONTRACT_CONTROLLER_ASSETS_EXPLORER = "c:explorer";
bytes32 constant CONTRACT_CONTROLLER_DIGIX_DIRECTORY = "c:directory";
bytes32 constant CONTRACT_CONTROLLER_MARKETPLACE = "c:mp";
bytes32 constant CONTRACT_CONTROLLER_MARKETPLACE_ADMIN = "c:mpadmin";
bytes32 constant CONTRACT_CONTROLLER_PRODUCTS_LIST = "c:products";
bytes32 constant CONTRACT_CONTROLLER_TOKEN_APPROVAL = "c:token:approval";
bytes32 constant CONTRACT_CONTROLLER_TOKEN_CONFIG = "c:token:config";
bytes32 constant CONTRACT_CONTROLLER_TOKEN_INFO = "c:token:info";
bytes32 constant CONTRACT_CONTROLLER_TOKEN_TRANSFER = "c:token:transfer";
bytes32 constant CONTRACT_CONTROLLER_JOB_ID = "c:jobid";
bytes32 constant CONTRACT_CONTROLLER_IDENTITY = "c:identity";
/// storage contracts
bytes32 constant CONTRACT_STORAGE_ASSETS = "s:asset";
bytes32 constant CONTRACT_STORAGE_ASSET_EVENTS = "s:asset:events";
bytes32 constant CONTRACT_STORAGE_DIGIX_DIRECTORY = "s:directory";
bytes32 constant CONTRACT_STORAGE_MARKETPLACE = "s:mp";
bytes32 constant CONTRACT_STORAGE_PRODUCTS_LIST = "s:products";
bytes32 constant CONTRACT_STORAGE_GOLD_TOKEN = "s:goldtoken";
bytes32 constant CONTRACT_STORAGE_JOB_ID = "s:jobid";
bytes32 constant CONTRACT_STORAGE_IDENTITY = "s:identity";
/// service contracts
bytes32 constant CONTRACT_SERVICE_TOKEN_DEMURRAGE = "sv:tdemurrage";
bytes32 constant CONTRACT_SERVICE_MARKETPLACE = "sv:mp";
bytes32 constant CONTRACT_SERVICE_DIRECTORY = "sv:directory";
/// fees distributors
bytes32 constant CONTRACT_DEMURRAGE_FEES_DISTRIBUTOR = "fees:distributor:demurrage";
bytes32 constant CONTRACT_RECAST_FEES_DISTRIBUTOR = "fees:distributor:recast";
bytes32 constant CONTRACT_TRANSFER_FEES_DISTRIBUTOR = "fees:distributor:transfer";
}
contract TokenLoggerCallback is ResolverClient, DigixConstants {
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
function log_mint(address _to, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_ASSETS)
public
{
Transfer(address(0x0), _to, _value);
}
function log_recast_fees(address _from, address _to, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_ASSETS_RECAST)
public
{
Transfer(_from, _to, _value);
}
function log_recast(address _from, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_ASSETS_RECAST)
public
{
Transfer(_from, address(0x0), _value);
}
function log_demurrage_fees(address _from, address _to, uint256 _value)
if_sender_is(CONTRACT_SERVICE_TOKEN_DEMURRAGE)
public
{
Transfer(_from, _to, _value);
}
function log_move_fees(address _from, address _to, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_TOKEN_CONFIG)
public
{
Transfer(_from, _to, _value);
}
function log_transfer(address _from, address _to, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_TOKEN_TRANSFER)
public
{
Transfer(_from, _to, _value);
}
function log_approve(address _owner, address _spender, uint256 _value)
if_sender_is(CONTRACT_CONTROLLER_TOKEN_APPROVAL)
public
{
Approval(_owner, _spender, _value);
}
}
contract TokenInfoController {
function get_total_supply() constant public returns (uint256 _total_supply){}
function get_allowance(address _account, address _spender) constant public returns (uint256 _allowance){}
function get_balance(address _user) constant public returns (uint256 _actual_balance){}
}
contract TokenTransferController {
function put_transfer(address _sender, address _recipient, address _spender, uint256 _amount, bool _transfer_from) public returns (bool _success){}
}
contract TokenApprovalController {
function approve(address _account, address _spender, uint256 _amount) public returns (bool _success){}
}
/// The interface of a contract that can receive tokens from transferAndCall()
contract TokenReceiver {
function tokenFallback(address from, uint256 amount, bytes32 data) public returns (bool success);
}
/// @title DGX2.0 ERC-20 Token. ERC-677 is also implemented https://github.com/ethereum/EIPs/issues/677
/// @author Digix Holdings Pte Ltd
contract Token is TokenLoggerCallback {
string public constant name = "Digix Gold Token";
string public constant symbol = "DGX";
uint8 public constant decimals = 9;
function Token(address _resolver) public
{
require(init(CONTRACT_INTERACTIVE_TOKEN, _resolver));
}
/// @notice show the total supply of gold tokens
/// @return {
/// "totalSupply": "total number of tokens"
/// }
function totalSupply()
constant
public
returns (uint256 _total_supply)
{
_total_supply = TokenInfoController(get_contract(CONTRACT_CONTROLLER_TOKEN_INFO)).get_total_supply();
}
/// @notice display balance of given account
/// @param _owner the account to query
/// @return {
/// "balance": "balance of the given account in nanograms"
/// }
function balanceOf(address _owner)
constant
public
returns (uint256 balance)
{
balance = TokenInfoController(get_contract(CONTRACT_CONTROLLER_TOKEN_INFO)).get_balance(_owner);
}
/// @notice transfer amount to account
/// @param _to account to send to
/// @param _value the amount in nanograms to send
/// @return {
/// "success": "returns true if successful"
/// }
function transfer(address _to, uint256 _value)
public
returns (bool success)
{
success =
TokenTransferController(get_contract(CONTRACT_CONTROLLER_TOKEN_TRANSFER)).put_transfer(msg.sender, _to, 0x0, _value, false);
}
/// @notice transfer amount to account from account deducting from spender allowance
/// @param _to account to send to
/// @param _from account to send from
/// @param _value the amount in nanograms to send
/// @return {
/// "success": "returns true if successful"
/// }
function transferFrom(address _from, address _to, uint256 _value)
public
returns (bool success)
{
success =
TokenTransferController(get_contract(CONTRACT_CONTROLLER_TOKEN_TRANSFER)).put_transfer(_from, _to, msg.sender,
_value, true);
}
/// @notice implements transferAndCall() of ERC677
/// @param _receiver the contract to receive the token
/// @param _amount the amount of tokens to be transfered
/// @param _data the data to be passed to the tokenFallback function of the receiving contract
/// @return {
/// "success": "returns true if successful"
/// }
function transferAndCall(address _receiver, uint256 _amount, bytes32 _data)
public
returns (bool success)
{
transfer(_receiver, _amount);
success = TokenReceiver(_receiver).tokenFallback(msg.sender, _amount, _data);
require(success);
}
/// @notice approve given spender to transfer given amount this will set allowance to 0 if current value is non-zero
/// @param _spender the account that is given an allowance
/// @param _value the amount in nanograms to approve
/// @return {
/// "success": "returns true if successful"
/// }
function approve(address _spender, uint256 _value)
public
returns (bool success)
{
success = TokenApprovalController(get_contract(CONTRACT_CONTROLLER_TOKEN_APPROVAL)).approve(msg.sender, _spender, _value);
}
/// @notice check the spending allowance of a given user from a given account
/// @param _owner the account to spend from
/// @param _spender the spender
/// @return {
/// "remaining": "the remaining allowance in nanograms"
/// }
function allowance(address _owner, address _spender)
constant
public
returns (uint256 remaining)
{
remaining = TokenInfoController(get_contract(CONTRACT_CONTROLLER_TOKEN_INFO)).get_allowance(_owner, _spender);
}
}