HourGlass

Deployments

Every contract HourGlass has deployed on-chain, with verified source.

HourGlass has no contract logic of its own. What it deploys are its own instances of MetaMask's audited caveat enforcers — unmodified bytecode at a different address — plus the DeleGatorModuleFactory that was missing on Ethereum mainnet.

Why redeploy something that already exists: the enforcer address is the emitter of the caveat events, so an HourGlass-owned instance makes a charge attributable to HourGlass by a single filter, with no central registry. The reasoning is in Analytics and the trust implications in Security.

What "unmodified" means here

Each address below was produced by CREATE2 from the salt bytes32("OURGLASS") and the compiled artifact of the corresponding @metamask/delegation-framework contract. The salt and the creation bytecode fully determine the address, so anyone can recompute it and confirm nothing else was deployed there.

The salt reads OURGLASS, not HOURGLASS: it predates the rename and is baked into every address above. Changing it would produce an entirely different address set, so it stays as deployed. Use OURGLASS when recomputing.

All of them carry verified source on Etherscan (solc 0.8.23, optimizer enabled at 200 runs, EVM version london). Most were accepted as already-verified on submission — Etherscan matched the bytecode against MetaMask's own verified instances, which is exactly the property being claimed.

Because the address depends only on the salt and the bytecode, the same contract has the same address on every chain. The tables below therefore apply to both Ethereum mainnet and Base — a given enforcer is at one address, everywhere.

Ethereum mainnet (chain 1) and Base (chain 8453)

Deployer: 0x2FF0363132d0dc5feb090790C46B77EF1ce96aa2. On Ethereum mainnet, the three enforcers HourGlass delegations reference were deployed 2026-06-25 and the rest of the suite on 2026-07-25. On Base, all 37 were deployed 2026-07-25.

Source is verified on Etherscan for mainnet and on Basescan for Base.

Infrastructure

The DelegationManager is MetaMask's canonical deterministic deployment, identical everywhere. The factory is not deterministic, so it differs per chain. Both factories carry verified source; their code lives in the delegator-safe-module project, not in the Delegation Framework.

ContractChainAddress
DelegationManager (MetaMask, canonical)all0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3
DeleGatorModuleFactoryEthereum mainnet0xbDDE43bCf6Db9DBeB1127E6574CCF70BFb1c2DC3
DeleGatorModuleFactoryBase0x0D0421e43057bf850e243EcDA2AD8966C8D5877B

Enforcers referenced by HourGlass delegations

These three are the ones the app actually routes through — a subscription cap, its optional end date, and the payroll stream.

ContractAddress
ERC20PeriodTransferEnforcer0x11262E3116a50654547AB0A417BE77eB14b9F339
TimestampEnforcer0xF1635460548F44543366ec4453D512a7Ce85Af85
ERC20StreamingEnforcer0xE475D14d61756D6e940B74C20d2E44EB70c71a8D

Rest of the suite

Deployed so that any future delegation shape can reference an HourGlass-owned enforcer without a new deployment round. They are not wired into the app today.

ContractAddress
AllowedCalldataEnforcer0xb418A0C7003F15EEC765D1e1c0E198cA8531fABe
AllowedMethodsEnforcer0x5FFb84883543A9ED068b1D3DB428037e95C1f26A
AllowedTargetsEnforcer0x71832d69693A818C7e6163e632c5e3fBedf65362
ApprovalRevocationEnforcer0xa92E4c2f624ac064875CA92beDa44629958A0803
ArgsEqualityCheckEnforcer0xAF081f825b0Fd4D1cA3b56E2766248A3689Aea4f
BlockNumberEnforcer0xDaE46FC044CC9A03E0274E51c900946F52afC59A
DeployedEnforcer0x0F40211A6E6B68920690f2a0619714283706E7b3
ERC1155BalanceChangeEnforcer0x341CD2A57ececdAbd41D348b7B616C63D3Ba86f7
ERC1155MultiOperationIncreaseBalanceEnforcer0x7a6c0065a6306b93e82E5Dc7BFD871990a0F910E
ERC20BalanceChangeEnforcer0xf069a9da3987eDA46F711dC40012f3674c6Ad517
ERC20MultiOperationIncreaseBalanceEnforcer0xd1f2F8b225e16A1a22E0C760e25B8da5e58fbb88
ERC20TransferAmountEnforcer0xf180Ec5552f7251268540f5D0292e44e6cD37491
ERC721BalanceChangeEnforcer0x3a9aF4D3089F6755f80FF5568268CC1fFd233103
ERC721MultiOperationIncreaseBalanceEnforcer0xF9D8b696eb1FC8E07F17aF2b491B36e63985f814
ERC721TransferEnforcer0x9ACf459b3495626a1Fb7B9e60519582c273295e7
ExactCalldataBatchEnforcer0xE7dB63Ae90BF479Fd3Ca0148Eca73560DD324591
ExactCalldataEnforcer0x0a1A4e45Be9183465c0f4ac7907605269B2a2573
ExactExecutionBatchEnforcer0x1c0e253Ef34F05f9Bb35bc373F811A719478a4BB
ExactExecutionEnforcer0xb0deD8b9f02f8D100078F1AA75Ab9FCDB0D5e729
IdEnforcer0xF60958a138A885FD10418E7b0D76Ceb45AA25605
LimitedCallsEnforcer0x0c6a3a33d02c7bEb6B066960CE92DF8CC8EA35C8
LogicalOrWrapperEnforcer0x3FeDC2610F558E6a0e5c5d9A591E4621C76Ea4f7
MultiTokenPeriodEnforcer0xAA7E306EcBCFF5A5b37BE13d8a4655E0998D8E87
NativeBalanceChangeEnforcer0xF069FB64eFDBdA222a86952fC71E87CC6731d545
NativeTokenMultiOperationIncreaseBalanceEnforcer0x23D27CaFC7968C9C615a2CcDa9Ca80e36A0f76Ba
NativeTokenPaymentEnforcer0xD406D916bA7c155B186639f6f6783A17DFe81B1c
NativeTokenPeriodTransferEnforcer0xe96539D0aB03b9D7Dc45B2326E2FCdb598b721Dc
NativeTokenStreamingEnforcer0xC2db9C9c3fb2d15d67F4B89B61D6C7332C8B866B
NativeTokenTransferAmountEnforcer0x953AB69e4aeE3a5e311261573B826Daf29735e52
NonceEnforcer0x3266A5827F3fFED7c4BBa1a7F461F46C8D2835b6
OwnershipTransferEnforcer0xcA474A11645EeCBC225B60944940f81eCd1A7DF8
RedeemerEnforcer0x787308b5d74797E9FEA19cc186bcF12a19dcABB0
SpecificActionERC20TransferBatchEnforcer0xE9F0fb5011Db7F59763d999470af2b7f586712a0
ValueLteEnforcer0x9Fed2C8Bf48Af2c8C0D7E9aE089523Da78D0A076

Two of them take constructor arguments: LogicalOrWrapperEnforcer receives the DelegationManager, and NativeTokenPaymentEnforcer receives the DelegationManager plus the HourGlass ArgsEqualityCheckEnforcer above — not the canonical one. Both are part of the verified source on Etherscan.

Other chains

Base Sepolia and Ethereum Sepolia use MetaMask's canonical enforcer deployments. No HourGlass-owned instance exists there, so charges on those chains are not attributable by emitter address.

Verifying this yourself

The addresses in this page are the ones the app uses, held in src/config/addresses.ts under chains 1 and 8453. To confirm an address holds what it claims, compare the on-chain bytecode against the corresponding artifact from @metamask/delegation-framework — the deployed runtime code is byte-identical to the audited release.

On this page