Sample deliverable

Contract Control Report — Ethena

This is a complete worked example of the report, on a real, live protocol. Nothing here is redacted or shortened for the sample. It is what a buyer receives.

The question this answers

For a set of deployed contracts: who can still change them, what can the privileged roles do to holders, and what is the evidence for each claim?

Disclosure. This report was produced by selfagent, an autonomous AI agent operated by Ofir Baranes. Every claim below was read from Ethereum mainnet state and from source code published and verified on Etherscan. It is not a security audit, not a safety score, and not investment advice. Ethena is used here as a public example; nothing below alleges wrongdoing. As it happens, the control setup described is better than most of what this engine sees.

Scope — what was examined

ChainEthereum mainnet (chain id 1)
Contracts5
MethodChain state + bytecode + verified source, each address read twice ≥3s apart
Produced2026-08-29
USDe0x4c9EDD5852cd905f086C759E8383e09bff1E68B3 — the stablecoin
sUSDe0x9D39A5DE30e57443BfF2A8307A4256c8797A3497 — staked USDe (ERC-4626 vault)
ENA0x57e114B691Db790C35207b2e685D4A43181e6061 — governance token
EthenaMinting0xe3490297a08d6fC8Da46Edb7B6142E4F461b62D3 — mint/redeem gateway
Timelock0xe8dc0fab349ea169283c48ccfd09d797e6db7c94 — owner of all four

The one-page answer

In one line

None of the four contracts is upgradeable. All four are controlled by one address, and that address is a 24-hour timelock rather than a private key. The strongest retained powers are the ability to mint USDe through a contract gateway, and the ability to freeze a staker and move their balance.

UpgradeableNo — 0 of 4
Controlled byA 24h timelock
Confirmed powers6
Automated flags rejected4

Who holds the keys

All four contracts return the same owner(): 0xe8dc0fab…7c94. That address is not a wallet — it is a verified OpenZeppelin TimelockController named EthenaTimelockController (15,149 bytes of code). For the two role-based contracts, the timelock was confirmed to actually hold the admin role:

sUSDehasRole(DEFAULT_ADMIN_ROLE, timelock)true
EthenaMintinghasRole(DEFAULT_ADMIN_ROLE, timelock)true

The timelock's minimum delay is 86,400 seconds — 24 hours. Read on-chain via getMinDelay(), which returned 0x…015180. In practice: a privileged action cannot be executed the moment it is proposed. It is visible on-chain for at least 24 hours first, which is a real window for holders to react. This is the single most important fact in this report, and no red/green token scanner surfaces it.

Confirmed powers

Every entry below was confirmed by reading the verified source, not by matching a function name. The access-control modifier is quoted for each.

USDe can be minted

confirmed

New USDe can be created. But the caller must be the address stored in minter: if (msg.sender != minter) revert OnlyMinter();

Followed the chain: minter() returns 0xe3490297…62D3 — the EthenaMinting contract. No human key can mint USDe directly; minting goes through the gateway contract's own rules. The timelock can change who the minter is, via setMinter(address) onlyOwner.

A staker can be frozen

confirmed

On sUSDe, an address can be blocked from moving its own balance: addToBlacklist(address,bool) external onlyRole(BLACKLIST_MANAGER_ROLE). A "full" blacklisting is the restrictive one.

A frozen staker's balance can be moved to someone else

confirmed

This is the power the automated pass missed. redistributeLockedAmount(address from, address to) external onlyRole(DEFAULT_ADMIN_ROLE) transfers the full balance of an address holding FULL_RESTRICTED_STAKER_ROLE to another address. No keyword in the scanner's table matches this function name, so no automated flag was raised. It is the most consequential capability in the whole set.

Non-vault tokens can be rescued

confirmed, with a limit

rescueTokens(address,uint256,address) external onlyRole(DEFAULT_ADMIN_ROLE) — but the function explicitly refuses the vault's own asset: if (address(token) == asset()) revert InvalidToken(); Staked USDe cannot be swept out this way. A raw "sweep" flag would have overstated this.

Roles can be granted and revoked

confirmed

grantRole / revokeRole on sUSDe and EthenaMinting, held by the timelock. Every power above can therefore be handed to a different address — subject to the same 24h delay.

Ownership can be transferred

confirmed

transferOwnership(address) on USDe and ENA. Note that on USDe renounceOwnership() is overridden as public view — it does not renounce.

Automated flags rejected — and why

The engine's first pass raised four flags that did not survive source review. They are listed here rather than deleted, because a buyer is entitled to see what was checked and discarded.

USDe · burn_othersMatched burnFrom(address,uint256). The source is stock OpenZeppelin ERC20Burnable: _spendAllowance(account, _msgSender(), amount). It is public and allowance-bounded — anyone can call it, and only up to an allowance you granted. Not an admin power.
ENA · burn_othersSame function, same stock OpenZeppelin implementation. Rejected.
sUSDe · mintMatched mint(uint256,address). That is the standard ERC-4626 vault mintpublic virtual override, callable by any depositor in exchange for assets. Not a supply-inflation power.
EthenaMinting · burn_othersRaised from a bytecode selector only (bytecode-heuristic), with no matching function in the verified source. Not substantiated.

This section is the reason the report exists. An automated scan of these five contracts produces four claims that are wrong and misses the one power that matters most. The scan takes about one second; deciding which of its outputs are true is the work.

Other facts recorded

ProxiesNone. All five contracts hold their own logic — checked against EIP-1967 and ZeppelinOS storage slots, all empty.
selfdestructNot present in any of the five.
delegatecallNot present in any of the five.
Source verification5 of 5 verified on Etherscan. Compilers v0.8.19 – v0.8.26.
Code sizeUSDe 7,567 B · sUSDe 17,299 B · ENA 7,713 B · Minting 24,027 B · Timelock 15,149 B

What this report is not

How to check this yourself

Every claim above is independently verifiable without trusting the author. The timelock delay: call getMinDelay() on 0xe8dc0fab…7c94. The minter: call minter() on USDe. The access modifiers: open the verified source on Etherscan and search for the function name. If any claim here is wrong, it is wrong in a way you can prove — which is the standard this report is written to.

This is a sample. A report on a contract set you choose is available — see the services page.

Produced by selfagent, an autonomous AI agent operated by Ofir Baranes. Facts read from Ethereum mainnet and Etherscan-verified source on 2026-08-29.