Skip to content

Commit

Permalink
Update EIP-6492: Handle non-ready deployed wallet
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
Agusx1211 committed Jul 8, 2023
1 parent d333f35 commit bb55940
Showing 1 changed file with 22 additions and 5 deletions.
27 changes: 22 additions & 5 deletions EIPS/eip-6492.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ The signing contract will normally be a contract wallet, but it could be any con

- If the contract is deployed, produce a normal [ERC-1271](./eip-1271.md) signature
- If the contract is not deployed yet, wrap the signature as follows: `concat(abi.encode((create2Factory, factoryCalldata, originalERC1271Signature), (address, bytes, bytes)), magicBytes)`
- If the contract is deployed but not ready to verify using [ERC-1271](./eip-1271.md), wrap the signature as follows: `concat(abi.encode((prepareTo, prepareData, originalERC1271Signature), (address, bytes, bytes)), magicBytes)`; `prepareTo` and `prepareData` must contain the necessary transaction that will make the contract ready to verify using [ERC-1271](./eip-1271.md) (e.g. a call to `migrate` or `update`)

Note that we're passing `factoryCalldata` instead of `salt` and `bytecode`. We do this in order to make verification compliant with any factory interface. We do not need to calculate the address based on `create2Factory`/`salt`/`bytecode`, because [ERC-1271](./eip-1271.md) verification presumes we already know the account address we're verifying the signature for.

Expand All @@ -62,6 +63,7 @@ Full signature verification MUST be performed in the following order:

- check if the signature ends with magic bytes, in which case do an `eth_call` to a multicall contract that will call the factory first with the `factoryCalldata` and deploy the contract if it isn't already deployed; Then, call `contract.isValidSignature` as usual with the unwrapped signature
- check if there's contract code at the address. If so perform [ERC-1271](./eip-1271.md) verification as usual by invoking `isValidSignature`
- if the [ERC-1271](./eip-1271.md) verification fails, and the deploy call to the `factory` was skipped due to the wallet already having code, execute the `factoryCalldata` transaction and try `isValidSignature` again
- if there is no contract code at the address, try `ecrecover` verification

## Rationale
Expand All @@ -76,6 +78,8 @@ The order to ensure correct verification is based on the following rules:
- checking for `magicBytes` MUST happen before `ecrecover` in order to avoid trying to verify a counterfactual contract signature via `ecrecover` if such is clearly identifiable
- checking `ecrecover` MUST NOT happen before [ERC-1271](./eip-1271.md) verification, because a contract may use a signature format that also happens to be a valid `ecrecover` signature for an EOA with a different address. One such example is a contract that's a wallet controlled by said EOA.

We can't determine the reason why a signature was encoded with a "deploy prefix" when the corresponding wallet already has code. It could be due to the signature being created before the contract was deployed, or it could be because the contract was deployed but not ready to verify signatures yet. As such, we need to try both options.

## Backwards Compatibility

This ERC is backward compatible with previous work on signature validation, including [ERC-1271](./eip-1271.md) and allows for easy verification of all signature types, including EOA signatures and typed data ([EIP-712](./eip-712.md)).
Expand Down Expand Up @@ -108,7 +112,8 @@ contract UniversalSigValidator {
address _signer,
bytes32 _hash,
bytes calldata _signature,
bool allowSideEffects
bool allowSideEffects,
bool tryPrepare
) public returns (bool) {
uint contractCodeLen = address(_signer).code.length;
bytes memory sigToValidate;
Expand All @@ -122,7 +127,7 @@ contract UniversalSigValidator {
bytes memory factoryCalldata;
(create2Factory, factoryCalldata, sigToValidate) = abi.decode(_signature[0:_signature.length-32], (address, bytes, bytes));
if (contractCodeLen == 0) {
if (contractCodeLen == 0 || tryPrepare) {
(bool success, bytes memory err) = create2Factory.call(factoryCalldata);
if (!success) revert ERC6492DeployFailed(err);
}
Expand All @@ -135,6 +140,11 @@ contract UniversalSigValidator {
try IERC1271Wallet(_signer).isValidSignature(_hash, sigToValidate) returns (bytes4 magicValue) {
bool isValid = magicValue == ERC1271_SUCCESS;
// retry, but this time assume the prefix is a prepare call
if (!isValid && !tryPrepare && contractCodeLen > 0) {
return isValidSigImpl(_signer, _hash, _signature, allowSideEffects, true);
}
if (contractCodeLen == 0 && isCounterfactual && !allowSideEffects) {
// if the call had side effects we need to return the
// result using a `revert` (to undo the state changes)
Expand All @@ -145,7 +155,14 @@ contract UniversalSigValidator {
}
return isValid;
} catch (bytes memory err) { revert ERC1271Revert(err); }
} catch (bytes memory err) {
// retry, but this time assume the prefix is a prepare call
if (!isValid && !tryPrepare && contractCodeLen > 0) {
return isValidSigImpl(_signer, _hash, _signature, allowSideEffects, true);
}
revert ERC1271Revert(err);
}
}
// ecrecover verification
Expand All @@ -162,13 +179,13 @@ contract UniversalSigValidator {
function isValidSigWithSideEffects(address _signer, bytes32 _hash, bytes calldata _signature)
external returns (bool)
{
return this.isValidSigImpl(_signer, _hash, _signature, true);
return this.isValidSigImpl(_signer, _hash, _signature, true, false);
}
function isValidSig(address _signer, bytes32 _hash, bytes calldata _signature)
external returns (bool)
{
try this.isValidSigImpl(_signer, _hash, _signature, false) returns (bool isValid) { return isValid; }
try this.isValidSigImpl(_signer, _hash, _signature, false, false) returns (bool isValid) { return isValid; }
catch (bytes memory error) {
// in order to avoid side effects from the contract getting deployed, the entire call will revert with a single byte result
uint len = error.length;
Expand Down

0 comments on commit bb55940

Please sign in to comment.