EIP-7730: Proposal for a clear signing standard format for wallets

Ok, a big issue of this ERC in it’s current state is upgrades. Take the following example:

uint256 a = 1;                                                                                
// Original intent: deposit collateral                                                        
// Updated intent: steal funds                                                                
function hi() {                                                                               
                                                                                              
  if (a==1){                                                                                  
    // intent: deposit funds                                                                           
  } else {                                                                                    
    // intent: steal funds                                                                            
  }                                                                                           
} 

In this scenario, the intent can change based on some state variable. I chose this example specifically because it highlights that a function’s intent can change outside of a simple proxy upgrade (which are easier to detect).

The same pattern shows up in:

  • Proxy upgrades — the implementation slot points to new code; selector and parameters are identical, executed bytecode is entirely different.

  • Admin-controlled pause/blacklisttransfer reverts for blacklisted accounts or in paused mode; the displayed “Send tokens” intent becomes false.

  • Fee or routing parameters — a function “swap X for at least Y” silently honors a new fee schedule, or delegatecalls a target whose address is stored in mutable state.

What I’m proposing

A new optional top-level intentMutability field that declares the storage slots whose values bound the displayed intent’s correctness, plus the values witnessed at authoring time:

"intentMutability": {
  "functions": {
    "hi()": {
      "stable": false,
      "stateRefs": [
        {
          "slot": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "expectedValue": "0x0000000000000000000000000000000000000000000000000000000000000001",
          "description": "When slot 0 (`a`) == 1, function deposits collateral. When a != 1, function transfers caller funds to the owner. The owner can change `a`."
        }
      ]
    }
  }
}

Wallets CAN (but not required to, they can do with this information as they please) read each declared slot’s live value and compare to expectedValue before applying the descriptor’s formatting. On mismatch, they downgrade to opaque signing or warn. The check is local — one eth_getStorageAt and a memcmp — so it’s cheap enough to run on every signing.

Absence of intentMutability is treated as “unknown,” not “stable” — wallets warn or downgrade. This is deliberate; the alternative would silently grant every legacy descriptor a trust label it wasn’t authored to bear.

HOWEVER, a wallet can still do whatever they want. If they want to trust an address (like USDC for example, which is behind a proxy and can technically change intent at any time), they may. This will help us prevent lesser-known projects from having their intent verified on the registry, only to rug pull users later once enough wallets have opted in. This also avoids any issues where a wallet wants to upgrade a contract (without malicious intent) and makes the mistake of repurposing a function to do something else (this would be dumb of them, but this is web3, and people do dumb things very often).

The PR

PR: Update ERC-7730: added intent mutability specification by PatrickAlphaC · Pull Request #1738 · ethereum/ERCs · GitHub

Please take a look and review. It includes some examples.

1 Like