Skip to content

Commit

Permalink
Merge pull request #111 from ethereum-attestation-service/improve-del…
Browse files Browse the repository at this point in the history
…egated

Improve delegated attestations
  • Loading branch information
lbeder authored Nov 5, 2023
2 parents 8dd7b40 + 5b73368 commit 0c51c77
Show file tree
Hide file tree
Showing 22 changed files with 83 additions and 46 deletions.
2 changes: 1 addition & 1 deletion contracts/EAS.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ contract EAS is IEAS, Semver, EIP1271Verifier {

/// @dev Creates a new EAS instance.
/// @param registry The address of the global schema registry.
constructor(ISchemaRegistry registry) Semver(1, 2, 0) EIP1271Verifier("EAS", "1.2.0") {
constructor(ISchemaRegistry registry) Semver(1, 3, 0) EIP1271Verifier("EAS", "1.3.0") {
if (address(registry) == address(0)) {
revert InvalidRegistry();
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/Indexer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ contract Indexer is Semver {

/// @dev Creates a new Indexer instance.
/// @param eas The address of the global EAS contract.
constructor(IEAS eas) Semver(1, 2, 0) {
constructor(IEAS eas) Semver(1, 3, 0) {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/SchemaRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract SchemaRegistry is ISchemaRegistry, Semver {
mapping(bytes32 uid => SchemaRecord schemaRecord) private _registry;

/// @dev Creates a new SchemaRegistry instance.
constructor() Semver(1, 2, 0) {}
constructor() Semver(1, 3, 0) {}

/// @inheritdoc ISchemaRegistry
function register(string calldata schema, ISchemaResolver resolver, bool revocable) external returns (bytes32) {
Expand Down
10 changes: 6 additions & 4 deletions contracts/eip1271/EIP1271Verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ abstract contract EIP1271Verifier is EIP712 {
error InvalidNonce();

// 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 data,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant ATTEST_TYPEHASH = 0xf83bb2b0ede93a840239f7e701a54d9bc35f03701f51ae153d601c6947ff3d3f;
// keccak256("Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant ATTEST_TYPEHASH = 0xfeb2925a02bae3dae48d424a0437a2b6ac939aa9230ddc55a1a76f065d988076;

// The hash of the data type used to relay calls to the revoke function. It's the value of
// keccak256("Revoke(bytes32 schema,bytes32 uid,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant REVOKE_TYPEHASH = 0x2d4116d8c9824e4c316453e5c2843a1885580374159ce8768603c49085ef424c;
// keccak256("Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint256 nonce,uint64 deadline)").
bytes32 private constant REVOKE_TYPEHASH = 0xb5d556f07587ec0f08cf386545cc4362c702a001650c2058002615ee5c9d1e75;

// The user readable name of the signing domain.
string private _name;
Expand Down Expand Up @@ -106,6 +106,7 @@ abstract contract EIP1271Verifier is EIP712 {
keccak256(
abi.encode(
ATTEST_TYPEHASH,
request.attester,
request.schema,
data.recipient,
data.expirationTime,
Expand Down Expand Up @@ -143,6 +144,7 @@ abstract contract EIP1271Verifier is EIP712 {
keccak256(
abi.encode(
REVOKE_TYPEHASH,
request.revoker,
request.schema,
data.uid,
data.value,
Expand Down
22 changes: 16 additions & 6 deletions contracts/eip712/proxy/EIP712Proxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ contract EIP712Proxy is Semver, EIP712 {
error UsedSignature();

// 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 data,uint256 value,uint64 deadline)").
bytes32 private constant ATTEST_PROXY_TYPEHASH = 0x9d3e80e7032dc16815a5f67aa94e851240ae3b24eed13a7431bdac738f814567;
// keccak256("Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 value,uint64 deadline)").
bytes32 private constant ATTEST_PROXY_TYPEHASH = 0xea02ffba7dcb45f6fc649714d23f315eef12e3b27f9a7735d8d8bf41eb2b1af1;

// The hash of the data type used to relay calls to the revoke function. It's the value of
// keccak256("Revoke(bytes32 schema,bytes32 uid,uint256 value,uint64 deadline)").
bytes32 private constant REVOKE_PROXY_TYPEHASH = 0xd4e76f924411647a916bb4ae4631b3cf45c44e2da56ed1c63edb18ebc97ba5e4;
// keccak256("Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint64 deadline)").
bytes32 private constant REVOKE_PROXY_TYPEHASH = 0x78a69a78c1a55cdff5cbf949580b410778cd9e4d1ecbe6f06a7fa8dc2441b57d;

// The global EAS contract.
IEAS private immutable _eas;
Expand All @@ -102,7 +102,7 @@ contract EIP712Proxy is Semver, EIP712 {
/// @dev Creates a new EIP1271Verifier instance.
/// @param eas The address of the global EAS contract.
/// @param name The user readable name of the signing domain.
constructor(IEAS eas, string memory name) Semver(1, 2, 0) EIP712(name, "1.2.0") {
constructor(IEAS eas, string memory name) Semver(1, 3, 0) EIP712(name, "1.3.0") {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
Expand Down Expand Up @@ -377,6 +377,7 @@ contract EIP712Proxy is Semver, EIP712 {
keccak256(
abi.encode(
ATTEST_PROXY_TYPEHASH,
request.attester,
request.schema,
data.recipient,
data.expirationTime,
Expand Down Expand Up @@ -418,7 +419,16 @@ contract EIP712Proxy is Semver, EIP712 {
_verifyUnusedSignature(signature);

bytes32 digest = _hashTypedDataV4(
keccak256(abi.encode(REVOKE_PROXY_TYPEHASH, request.schema, data.uid, data.value, request.deadline))
keccak256(
abi.encode(
REVOKE_PROXY_TYPEHASH,
request.revoker,
request.schema,
data.uid,
data.value,
request.deadline
)
)
);

if (ECDSA.recover(digest, signature.v, signature.r, signature.s) != request.revoker) {
Expand Down
2 changes: 1 addition & 1 deletion contracts/resolver/SchemaResolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ abstract contract SchemaResolver is ISchemaResolver, Semver {

/// @dev Creates a new resolver.
/// @param eas The address of the global EAS contract.
constructor(IEAS eas) Semver(1, 2, 0) {
constructor(IEAS eas) Semver(1, 3, 0) {
if (address(eas) == address(0)) {
revert InvalidEAS();
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/tests/eip1271/TestEIP1271Verifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { DelegatedAttestationRequest, DelegatedRevocationRequest } from "../../I
import { Semver } from "../../Semver.sol";

contract TestEIP1271Verifier is Semver, EIP1271Verifier {
constructor(string memory name) Semver(1, 2, 0) EIP1271Verifier(name, "1.2.0") {}
constructor(string memory name) Semver(1, 3, 0) EIP1271Verifier(name, "1.3.0") {}

function verifyAttest(DelegatedAttestationRequest memory request) external {
_verifyAttest(request);
Expand Down
2 changes: 1 addition & 1 deletion deploy/tests/000001-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ describeDeployment(__filename, () => {
});

it('should deploy the schema registry', async () => {
expect(await registry.version()).to.equal('1.2.0');
expect(await registry.version()).to.equal('1.3.0');
});
});
2 changes: 1 addition & 1 deletion deploy/tests/000002-eas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describeDeployment(__filename, () => {
});

it('should deploy the EAS', async () => {
expect(await eas.version()).to.equal('1.2.0');
expect(await eas.version()).to.equal('1.3.0');

expect(await eas.getSchemaRegistry()).to.equal(await registry.getAddress());
});
Expand Down
2 changes: 1 addition & 1 deletion deploy/tests/000005-eip712-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describeDeployment(__filename, () => {
});

it('should deploy the EIP712 proxy', async () => {
expect(await proxy.version()).to.equal('1.2.0');
expect(await proxy.version()).to.equal('1.3.0');

expect(await proxy.getEAS()).to.equal(await eas.getAddress());
expect(await proxy.getDomainSeparator()).to.equal(eip712ProxyUtils.getDomainSeparator(EIP712_PROXY_NAME));
Expand Down
2 changes: 1 addition & 1 deletion deploy/tests/000006-indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describeDeployment(__filename, () => {
});

it('should deploy the indexer', async () => {
expect(await indexer.version()).to.equal('1.2.0');
expect(await indexer.version()).to.equal('1.3.0');

expect(await indexer.getEAS()).to.equal(await eas.getAddress());
});
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ethereum-attestation-service/eas-contracts",
"version": "1.2.3-beta.0",
"version": "1.3.0-beta.0",
"description": "Ethereum Attestation Service",
"repository": {
"type": "git",
Expand Down Expand Up @@ -115,7 +115,7 @@
"prettier": "^3.0.3",
"prettier-package-json": "^2.8.0",
"prettier-plugin-solidity": "^1.1.3",
"solc": "0.8.21",
"solc": "0.8.19",
"solhint": "^3.6.2",
"ts-node": "^10.9.1",
"typescript": "^5.2.2"
Expand Down
12 changes: 6 additions & 6 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion test/EAS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ describe('EAS', () => {
});

it('should be properly initialized', async () => {
expect(await eas.version()).to.equal('1.2.0');
expect(await eas.version()).to.equal('1.3.0');

expect(await eas.getSchemaRegistry()).to.equal(await registry.getAddress());
expect(await eas.getName()).to.equal(EIP712_NAME);
Expand Down
2 changes: 1 addition & 1 deletion test/Indexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe('Indexer', () => {
});

it('should be properly initialized', async () => {
expect(await indexer.version()).to.equal('1.2.0');
expect(await indexer.version()).to.equal('1.3.0');

expect(await indexer.getEAS()).to.equal(await eas.getAddress());
});
Expand Down
2 changes: 1 addition & 1 deletion test/SchemaRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('SchemaRegistry', () => {

describe('construction', () => {
it('should report a version', async () => {
expect(await registry.version()).to.equal('1.2.0');
expect(await registry.version()).to.equal('1.3.0');
});
});

Expand Down
2 changes: 2 additions & 0 deletions test/eip1271/EIP1271Verifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ describe('EIP1271Verifier', () => {

case SignerType.Contract: {
const hash = await eip712Utils.hashDelegatedAttestation(
await signer.getAddress(),
schema,
attestationRequest.recipient,
attestationRequest.expirationTime,
Expand Down Expand Up @@ -223,6 +224,7 @@ describe('EIP1271Verifier', () => {

case SignerType.Contract: {
const hash = await eip712Utils.hashDelegatedRevocation(
await signer.getAddress(),
schema,
revocationRequest.uid,
revocationRequest.value,
Expand Down
2 changes: 1 addition & 1 deletion test/eip712/proxy/EIP712Proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe('EIP712Proxy', () => {
});

it('should be properly initialized', async () => {
expect(await proxy.version()).to.equal('1.2.0');
expect(await proxy.version()).to.equal('1.3.0');

expect(await proxy.getEAS()).to.equal(await eas.getAddress());
expect(await proxy.getDomainSeparator()).to.equal(eip712ProxyUtils.getDomainSeparator(EIP712_PROXY_NAME));
Expand Down
2 changes: 1 addition & 1 deletion test/eip712/proxy/PermissionedEIP712Proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ describe('PermissionedEIP712Proxy', () => {

describe('construction', () => {
it('should be properly initialized', async () => {
expect(await proxy.version()).to.equal('1.2.0');
expect(await proxy.version()).to.equal('1.3.0');

expect(await proxy.getDomainSeparator()).to.equal(
eip712ProxyUtils.getDomainSeparator(PERMISSIONED_EIP712_PROXY_NAME)
Expand Down
16 changes: 11 additions & 5 deletions test/helpers/EIP712ProxyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import {
} from './EIP712Utils';

export const ATTEST_PROXY_TYPED_SIGNATURE =
'Attest(bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 value,uint64 deadline)';
export const REVOKE_PROXY_TYPED_SIGNATURE = 'Revoke(bytes32 schema,bytes32 uid,uint256 value,uint64 deadline)';
// eslint-disable-next-line max-len
'Attest(address attester,bytes32 schema,address recipient,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,uint256 value,uint64 deadline)';
export const REVOKE_PROXY_TYPED_SIGNATURE =
'Revoke(address revoker,bytes32 schema,bytes32 uid,uint256 value,uint64 deadline)';
export const ATTEST_PROXY_PRIMARY_TYPE = 'Attest';
export const REVOKE_PROXY_PRIMARY_TYPE = 'Revoke';
export const ATTEST_PROXY_TYPE: TypedData[] = [
{ name: 'attester', type: 'address' },
{ name: 'schema', type: 'bytes32' },
{ name: 'recipient', type: 'address' },
{ name: 'expirationTime', type: 'uint64' },
Expand All @@ -29,6 +32,7 @@ export const ATTEST_PROXY_TYPE: TypedData[] = [
{ name: 'deadline', type: 'uint64' }
];
export const REVOKE_PROXY_TYPE: TypedData[] = [
{ name: 'revoker', type: 'address' },
{ name: 'schema', type: 'bytes32' },
{ name: 'uid', type: 'bytes32' },
{ name: 'value', type: 'uint256' },
Expand Down Expand Up @@ -105,6 +109,7 @@ export class EIP712ProxyUtils {
deadline: bigint
): Promise<EIP712Request<EIP712MessageTypes, EIP712AttestationParams>> {
const params = {
attester: await attester.getAddress(),
schema,
recipient: typeof recipient === 'string' ? recipient : await recipient.getAddress(),
expirationTime,
Expand Down Expand Up @@ -139,14 +144,15 @@ export class EIP712ProxyUtils {
);
}

public signDelegatedProxyRevocation(
attester: Signer,
public async signDelegatedProxyRevocation(
revoker: Signer,
schema: string,
uid: string,
value: bigint,
deadline: bigint
): Promise<EIP712Request<EIP712MessageTypes, EIP712RevocationParams>> {
const params = {
revoker: await revoker.getAddress(),
schema,
uid,
value,
Expand All @@ -163,7 +169,7 @@ export class EIP712ProxyUtils {
Revoke: REVOKE_PROXY_TYPE
}
},
attester
revoker
);
}

Expand Down
Loading

0 comments on commit 0c51c77

Please sign in to comment.