Contract signatures: verify validity at the relevant state
A contract signature can be valid in one state and invalid in another without its bytes changing. Research must bind an ERC-1271 validation result to the contract, digest, signature and historical state actually queried. Today’s answer cannot automatically determine what an earlier application was entitled to accept.
The task is to reproduce one validation judgment at two observation points, then identify what the result does and does not establish. It is narrower than reconstructing a whole governance process or inferring the legal identity of a signer.
Preserve the validation tuple
ERC-1271, Specification, defines isValidSignature for a supplied digest and signature, with the bytes4 magic value 0x1626ba7e indicating success. It explicitly permits context-dependent validation, including state, time and signer-authorization conditions. The check must not modify state.
Record network, signing-contract address, exact digest, original signature bytes, block hash and call context. A transaction sender’s EOA signature is another object. Recovering an EOA address locally does not replace the signing contract’s decision when the application relies on contract authorization.
The digest must be the one the application actually verifies. Preserve how the original message and domain produce it. Two readable requests with similar text can hash differently, while one copied digest may have been detached from the request the researcher is discussing.
A hypothetical owner rotation
Assume fictional signing contract W uses a simple policy: recover a signer from the supplied signature and accept only if it equals W’s current authorized owner. This is an assumed implementation, not a requirement that every ERC-1271 wallet follow that rule.
At block H100, Alice is the authorized owner. Signature S for digest D is accepted. At H120, a verified policy update makes Bob the current owner. The same bytes D and S are queried again and rejected under this assumed current-owner rule.
| Observation | Relevant owner state | Result for identical D and S | Research interpretation |
|---|---|---|---|
| H100 | Alice | 0x1626ba7e | W accepts this signature in this state |
| H120 | Bob | 0xffffffff in this example | W does not accept it under the later policy |
| H100 queried through unavailable historical state | Unknown to this call | Retrieval or execution error | Historical validation remains unresolved |
The non-magic value is an example-specific failure response, not a universal required rejection code. The two successful observations of the relevant states establish a change in W’s judgment. They do not prove that Alice never authorized D or that a past application acceptance was retrospectively invalid.
Save both calls as separate evidence records. The state transition is the explanation, not an excuse to overwrite the older result with the latest one.
Decode the return according to its type
Treat the expected bytes4 value as the success criterion. Do not accept any nonzero return or a generic transaction-success flag as signature validity. Preserve raw return data and the decoded value so that an ABI or padding error can be investigated.
Distinguish a non-magic result from a reverted call, a provider error and malformed return data. A revert may arise from invalid signature handling, but an insufficient execution allowance or unavailable historical dependency can also prevent a conclusive check. Diagnose the failure before labeling it a cryptographic rejection.
Use an adequate, documented call environment. If the contract’s logic consults another contract or depends on caller context, preserve those dependencies too. A convenient query performed under different conditions may not reproduce the application’s check.
A different policy can preserve older signatures
Owner rotation does not universally invalidate old signatures. A different contract could accept preapproved digests, historical owner snapshots or another policy explicitly encoded in its implementation. Under such a design, D and S might remain accepted after the current owner changes.
Therefore inspect the actual policy and its effective version. Do not infer the rule solely from a standard interface name. If a proxy or other implementation dependency changed, connect each historical call to the code and configuration relevant then.
An unresolved policy can still support a limited observation: the call returned the magic value at a specified block. It cannot support a broader explanation of why or a forecast that the result will remain stable.
Validation is not consumption or execution
An acceptance query is a check, not evidence that an asset movement happened. It also does not by itself establish that the message has been consumed or cannot be replayed. The consuming application may impose its own nonce, expiry, cancellation or one-use rule.
For example, W can accept D at H100 while an application rejects the corresponding request because its order nonce was already used. Another application can accept the same signature but still fail its transfer because a balance condition is unmet. Keep contract validation, application eligibility and committed execution in separate columns.
These distinctions matter when examining a claimed authorization incident. A screenshot of the magic value does not identify a legal person, prove available collateral or demonstrate a completed loss. Locate the application record and resulting state before making an economic claim.
Separate three dates in the record
The signature’s stated creation time, the state being tested and the date the researcher ran the query can differ. Suppose S was supplied to the analyst at H130 but the query successfully reconstructs H100. The result describes H100; it does not prove that the analyst had inspected S then. Retain evidence availability and contract acceptance as separate histories.
For a stored application receipt, determine whether it records the original validation outcome or recomputes validity against current state when displayed. An interface can show a new answer for an old request without changing what happened at execution. Resolve that distinction before alleging that an old record was altered.
A reproducible validation checklist
| Action | Save | Stop condition |
|---|---|---|
| Fix the signed object | Message construction, domain and digest | Digest cannot be connected to the claimed request |
| Preserve the signature | Exact bytes and sanitized public identifier | Only a truncated screenshot exists |
| Select historical state | Network, W, block hash and implementation | Current state is being attached to an older date |
| Execute the check | Call context, raw return and decoded bytes4 | Provider failure is unresolved |
| Compare states | Policy transition and both result records | Different contexts are being treated as identical |
| Check downstream action | Application nonce, eligibility and receipt | Validation is being counted as execution |
Reopen the record after a policy change, newly recovered historical state, corrected digest or different call result under supposedly identical conditions. Publish which state accepted which signed object, preserving uncertainty about unavailable observations. This describes an auditable authorization decision without converting one standard response into a timeless certificate.
FAQ
Does a valid ERC-1271 result stay valid forever?
Not necessarily. The implementation can depend on state or time. Preserve the observation context and inspect the actual policy.
Does a successful signature check prove the application executed the request?
No. Application eligibility, replay handling and committed execution require their own evidence.