Bytecode verified via sibling
This contract shares identical runtime bytecode with GoldTokenLedger (0x99146bab...) which has been verified through compiler archaeology.
DigixDAO gold token: ERC20 with demurrage (actualBalanceOf, storage fee, calculateDemurrage), tx and recast fees read from config. Anthony Eufemio, Jan 2016.
Token Information
Key Facts
Source Verified
Historian Categories
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Frontier Era
The initial release of Ethereum. A bare-bones implementation for technical users.
Bytecode Overview
Verified Source Available
Source verified through compiler archaeology (near-exact bytecode match).
Show source code (Solidity)
// Submitted by EthereumHistory (ethereumhistory.com)
contract DigixConfiguration {
function getConfigEntryAddr(bytes32 _key) public constant returns (address) {}
function getConfigEntryInt(bytes32 _key) public constant returns (uint256) {}
function isAdmin(address _acct) public returns (bool) {}
function getConfigEntryBytes(bytes32 _key) public constant returns (bytes32) {}
}
contract VendorRegistry {
function isVendor(address _vndr) public returns (bool) {}
}
contract CustodianRegistry {
function isCustodian(address _cust) public returns (bool) {}
}
contract AuditorRegistry {
function isAuditor(address _adtr) public returns (bool) {}
}
contract GenericInterface {
address public config;
address public owner;
function getConfigAddress() public returns (address) {
return config;
}
function getOwner() public returns (address) {
return owner;
}
function setOwner(address _newowner) ifowner {
owner = _newowner;
}
function isAdmin(address _acct) public returns (bool) {
return DigixConfiguration(config).isAdmin(_acct);
}
function goldRegistry() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("registry/gold");
}
function vendorRegistry() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("registry/vendor");
}
function custodianRegistry() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("registry/custodian");
}
function auditorRegistry() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("registry/auditor");
}
function goldTokenLedger() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("ledger/token");
}
function recastContract() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("contract/recast");
}
function minterContract() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("contract/minter");
}
function txFeeWallet() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("wallet/txfee");
}
function accountingWallet() public returns (address) {
return DigixConfiguration(config).getConfigEntryAddr("wallet/accounting");
}
function redemptionFee() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/redemptionfee");
}
function recastFee() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/recastfee");
}
function txFee() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/txfee");
}
function txFeeMax() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/txfeemax");
}
function storageRate() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/rate");
}
function getBase() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/base");
}
function billingPeriod() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/billingperiod");
}
function requiredConfirmations() public returns (uint256) {
return DigixConfiguration(config).getConfigEntryInt("settings/confirmations");
}
function nonMintSku() public returns (uint256) {
return uint256(DigixConfiguration(config).getConfigEntryBytes("settings/nonmintsku"));
}
function isGoldRegistry(address _greg) public returns (bool) {
return (goldRegistry() == _greg);
}
function isCustodian(address _cust) public returns (bool) {
return CustodianRegistry(custodianRegistry()).isCustodian(_cust);
}
function isAuditor(address _adtr) public returns (bool) {
return AuditorRegistry(auditorRegistry()).isAuditor(_adtr);
}
function isVendor(address _vndr) public returns (bool) {
return VendorRegistry(vendorRegistry()).isVendor(_vndr);
}
modifier ifvendor { if(isVendor(msg.sender)) _ }
modifier ifowner { if(msg.sender == owner) _ }
modifier ifcustodian { if(isCustodian(msg.sender)) _ }
modifier ifauditor { if(isAuditor(msg.sender)) _ }
modifier ifgoldregistry { if(isGoldRegistry(msg.sender)) _ }
}
contract GoldRegistry {
function getFee(address _gold) public returns (uint256) {}
function unknown65afd0ed(address _gold) public returns (bool) {}
}
contract GoldTokenLedger is GenericInterface {
struct Account {
bool exists;
uint256 balance;
uint256 lastPayDate;
mapping (address => uint256) allowances;
}
uint256 public totalSupply;
mapping (address => Account) accounts;
modifier ifrecast { if (recastContract() == msg.sender) _ }
event Transfer(address indexed _from, address indexed _to, uint256 indexed _value);
event NewAccount(address indexed user);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
function GoldTokenLedger(address _conf) {
owner = msg.sender;
config = _conf;
totalSupply = 0;
newAccount(accountingWallet());
newAccount(txFeeWallet());
}
function newAccount(address _address) internal {
if (userExists(_address)) return;
accounts[_address].balance = 0;
accounts[_address].lastPayDate = block.timestamp;
accounts[_address].exists = true;
NewAccount(_address);
}
function userExists(address _address) public returns (bool) {
return accounts[_address].exists;
}
function actualBalanceOf(address _address) public returns (uint256) {
return accounts[_address].balance;
}
function approve(address _addr, uint256 _val) public returns (bool) {
accounts[msg.sender].allowances[_addr] = _val;
Approval(msg.sender, _addr, _val);
return true;
}
function allowance(address _owner, address _spender) public constant returns (uint256) {
return accounts[_owner].allowances[_spender];
}
function transfer(address _to, uint256 _value) public returns (bool) {
if (_to == 0x0) return false;
if (!userExists(_to)) newAccount(_to);
uint256 _fee = calculateTxFee(_value, msg.sender);
uint256 _total;
if (msg.sender == accountingWallet()) _fee = 0;
if (msg.sender == txFeeWallet()) _fee = 0;
_total = _value + _fee;
if (balanceOf(msg.sender) < _total) return false;
if (!deductFees(msg.sender)) return false;
if (!deductFees(_to)) return false;
accounts[msg.sender].balance -= _total;
accounts[_to].balance += _value;
uint256 _timestamp = block.timestamp;
accounts[txFeeWallet()].balance += _fee;
Transfer(msg.sender, _to, _value);
Transfer(msg.sender, txFeeWallet(), _fee);
return true;
}
function calculateTxFee(uint256 _value, address _user) public constant returns (uint256) {
uint256 _fee;
if (_user == accountingWallet()) return 0;
if (_user == txFeeWallet()) return 0;
_fee = ((_value * txFee()) / getBase());
if (_fee > txFeeMax()) return txFeeMax();
return _fee;
}
function calculateDemurrage(address _address) public constant returns (uint256) {
if (actualBalanceOf(_address) == 0) return 0;
if (_address == accountingWallet()) return 0;
if (_address == txFeeWallet()) return 0;
if (getFeeDays(_address) == 0) return 0;
return demurrageCalc(accounts[_address].balance, getFeeDays(_address));
}
function demurrageCalc(uint256 _balance, uint256 _feedays) public returns (uint256) {
uint256 _rate = storageRate() * _feedays;
return ((_balance * _rate) / getBase());
}
function balanceOf(address _address) public constant returns (uint256) {
if (_address == 0x0) return 0;
if (_address == accountingWallet()) return accounts[accountingWallet()].balance;
if (_address == txFeeWallet()) return accounts[txFeeWallet()].balance;
if (accounts[_address].balance == 0) return 0;
if (getFeeDays(_address) <= 0) return accounts[_address].balance;
return (actualBalanceOf(_address) - calculateDemurrage(_address));
}
function deductFees(address _address) public returns (bool) {
if (_address == accountingWallet()) return true;
if (_address == txFeeWallet()) return true;
if (actualBalanceOf(_address) == 0) {
accounts[_address].lastPayDate = block.timestamp;
return true;
}
if (getFeeDays(_address) == 0) return true;
uint256 _fees = calculateDemurrage(_address);
uint256 _balance = actualBalanceOf(_address);
accounts[_address].balance -= _fees;
accounts[txFeeWallet()].balance += _fees;
uint256 _remainder = block.timestamp - (accounts[_address].lastPayDate + (getFeeDays(_address) * billingPeriod()));
accounts[_address].lastPayDate = block.timestamp - _remainder;
Transfer(_address, txFeeWallet(), _fees);
return true;
}
function getFeeDays(address _address) public returns (uint256) {
return ((block.timestamp - accounts[_address].lastPayDate) / billingPeriod());
}
function payStorageFee(address _gold) public {
uint256 _fee = GoldRegistry(goldRegistry()).getFee(_gold);
if (!userExists(tx.origin)) newAccount(tx.origin);
if (!deductFees(tx.origin)) throw;
if (balanceOf(tx.origin) < _fee) throw;
if (!GoldRegistry(goldRegistry()).unknown65afd0ed(_gold)) throw;
accounts[tx.origin].balance -= _fee;
accounts[accountingWallet()].balance += _fee;
Transfer(tx.origin, accountingWallet(), _fee);
}
function ledgerMint(address _gold, address _user, uint256 _tokens, uint256 _fees) public ifgoldregistry returns (bool) {
if (!userExists(_user)) newAccount(_user);
if (!deductFees(_user)) return false;
accounts[accountingWallet()].balance += _fees;
Transfer(tx.origin, accountingWallet(), _fees);
accounts[_user].balance += (_tokens - _fees);
uint256 _total = (_tokens + _fees);
totalSupply += _total;
Transfer(minterContract(), tx.origin, (_tokens - _fees));
return true;
}
function recastCall(address _gold, address _user, uint256 _tokens, uint256 _recastfee) public ifrecast returns (bool) {
if (!userExists(_user)) newAccount(_user);
uint256 _total = _tokens + _recastfee;
if (balanceOf(_user) < _total) return false;
if (!deductFees(_user)) return false;
accounts[_user].balance -= _total;
accounts[accountingWallet()].balance += _recastfee;
totalSupply -= _tokens;
Transfer(tx.origin, accountingWallet(), _recastfee);
Transfer(tx.origin, 0x0, _tokens);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
if (_to == 0x0) return false;
if (!userExists(_to)) newAccount(_to);
uint256 _fee = calculateTxFee(_value, _from);
uint256 _total;
if (_from == accountingWallet()) _fee = 0;
if (_from == txFeeWallet()) _fee = 0;
_total = _value + _fee;
if (accounts[_from].allowances[msg.sender] < _total) return false;
if (balanceOf(_from) < _total) return false;
if (!deductFees(_from)) return false;
if (!deductFees(_to)) return false;
accounts[_from].balance -= _total;
accounts[_to].balance += _value;
uint256 _timestamp = block.timestamp;
accounts[txFeeWallet()].balance += _fee;
Transfer(msg.sender, _to, _value);
Transfer(msg.sender, txFeeWallet(), _fee);
return true;
}
}External Links
Related contracts
Directory
Same deployerDigixDAO typed-collection storage library (Address to bytes/address/bool maps; insert/remove/contains). Anthony Eufemio, Nov 2015. 1 of 9 clones.
0xbce3b5...64bac0January 9, 2016Ledger Storage
Same deployerDigixDAO marketplace ledger storage: maps (uint256 id, address) to records of amount, timestamp and state. Anthony Eufemio, Jan 2016. 7 identical clones.
0x35e1d3...7c2e6dJanuary 9, 2016DigixConfiguration
Same deployerDigixDAO owner + admin-ACL config registry (typed key/value store). CALLCODEs a Directory library clone for its admin set. Anthony Eufemio, Jan 2016.
0xc0a2b0...dfbf56January 9, 2016Directory
Same deployerDigixDAO typed-collection storage library (Address to bytes/address/bool maps; insert/remove/contains). Anthony Eufemio, Nov 2015. 1 of 9 clones.
0x6fb339...164bd9January 9, 2016Ledger Storage
Same deployerDigixDAO marketplace ledger storage: maps (uint256 id, address) to records of amount, timestamp and state. Anthony Eufemio, Jan 2016. 7 identical clones.
0x4c8e1e...92b8d9January 9, 2016DigixConfiguration
Same deployerDigixDAO owner + admin-ACL config registry (typed key/value store). CALLCODEs a Directory library clone for its admin set. Anthony Eufemio, Jan 2016.
0x2f7764...ff9d6cJanuary 9, 2016