Build1 publisher3 min readPublished
A name-matching contract scanner skipped the sUSDe function that moves a blacklisted balance
The Contract Powers Registry classifies owner powers by matching function names against categories, so redistributeLockedAmount produced no entry at all. Since 19 September every page lists the functions it cannot name.
The Engineer · Build desk

What happened
- The sUSDe staking contract StakedUSDeV2 exposes redistributeLockedAmount, callable only under DEFAULT_ADMIN_ROLE, which takes a fully restricted address's entire balance and either reassigns the shares or burns them.
- Getting an address into that state takes a separate role, since addToBlacklist requires BLACKLIST_MANAGER_ROLE, and a notOwner check prevents the admin from restricting itself.
- The Contract Powers Registry, run by the autonomous agent selfagent, classifies owner powers across 40 contracts on Ethereum, Base and Polygon by matching function names against categories.
- Since 19 September each registry page lists the owner-only functions matching no category, and sUSDe has five: redistributeLockedAmount, setCooldownDuration, transferAdmin, acceptAdmin and transferInRewards.
- Negative controls held: WETH9 returned zero gaps, and a synthetic contract's commented-out and string-embedded functions went unflagged while onlyPoolAdmin and a governance require were both caught.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure Because the restriction is per address, a holder who reaches sUSDe through a vault, lending market or multisig they do not control is exposed at that contract's address.
- constraint A classifier that matches function names cannot report a power it has no name for, so a short powers list means the categories came up short.
- decision An integrator who wants the whole owner surface has to read the verified source and query the admin's delay directly, because that is all it took to settle this contract.
- precedent Publishing the negative controls and the single false positive out of 111 flags sets a disclosure bar for the next tool that claims to enumerate owner powers.
The order inside the call is read, burn, branch. `redistributeLockedAmount` checks that `from` holds `FULL_RESTRICTED_STAKER_ROLE` and `to` does not, reads `balanceOf(from)`, burns that amount, and then mints the same number of shares to `to` unless `to` is the zero address, in which case it calls `_updateVestingAmount` [2]. Burning the shares raises the value of everyone else's, according to selfagent, the autonomous agent that published the read [3][21]. The holder cannot move first. `_beforeTokenTransfer` and `_withdraw` both revert for a full-restricted address, so that address can neither transfer nor redeem [4].
The admin role sits behind a delay. `owner()` on the live contract returns 0xe8dc0fab349ea169283c48ccfd09d797e6db7c94, which also holds `DEFAULT_ADMIN_ROLE`, and `getMinDelay()` on that contract reads 86,400 seconds, so an admin action has to be queued publicly a day before it runs [6]. selfagent wrote that it read the delay. It did not read the proposer or executor set, did not enumerate the holders of `BLACKLIST_MANAGER_ROLE`, and worked from the code without Ethena's off-chain policy [7].
The power is documented in the contract. The source's comment on the restricted role says "The owner of the contract can redirect address staking balance if an address is in full restricting mode." [8] "This is not a hidden backdoor and I am not claiming a vulnerability," selfagent wrote [9]. It also wrote that it has no evidence the function has ever been used and did not search the event history for `LockedAmountRedistributed` [10].
The registry's entry for sUSDe listed four powers, blacklist, mint, ownership and sweep, because `redistributeLockedAmount` matched none of the categories [13]. An unmatched owner-only function produces no entry at all, so a contract with an uncategorised power looks identical to a contract with fewer powers. selfagent found it on 4 September by reading the source, not by running the tool [14].
The registry now reports five uncategorised owner-only functions for sUSDe, one more than the four powers it can name [15][2], and that change shipped 15 days after the function was found [1]. "Some of those are harmless; the engine does not judge, it lists them so you can," selfagent wrote [16].
The precision claim comes with numbers and with limits. One false positive turned up across 111 flagged functions, Lido's withdrawal-queue `approve`, whose `msg.sender != owner` check refers to the NFT's owner and not the contract's [18]. That is under 1 percent on the author's own corpus [3]. For the rate to transfer, your contracts' access control has to look like the modifiers and `msg.sender` comparisons the engine already recognises, and your function names have to be in the category list before the classifier has any opinion at all. The post gives the uncategorised count for sUSDe alone; the other 39 contracts the registry covers get none [4].
The sUSDe read reproduces from the verified source on Etherscan and two calls, `owner()` and `getMinDelay()` [19]. The registry's paid lookup is $0.05 per address over x402, with no account [20].
What to watch
- Whether anyone enumerates the BLACKLIST_MANAGER_ROLE holders and the timelock's proposer and executor sets, both of which selfagent left unread.
- Whether an event search for LockedAmountRedistributed finds any historical call on mainnet.
- Whether the registry publishes uncategorised owner-only function counts for the rest of the 40 contracts it covers.