// As per ERC-1271
// 按照 ERC-1271
interfaceIERC1271Wallet{functionisValidSignature(bytes32hash,bytescalldatasignature)externalviewreturns(bytes4magicValue);}errorERC1271Revert(byteserror);errorERC6492DeployFailed(byteserror);contractUniversalSigValidator{bytes32privateconstantERC6492_DETECTION_SUFFIX=0x6492649264926492649264926492649264926492649264926492649264926492;bytes4privateconstantERC1271_SUCCESS=0x1626ba7e;functionisValidSigImpl(address_signer,bytes32_hash,bytescalldata_signature,boolallowSideEffects,booltryPrepare)publicreturns(bool){uintcontractCodeLen=address(_signer).code.length;bytesmemorysigToValidate;// The order here is strictly defined in https://eips.ethereum.org/EIPS/eip-6492
// 这里顺序在 https://eips.ethereum.org/EIPS/eip-6492 中严格定义
// - ERC-6492 后缀检查和验证优先,同时允许合同已部署的情况;如果合约已部署,我们将根据已部署版本检查 sig,这允许 6492 签名仍然有效,同时考虑到潜在的密钥轮换
// - 如果存在合约代码,则进行 ERC-1271 验证
// - 最后,ecrecover
boolisCounterfactual=bytes32(_signature[_signature.length-32:_signature.length])==ERC6492_DETECTION_SUFFIX;if(isCounterfactual){addresscreate2Factory;bytesmemoryfactoryCalldata;(create2Factory,factoryCalldata,sigToValidate)=abi.decode(_signature[0:_signature.length-32],(address,bytes,bytes));if(contractCodeLen==0||tryPrepare){(boolsuccess,bytesmemoryerr)=create2Factory.call(factoryCalldata);if(!success)revertERC6492DeployFailed(err);}}else{sigToValidate=_signature;}// Try ERC-1271 verification
// 尝试 ERC-1271 验证
if(isCounterfactual||contractCodeLen>0){tryIERC1271Wallet(_signer).isValidSignature(_hash,sigToValidate)returns(bytes4magicValue){boolisValid=magicValue==ERC1271_SUCCESS;// retry, but this time assume the prefix is a prepare call
// 重试,但这次假设前缀是准备调用
if(!isValid&&!tryPrepare&&contractCodeLen>0){returnisValidSigImpl(_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)
// 使用 `revert` 的结果(撤消状态更改)
assembly{mstore(0,isValid)revert(31,1)}}returnisValid;}catch(bytesmemoryerr){// retry, but this time assume the prefix is a prepare call
// 重试,但这次假设前缀是准备调用
if(!tryPrepare&&contractCodeLen>0){returnisValidSigImpl(_signer,_hash,_signature,allowSideEffects,true);}revertERC1271Revert(err);}}// ecrecover verification
// ecrecover 验证
require(_signature.length==65,'SignatureValidator#recoverSigner: invalid signature length');bytes32r=bytes32(_signature[0:32]);bytes32s=bytes32(_signature[32:64]);uint8v=uint8(_signature[64]);if(v!=27&&v!=28){revert('SignatureValidator: invalid signature v value');}returnecrecover(_hash,v,r,s)==_signer;}functionisValidSigWithSideEffects(address_signer,bytes32_hash,bytescalldata_signature)externalreturns(bool){returnthis.isValidSigImpl(_signer,_hash,_signature,true,false);}functionisValidSig(address_signer,bytes32_hash,bytescalldata_signature)externalreturns(bool){trythis.isValidSigImpl(_signer,_hash,_signature,false,false)returns(boolisValid){returnisValid;}catch(bytesmemoryerror){// in order to avoid side effects from the contract getting deployed, the entire call will revert with a single byte result
// 为了避免合约部署的副作用,整个调用将恢复为单字节结果
uintlen=error.length;if(len==1)returnerror[0]==0x01;// all other errors are simply forwarded, but in custom formats so that nothing else can revert with a single byte in the call
// 所有其他错误都只是转发,但以自定义格式转发,以便其他任何东西都无法在调用中恢复为单字节
elseassembly{revert(error,len)}}}}// this is a helper so we can perform validation in a single eth_call without pre-deploying a singleton
// 这是一个助手,因此我们可以在单个 eth_call 中执行验证,而无需预先部署单例
contractValidateSigOffchain{constructor(address_signer,bytes32_hash,bytesmemory_signature){UniversalSigValidatorvalidator=newUniversalSigValidator();boolisValidSig=validator.isValidSigWithSideEffects(_signer,_hash,_signature);assembly{mstore(0,isValidSig)return(31,1)}}}