Skip to content

DD (contract)

The Dollar Day token. See DD token page for the user-facing narrative; this page documents the contract.

contracts/src/core/DD.sol

Inherits

ERC20, ERC20Burnable, ERC20Permit, Ownable2Step, Pausable

Constants

NameValue
ROLE_DELAY7 days

Mutable state

NamePurpose
isMinter[address]Allowlist
bootstrappedTrue after first addMinterInitial
pendingMinterAdd[address]Pending add effective-at
pendingMinterRemove[address]Pending remove effective-at

Mint

solidity
function mint(address to, uint256 amount) external onlyMinter whenNotPaused;

Reverts if !isMinter[msg.sender] or if paused.

Burn

Standard ERC20Burnable:

solidity
function burn(uint256 amount) external;                    // burn from self
function burnFrom(address account, uint256 amount) external;  // with allowance

Burn is not affected by pause — users can always exit positions during a pause.

Pause

solidity
function pause() external onlyOwner;
function unpause() external onlyOwner;

Instant (no timelock — emergency response tool).

Bootstrap

solidity
function addMinterInitial(address minter) external onlyOwner;

Callable exactly once (gated by bootstrapped). Adds the first minter without waiting for the 7-day timelock — used by Deploy.s.sol.

Minter rotation (7-day timelock)

solidity
function proposeMinterAdd(address minter) external onlyOwner;
function activateMinterAdd(address minter) external;             // permissionless after 7d
function cancelMinterAdd(address minter) external onlyOwner;

function proposeMinterRemove(address minter) external onlyOwner;
function activateMinterRemove(address minter) external;
function cancelMinterRemove(address minter) external onlyOwner;

This is the highest-leverage admin path in the protocol — a compromised owner adding their own EOA as a minter would otherwise be able to inflate DD supply at will. The 7-day delay gives the community time to detect and respond.

Permit

ERC20Permit provides EIP-2612 permit, enabling gasless approve flows for DD spending (e.g. bidding without a separate approve tx).

Events

MinterAdded, MinterRemoved,
MinterAddProposed, MinterAddCancelled,
MinterRemoveProposed, MinterRemoveCancelled,
+ standard ERC20 Transfer, Approval, Pausable, Ownable2Step events

Errors

NotMinter, ZeroAddress,
AlreadySet, AlreadyMember, NotMember,
NoPending, TooEarly
+ standard ERC20Pausable errors

Why no hard total-supply cap

An earlier draft had MAX_TOTAL_SUPPLY = 10B × 1e18 baked in. We removed it because it gave a false sense of security against a compromised mint key — 10B is hundreds of times any realistic supply, so it doesn't bind in practice.

The real defences are:

  1. isMinter allowlist — only owner-curated contracts can mint.
  2. Ownable2Step — propose-then-accept for ownership transfer.
  3. Pausable — owner can halt minting in response to a discovered exploit.
  4. 7-day timelock on adding/removing minters.

Decimals

18, like every other ERC-20 in the stack. 1 DD = 1e18 wei = $1 of inference.

Released under the MIT License.