3

I admit my defences were down due to gold checkmark on Twitter. See my video and report to @support: https://twitter.com/marsXRobertson/status/1752663546335224083

I didn't observe any tokens moving yet but the risk is there.

I would like to know what exactly I have signed. Does Metamask keeps the list of signatures?

Bonus / additional / optional question 1️⃣: I can revoke on-chain approvals, is there a way to revoke signtures?

Bonus / additional / optional question 2️⃣: Is there an EIP standard to tell what is the expiry date of a signature?

4
  • Re Q2: the expiry is determined based on what was the content they provided to you for signing. Also, that will be based on which token transfer you signed.
    – Mila A
    Commented Feb 1 at 14:26
  • You should ideally move your funds to a different wallet as soon as you can.
    – Mila A
    Commented Feb 1 at 14:27
  • I can't think of any way to revoke signatures.
    – Mila A
    Commented Feb 1 at 14:28
  • There's no way to check what you signed because Metamask doesn't save that data (reddit.com/r/ethdev/comments/rbvh93/comment/hnt9vd5/…)
    – Mila A
    Commented Feb 1 at 14:30

1 Answer 1

2

"I didn't observe any tokens moving yet but the risk is there."

No doubts! If you own any ERC20 tokens, they absolutely can be targeted by an attack at any moment. It might just be that the scammers have a Pacific timezone, and that explains why they haven't committed the theft yet.

"I would like to know what exactly I have signed. Does Metamask keeps the list of signatures?"

There's no way to see the transactions you already signed, until someone who has access uses your signature for a transfer/permit functionality. There's no way to keep a history of these on-chain, because the signature is partially derived from your private key, and you didn't physically interact with any smart contracts via transactions.

"I can revoke on-chain approvals, is there a way to revoke signatures?"

Unfortunately, there's no way to revoke signatures. Some protocols allow forcibly increasing the nonce of a particular user, to invalidate the signature, but as you don't know what permission you signed, and which group of your funds is vulnerable (ERC20 permit transfers based on ERC-2612 (https://eips.ethereum.org/EIPS/eip-2612), or staking protocols), you cannot perform that kind of invalidation. In addition to that, most protocols don't support the invalidation logic.

Generally, that was proposed by ERC-3009. (https://eips.ethereum.org/EIPS/eip-3009)

"Is there an EIP standard to tell what is the expiry date of a signature?"

No, there's no standard, therefore it should be checked at a protocol/smart contract level (https://stackoverflow.com/questions/68265812/expiry-date-of-signature)

For example, USDC (https://etherscan.io/address/0x43506849d7c04f9138d1a2050bbf3a0c054402dd#code) implemented the "gas-less access" (aka signature) expiry feature in the following way:

/**
     * @inheritdoc FiatTokenV2
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external override whenNotPaused {
        _permit(owner, spender, value, deadline, v, r, s);
    }

/* ... */

/**
     * @notice Verify a signed approval permit and execute if valid
     * @dev EOA wallet signatures should be packed in the order of r, s, v.
     * @param owner      Token owner's address (Authorizer)
     * @param spender    Spender's address
     * @param value      Amount of allowance
     * @param deadline   The time at which the signature expires (unix time), or max uint256 value to signal no expiration
     * @param signature  Signature byte array signed by an EOA wallet or a contract wallet
     */
    function _permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        bytes memory signature
    ) internal {
        require(
            deadline == type(uint256).max || deadline >= now,
            "FiatTokenV2: permit is expired"
        );

        bytes32 typedDataHash = MessageHashUtils.toTypedDataHash(
            _domainSeparator(),
            keccak256(
                abi.encode(
                    PERMIT_TYPEHASH,
                    owner,
                    spender,
                    value,
                    _permitNonces[owner]++,
                    deadline
                )
            )
        );
        require(
            SignatureChecker.isValidSignatureNow(
                owner,
                typedDataHash,
                signature
            ),
            "EIP2612: invalid signature"
        );

        _approve(owner, spender, value);
    }

By the way, USDC does have a signature access invalidation functionality available:

/**
     * @notice Attempt to cancel an authorization
     * @dev Works only if the authorization is not yet used.
     * EOA wallet signatures should be packed in the order of r, s, v.
     * @param authorizer    Authorizer's address
     * @param nonce         Nonce of the authorization
     * @param signature     Signature bytes signed by an EOA wallet or a contract wallet
     */
    function cancelAuthorization(
        address authorizer,
        bytes32 nonce,
        bytes memory signature
    ) external whenNotPaused {
        _cancelAuthorization(authorizer, nonce, signature);
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.