Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
ee284df3
Commit
ee284df3
authored
Aug 10, 2023
by
lbeder
Committed by
Mark Tyneway
Aug 11, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: Add EIP1271 support to EAS
parent
2261ab3b
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
48 additions
and
33 deletions
+48
-33
Common.sol
packages/contracts-bedrock/src/EAS/Common.sol
+2
-2
EAS.sol
packages/contracts-bedrock/src/EAS/EAS.sol
+6
-8
IEAS.sol
packages/contracts-bedrock/src/EAS/IEAS.sol
+5
-7
EIP1271Verifier.sol
...ges/contracts-bedrock/src/EAS/eip1271/EIP1271Verifier.sol
+35
-16
No files found.
packages/contracts-bedrock/src/EAS/Common.sol
View file @
ee284df3
...
@@ -13,8 +13,8 @@ error InvalidLength();
...
@@ -13,8 +13,8 @@ error InvalidLength();
error InvalidSignature();
error InvalidSignature();
error NotFound();
error NotFound();
/// @dev A struct representing E
IP712
signature data.
/// @dev A struct representing E
CDSA
signature data.
struct
EIP712
Signature {
struct Signature {
uint8 v; // The recovery ID.
uint8 v; // The recovery ID.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 r; // The x-coordinate of the nonce R.
bytes32 s; // The signature data.
bytes32 s; // The signature data.
...
...
packages/contracts-bedrock/src/EAS/EAS.sol
View file @
ee284df3
...
@@ -4,13 +4,13 @@ pragma solidity 0.8.19;
...
@@ -4,13 +4,13 @@ pragma solidity 0.8.19;
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Semver } from "../universal/Semver.sol";
import { Semver } from "../universal/Semver.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { Predeploys } from "../libraries/Predeploys.sol";
import { EIP
712Verifier } from "./eip712/EIP712
Verifier.sol";
import { EIP
1271Verifier } from "./eip1271/EIP1271
Verifier.sol";
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
import { ISchemaResolver } from "./resolver/ISchemaResolver.sol";
import {
import {
AccessDenied,
AccessDenied,
EMPTY_UID,
EMPTY_UID,
EIP712
Signature,
Signature,
InvalidLength,
InvalidLength,
MAX_GAP,
MAX_GAP,
NotFound,
NotFound,
...
@@ -44,7 +44,7 @@ struct AttestationsResult {
...
@@ -44,7 +44,7 @@ struct AttestationsResult {
/// @custom:predeploy 0x4200000000000000000000000000000000000021
/// @custom:predeploy 0x4200000000000000000000000000000000000021
/// @title EAS
/// @title EAS
/// @notice The Ethereum Attestation Service protocol.
/// @notice The Ethereum Attestation Service protocol.
contract EAS is IEAS, Semver, EIP
712
Verifier {
contract EAS is IEAS, Semver, EIP
1271
Verifier {
using Address for address payable;
using Address for address payable;
error AlreadyRevoked();
error AlreadyRevoked();
...
@@ -80,7 +80,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
...
@@ -80,7 +80,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
uint256[MAX_GAP - 3] private __gap;
uint256[MAX_GAP - 3] private __gap;
/// @dev Creates a new EAS instance.
/// @dev Creates a new EAS instance.
constructor() Semver(1, 0, 2) EIP
712
Verifier("EAS", "1.0.1") { }
constructor() Semver(1, 0, 2) EIP
1271
Verifier("EAS", "1.0.1") { }
/// @inheritdoc IEAS
/// @inheritdoc IEAS
function getSchemaRegistry() external pure returns (ISchemaRegistry) {
function getSchemaRegistry() external pure returns (ISchemaRegistry) {
...
@@ -186,8 +186,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
...
@@ -186,8 +186,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
revert InvalidLength();
revert InvalidLength();
}
}
// Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing
// Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces.
// nonces.
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
_verifyAttest(
_verifyAttest(
DelegatedAttestationRequest({
DelegatedAttestationRequest({
...
@@ -287,8 +286,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
...
@@ -287,8 +286,7 @@ contract EAS is IEAS, Semver, EIP712Verifier {
revert InvalidLength();
revert InvalidLength();
}
}
// Verify EIP712 signatures. Please note that the signatures are assumed to be signed with increasing
// Verify signatures. Please note that the signatures are assumed to be signed with increasing nonces.
// nonces.
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
for (uint256 j = 0; j < data.length; j = uncheckedInc(j)) {
_verifyRevoke(
_verifyRevoke(
DelegatedRevocationRequest({
DelegatedRevocationRequest({
...
...
packages/contracts-bedrock/src/EAS/IEAS.sol
View file @
ee284df3
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
pragma solidity ^0.8.0;
pragma solidity ^0.8.0;
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { ISchemaRegistry } from "./ISchemaRegistry.sol";
import { Attestation,
EIP712
Signature } from "./Common.sol";
import { Attestation, Signature } from "./Common.sol";
/// @dev A struct representing the arguments of the attestation request.
/// @dev A struct representing the arguments of the attestation request.
struct AttestationRequestData {
struct AttestationRequestData {
...
@@ -25,7 +25,7 @@ struct AttestationRequest {
...
@@ -25,7 +25,7 @@ struct AttestationRequest {
struct DelegatedAttestationRequest {
struct DelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData data; // The arguments of the attestation request.
AttestationRequestData data; // The arguments of the attestation request.
EIP712Signature signature; // The EIP712
signature data.
Signature signature; // The ECDSA
signature data.
address attester; // The attesting account.
address attester; // The attesting account.
}
}
...
@@ -39,8 +39,7 @@ struct MultiAttestationRequest {
...
@@ -39,8 +39,7 @@ struct MultiAttestationRequest {
struct MultiDelegatedAttestationRequest {
struct MultiDelegatedAttestationRequest {
bytes32 schema; // The unique identifier of the schema.
bytes32 schema; // The unique identifier of the schema.
AttestationRequestData[] data; // The arguments of the attestation requests.
AttestationRequestData[] data; // The arguments of the attestation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
// signed with increasing nonces.
address attester; // The attesting account.
address attester; // The attesting account.
}
}
...
@@ -61,7 +60,7 @@ struct RevocationRequest {
...
@@ -61,7 +60,7 @@ struct RevocationRequest {
struct DelegatedRevocationRequest {
struct DelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData data; // The arguments of the revocation request.
RevocationRequestData data; // The arguments of the revocation request.
EIP712Signature signature; // The EIP712
signature data.
Signature signature; // The ECDSA
signature data.
address revoker; // The revoking account.
address revoker; // The revoking account.
}
}
...
@@ -75,8 +74,7 @@ struct MultiRevocationRequest {
...
@@ -75,8 +74,7 @@ struct MultiRevocationRequest {
struct MultiDelegatedRevocationRequest {
struct MultiDelegatedRevocationRequest {
bytes32 schema; // The unique identifier of the schema.
bytes32 schema; // The unique identifier of the schema.
RevocationRequestData[] data; // The arguments of the revocation requests.
RevocationRequestData[] data; // The arguments of the revocation requests.
EIP712Signature[] signatures; // The EIP712 signatures data. Please note that the signatures are assumed to be
Signature[] signatures; // The ECDSA signatures data. Please note that the signatures are assumed to be signed with increasing nonces.
// signed with increasing nonces.
address revoker; // The revoking account.
address revoker; // The revoking account.
}
}
...
...
packages/contracts-bedrock/src/EAS/eip
712/EIP712
Verifier.sol
→
packages/contracts-bedrock/src/EAS/eip
1271/EIP1271
Verifier.sol
View file @
ee284df3
...
@@ -3,21 +3,23 @@ pragma solidity 0.8.19;
...
@@ -3,21 +3,23 @@ pragma solidity 0.8.19;
import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import { EIP712 } from "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import {
import {
AttestationRequest,
AttestationRequestData,
AttestationRequestData,
DelegatedAttestationRequest,
DelegatedAttestationRequest,
DelegatedRevocationRequest,
DelegatedRevocationRequest,
RevocationRequest,
RevocationRequestData
RevocationRequestData
} from "../IEAS.sol";
} from "../IEAS.sol";
import { EIP712Signature, InvalidSignature, MAX_GAP, stringToBytes32, bytes32ToString } from "../Common.sol";
import { Signature, InvalidSignature, MAX_GAP, stringToBytes32, bytes32ToString } from "../Common.sol";
/// @title EIP1271Verifier
/// @notice EIP1271Verifier typed signatures verifier for EAS delegated attestations.
abstract contract EIP1271Verifier is EIP712 {
using Address for address;
/// @title EIP712
/// @notice The EIP712 typed signatures verifier for EAS delegated attestations.
abstract contract EIP712Verifier is EIP712 {
// The hash of the data type used to relay calls to the attest function. It's the value of
// The hash of the data type used to relay calls to the attest function. It's the value of
// keccak256("Attest(bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes
// keccak256("Attest(bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes
// data,uint256 nonce)").
// data,uint256 nonce)").
...
@@ -36,13 +38,14 @@ abstract contract EIP712Verifier is EIP712 {
...
@@ -36,13 +38,14 @@ abstract contract EIP712Verifier is EIP712 {
// Upgrade forward-compatibility storage gap
// Upgrade forward-compatibility storage gap
uint256[MAX_GAP - 1] private __gap;
uint256[MAX_GAP - 1] private __gap;
/// @dev Creates a new EIP
712
Verifier instance.
/// @dev Creates a new EIP
1271
Verifier instance.
/// @param version The current major version of the signing domain
/// @param version The current major version of the signing domain
constructor(string memory name, string memory version) EIP712(name, version) {
constructor(string memory name, string memory version) EIP712(name, version) {
_name = stringToBytes32(name);
_name = stringToBytes32(name);
}
}
/// @notice Returns the domain separator used in the encoding of the signatures for attest, and revoke.
/// @notice Returns the domain separator used in the encoding of the signatures for attest, and revoke.
/// @return The domain separator used in the encoding of the signatures for attest, and revoke.
function getDomainSeparator() external view returns (bytes32) {
function getDomainSeparator() external view returns (bytes32) {
return _domainSeparatorV4();
return _domainSeparatorV4();
}
}
...
@@ -55,13 +58,13 @@ abstract contract EIP712Verifier is EIP712 {
...
@@ -55,13 +58,13 @@ abstract contract EIP712Verifier is EIP712 {
}
}
/// @notice Returns the EIP712 type hash for the attest function.
/// @notice Returns the EIP712 type hash for the attest function.
/// @return The EIP712
attest function type hash
.
/// @return The EIP712
type hash for the attest function
.
function getAttestTypeHash() external pure returns (bytes32) {
function getAttestTypeHash() external pure returns (bytes32) {
return ATTEST_TYPEHASH;
return ATTEST_TYPEHASH;
}
}
/// @notice Returns the EIP712 type hash for the revoke function.
/// @notice Returns the EIP712 type hash for the revoke function.
/// @return
hash_ The EIP712 revoke function type hash
.
/// @return
The EIP712 type hash for the revoke function
.
function getRevokeTypeHash() external pure returns (bytes32) {
function getRevokeTypeHash() external pure returns (bytes32) {
return REVOKE_TYPEHASH;
return REVOKE_TYPEHASH;
}
}
...
@@ -76,7 +79,7 @@ abstract contract EIP712Verifier is EIP712 {
...
@@ -76,7 +79,7 @@ abstract contract EIP712Verifier is EIP712 {
/// @param request The arguments of the delegated attestation request.
/// @param request The arguments of the delegated attestation request.
function _verifyAttest(DelegatedAttestationRequest memory request) internal {
function _verifyAttest(DelegatedAttestationRequest memory request) internal {
AttestationRequestData memory data = request.data;
AttestationRequestData memory data = request.data;
EIP712
Signature memory signature = request.signature;
Signature memory signature = request.signature;
uint256 nonce;
uint256 nonce;
unchecked {
unchecked {
...
@@ -97,17 +100,14 @@ abstract contract EIP712Verifier is EIP712 {
...
@@ -97,17 +100,14 @@ abstract contract EIP712Verifier is EIP712 {
)
)
)
)
);
);
_verifySignature(digest, signature, request.attester);
if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.attester) {
revert InvalidSignature();
}
}
}
/// @notice Verifies delegated revocation request.
/// @notice Verifies delegated revocation request.
/// @param request The arguments of the delegated revocation request.
/// @param request The arguments of the delegated revocation request.
function _verifyRevoke(DelegatedRevocationRequest memory request) internal {
function _verifyRevoke(DelegatedRevocationRequest memory request) internal {
RevocationRequestData memory data = request.data;
RevocationRequestData memory data = request.data;
EIP712
Signature memory signature = request.signature;
Signature memory signature = request.signature;
uint256 nonce;
uint256 nonce;
unchecked {
unchecked {
...
@@ -115,8 +115,27 @@ abstract contract EIP712Verifier is EIP712 {
...
@@ -115,8 +115,27 @@ abstract contract EIP712Verifier is EIP712 {
}
}
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(REVOKE_TYPEHASH, request.schema, data.uid, nonce)));
bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(REVOKE_TYPEHASH, request.schema, data.uid, nonce)));
_verifySignature(digest, signature, request.revoker);
}
/// @notice Verifies EIP712 signatures (with EIP1271 support).
/// @param digest The typed-data digest to verify.
/// @param signature The signature to verify (either a "real" ECDSA signature or an EIP1271-aware signature).
/// @param signer The signer to verify the signature against.
function _verifySignature(bytes32 digest, Signature memory signature, address signer) private view {
// If the signer is a contract, check if it's EIP1271 compliant.
if (signer.isContract()) {
bytes4 magicValue = IERC1271(signer).isValidSignature(digest, abi.encode(signature));
if (magicValue != IERC1271.isValidSignature.selector) {
revert InvalidSignature();
}
return;
}
if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.revoker) {
// If the signer is an EOA, verify the signature using the standard (non-malleable) ECDSA signature
// verification.
if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != signer) {
revert InvalidSignature();
revert InvalidSignature();
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment