Skip to content

cartoonitunes/dgx-goldtokenledger-verification

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

DGX GoldTokenLedger - Source Reconstruction

Contract: 0x55b9a11c2e8351b4ffc7b11561148bfac9977855 Compiler: solc 0.3.6 native, --optimize --optimize-runs=1 Runtime bytecode: 6,770 bytes Verification status: Source reconstructed. All 44 function names known. Compiler identified by matching dispatcher prefix (60606040523615...), v0.3.x gas stipend (PUSH2 0x61da GAS SUB CALL), and constant-optimizer multiplication trick (PUSH1 X PUSH1 0x02 EXP PUSH<n> Y MUL). Reconstructed source compiles to 6,483 bytes (287 short of target); the remaining gap is in shared subroutines that the optimizer creates from cross-function CSE patterns we have not been able to reproduce without the original source structure.

About

The DGX GoldTokenLedger is the core token contract of Digix Global's gold-backed token system, deployed on Ethereum mainnet in early 2016. Digix was one of the first projects to tokenize a real-world asset on Ethereum, representing physical gold bars stored in vaults in Singapore.

The contract implements an ERC20-like token with:

  • Demurrage fees - storage costs that accrue over time based on token balance and holding period
  • Transaction fees - percentage-based fees on transfers, capped at a maximum
  • Custodian/vendor/auditor roles - verified through linked registry contracts
  • Minting - controlled through a separate gold registry contract
  • Recasting - converting tokens back to physical gold through a recast contract

All configuration (fee rates, wallet addresses, role registries) is read from an on-chain config contract, making the system modular.

Source reconstruction

All 44 public function dispatch entries were identified by reverse-engineering the on-chain bytecode. The source in GoldTokenLedger.sol reproduces the full contract logic.

Selector 0x65afd0ed = regFeePayment

The selector 0x65afd0ed was the last unknown name on the contract — not present in 4byte.directory and over 17,000 brute-force name guesses returned no match. Anthony Eufemio (Digix CTO) provided the original function name and the exact payStorageFee implementation, confirming:

  • Selector 0x65afd0ed = regFeePayment(address) on the GoldRegistry
  • The token-side payStorageFee implementation, including variable names (_gold, _sfee) and the use of addUser, deductFees, and balanceOf helpers

The reconstructed source now reflects these exact names and structure.

All 44 function selectors

Selector Function
0x012beac9 vendorRegistry()
0x0627f5a9 getFeeDays(address)
0x095ea7b3 approve(address,uint256)
0x0e666e49 userExists(address)
0x13af4035 setOwner(address)
0x17a950ac actualBalanceOf(address)
0x18160ddd totalSupply()
0x23b872dd transferFrom(address,address,uint256)
0x24d7806c isAdmin(address)
0x28b2362f custodianRegistry()
0x35c80c8c isCustodian(address)
0x377141d9 calculateDemurrage(address)
0x3ec27341 getConfigAddress()
0x458f5815 redemptionFee()
0x46396e18 goldTokenLedger()
0x49b90557 isAuditor(address)
0x4a619fa6 txFeeWallet()
0x4e03ab49 accountingWallet()
0x4e0fb2a4 auditRelease()
0x64e1721c ledgerMint(address,address,uint256,uint256)
0x65448a76 storageRate()
0x694d98e5 recastContract()
0x6d786740 billingPeriod()
0x70a08231 balanceOf(address)
0x79502c55 config()
0x7d92f6be goldRegistry()
0x82e717f7 requiredConfirmations()
0x893d20e8 getOwner()
0x8da5cb5b owner()
0x8facfa01 deductFees(address)
0x92f00233 minterContract()
0x9dec628b demurrageCalc(uint256,uint256)
0xa9059cbb transfer(address,uint256)
0xc1a27089 recastFee()
0xc8028bee auditorRegistry()
0xcf820461 txFee()
0xd104a136 getBase()
0xd3dd22da txFeeMax()
0xd60f66de recastCall(address,address,uint256,uint256)
0xdd62ed3e allowance(address,address)
0xec1d9bf4 isGoldRegistry(address)
0xee54d54f isVendor(address)
0xfae9d06d calculateTxFee(uint256,address)
0xfd6e248e payStorageFee(address)

Linked contracts

Contract Address Role
Config 0x8568f930a560e4b84147d291342655a75d4f69a9 Configuration registry
Config helper 0x9988ffccd8620f49e355915fdbcc28d54b68cc98 Config accessor
Gold Registry 0x782059ecf4d5dc7fc2079c191917de44638c4d38 Fee management, role verification
Recast contract 0xb1d9062c1ebb025b62018b40af2f563599acf602 Token recasting
Minter contract 0xf58b008970f45b9de73a65c9f80307c20527a0f5 Token minting
Payment history 0x55dbd10c0e2ca1e86b2c5045d0c0a53059f3a816 Stores fee payment timestamps

payStorageFee flow

payStorageFee(_gold)
  -> GoldRegistry.getFee(_gold)           // get fee amount (_sfee)
  -> addUser(tx.origin) if new            // create account if first interaction
  -> deductFees(tx.origin)                // settle accrued demurrage
  -> check balanceOf(tx.origin) >= _sfee  // revert if insufficient
  -> GoldRegistry.regFeePayment(_gold)    // 0x65afd0ed - record timestamp
  -> deduct _sfee from tx.origin
  -> credit _sfee to accounting wallet
  -> emit Transfer event

Compiler identification

Three signatures in the on-chain bytecode pin down the compiler:

  1. Dispatcher prefix 60606040523615 6101f8 57 60e060020a 600035 04 63... — pre-v0.4.8 (no 63ffffffff AND-mask) and pre-v0.4.0 (no payable value-checks before each function entry).
  2. Gas stipend every external call uses PUSH2 0x61da GAS SUB CALL (gas - 25050). v0.4.x changed this to PUSH1 0x32 GAS SUB CALL (gas - 50). The 0x61da value is the v0.3.x signature.
  3. Constant optimizer every 14-22 byte string literal is encoded as PUSH1 X PUSH1 0x02 EXP PUSH<n> Y MUL instead of PUSH32 LITERAL, saving 11 bytes per literal. This pass only fires under --optimize-runs=1 (size-optimized). With default --optimize-runs=200, the same compiler emits PUSH32 directly.

Recompiling our reconstructed source with solc-0.3.6 --optimize --optimize-runs=1 reproduces all three signatures. Other versions miss at least one: v0.3.0–v0.3.5 don't apply the constant optimizer here even with --optimize-runs=1; v0.4.0–v0.4.7 add value-checks unless every function is payable; v0.4.8+ insert the 63ffffffff mask.

Attribution

Source reconstructed by EthereumHistory via bytecode reverse engineering. The function name regFeePayment for selector 0x65afd0ed and the exact payStorageFee implementation were provided by Anthony Eufemio (Digix CTO). Compiler identification (solc 0.3.6 --optimize-runs=1) was bracketed by sweeping prefix/gas-stipend/constant-optimizer signatures across solc 0.1.1 through 0.4.21.

About

DGX GoldTokenLedger (0x55b9a11c) source reconstruction — Digix gold-backed token, all 44 functions identified

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors