Skip to content

Commit

Permalink
Merge pull request #3 from ethereum-attestation-service/updates
Browse files Browse the repository at this point in the history
Support offchain attestation version 2
  • Loading branch information
lbeder authored Aug 30, 2024
2 parents 29e1879 + 7a74e73 commit 0aa6baa
Show file tree
Hide file tree
Showing 8 changed files with 1,155 additions and 1,128 deletions.
43 changes: 0 additions & 43 deletions .eslintrc

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 16
node-version: 20
cache: 'pnpm'

- name: Install dependencies
Expand Down
13 changes: 7 additions & 6 deletions components/Contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import {

export * from '../typechain-types';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AsyncReturnType<T extends (...args: any) => any> = T extends (...args: any) => Promise<infer U>
? U
: T extends (...args: any) => infer U
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends (...args: any) => infer U
? U
: any;
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
any;

type Contract<F extends ContractFactory> = AsyncReturnType<F['deploy']>;

Expand All @@ -41,7 +44,7 @@ export const deployOrAttach = <F extends ContractFactory>(
bytecode: FactoryConstructor.bytecode
},
deploy: async (...args: Parameters<F['deploy']>): Promise<Contract<F>> => {
const defaultSigner = initialSigner ?? ((await ethers.getSigners())[0] as any as Signer);
const defaultSigner = initialSigner ?? ((await ethers.getSigners())[0] as Signer);

return new FactoryConstructor(defaultSigner).deploy(...(args || [])) as Promise<Contract<F>>;
},
Expand All @@ -55,13 +58,12 @@ export const attachOnly = <F extends ContractFactory>(
) => {
return {
attach: async (address: string, signer?: Signer): Promise<Contract<F>> => {
const defaultSigner = initialSigner ?? ((await ethers.getSigners())[0] as any as Signer);
const defaultSigner = initialSigner ?? ((await ethers.getSigners())[0] as Signer);
return new FactoryConstructor(signer ?? defaultSigner).attach(address) as Contract<F>;
}
};
};

/* eslint-disable camelcase */
const getContracts = (signer?: Signer) => ({
connect: (signer: Signer) => getContracts(signer),

Expand All @@ -71,6 +73,5 @@ const getContracts = (signer?: Signer) => ({
OffchainAttestationVerifier: deployOrAttach(OffchainAttestationVerifier__factory, signer),
SchemaRegistry: deployOrAttach(SchemaRegistry__factory, signer)
});
/* eslint-enable camelcase */

export default getContracts();
36 changes: 34 additions & 2 deletions contracts/OffchainAttestationVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ contract OffchainAttestationVerifier is EIP712Verifier {
bool revocable; // Whether the attestation is revocable.
bytes32 refUID; // The UID of the related attestation.
bytes data; // Custom attestation data.
bytes32 salt; // Custom salt.
Signature signature; // The ECDSA signature data.
}

// Offchain attestation versions.
uint16 private constant LEGACY = 0;
uint16 private constant VERSION1 = 1;
uint16 private constant VERSION2 = 2;

// The hash of the data type used to relay calls to the attest function. It's the value of
// keccak256("Attestation(bytes32 schema,address recipient,uint64 time,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data)").
Expand All @@ -41,6 +43,11 @@ contract OffchainAttestationVerifier is EIP712Verifier {
bytes32 private constant VERSION1_ATTEST_TYPEHASH =
0x9a1ef129b3715afc513574bddcf4404e21b0296e3ca20fec532fe1ec8d0932ec;

// The hash of the data type used to relay calls to the attest function. It's the value of
// keccak256("Attest(uint16 version,bytes32 schema,address recipient,uint64 time,uint64 expirationTime,bool revocable,bytes32 refUID,bytes data,bytes32 salt)").
bytes32 private constant VERSION2_ATTEST_TYPEHASH =
0x258b757fc37a6699a984f4be01258122f834200374b34b4457b6db0dd0f71132;

// The address of the global EAS contract.
IEAS private immutable _eas;

Expand All @@ -65,7 +72,7 @@ contract OffchainAttestationVerifier is EIP712Verifier {

// Verify that the version is known.
uint16 version = attestation.version;
if (version > VERSION1) {
if (version > VERSION2) {
return false;
}

Expand Down Expand Up @@ -94,6 +101,8 @@ contract OffchainAttestationVerifier is EIP712Verifier {
hash = _hashTypedDataLegacy(attestation);
} else if (version == VERSION1) {
hash = _hashTypedDataVersion1(attestation);
} else if (version == VERSION2) {
hash = _hashTypedDataVersion2(attestation);
}

Signature memory signature = attestation.signature;
Expand Down Expand Up @@ -131,7 +140,7 @@ contract OffchainAttestationVerifier is EIP712Verifier {
);
}

/// @dev Returns the legacy (version 0) attestation typed data hash
/// @dev Returns the version 1 attestation typed data hash
/// @param attestation The offchain attestation to verify.
/// @return The typed data hash.
function _hashTypedDataVersion1(OffchainAttestation calldata attestation) private view returns (bytes32) {
Expand All @@ -153,6 +162,29 @@ contract OffchainAttestationVerifier is EIP712Verifier {
);
}

/// @dev Returns the version 2 attestation typed data hash
/// @param attestation The offchain attestation to verify.
/// @return The typed data hash.
function _hashTypedDataVersion2(OffchainAttestation calldata attestation) private view returns (bytes32) {
return
_hashTypedDataV4(
keccak256(
abi.encode(
VERSION2_ATTEST_TYPEHASH,
VERSION2,
attestation.schema,
attestation.recipient,
attestation.time,
attestation.expirationTime,
attestation.revocable,
attestation.refUID,
keccak256(attestation.data),
attestation.salt
)
)
);
}

/// @dev Returns the current's block timestamp. This method is overridden during tests and used to simulate the
/// current block time.
function _time() internal view virtual returns (uint64) {
Expand Down
58 changes: 58 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import prettier from 'eslint-config-prettier';
import chaiFriendly from 'eslint-plugin-chai-friendly';
import tseslint from 'typescript-eslint';

export default [
...tseslint.configs.recommended,
prettier,
chaiFriendly.configs.recommendedFlat,
{
files: ['**/*.ts'],
rules: {
'max-len': ['error', 150, 2],
camelcase: [
'error',
{
ignoreImports: true
}
],
indent: [
'error',
2,
{
SwitchCase: 1
}
],
semi: ['error', 'always'],
quotes: ['error', 'single', { avoidEscape: true }],
'no-console': 'error',
'require-await': 'error',
'no-return-await': 'error',
'object-shorthand-properties-first': 'off',
'chai-friendly/no-unused-expressions': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unused-expressions': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true
}
]
},
languageOptions: {
globals: {
assert: true,
expect: true,
artifacts: true,
contract: true
}
}
}
];
57 changes: 24 additions & 33 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ethereum-attestation-service/eas-contracts-example",
"version": "1.7.1",
"version": "1.7.2",
"description": "Ethereum Attestation Service - Example",
"repository": {
"type": "git",
Expand All @@ -10,15 +10,6 @@
"license": "MIT",
"main": "dist/typechain-types/index.js",
"types": "dist/typechain-types/index.d.ts",
"files": [
"**/*.sol",
"!/contracts/tests/**/*",
"/artifacts/contracts",
"!/artifacts/contracts/tests/**/*",
"/dist/typechain-types",
"!/dist/typechain-types/contracts/tests/**/*",
"!/dist/typechain-types/factories/contracts/tests/**/*"
],
"scripts": {
"compile": "hardhat compile",
"recompile": "pnpm clean && pnpm compile",
Expand All @@ -33,42 +24,42 @@
"clean": "rm -rf artifacts cache dist coverage typechain-types out"
},
"dependencies": {
"@ethereum-attestation-service/eas-contracts": "1.7.1",
"hardhat": "2.22.4"
"@ethereum-attestation-service/eas-contracts": "^1.7.1",
"hardhat": "2.22.9"
},
"devDependencies": {
"@ethereum-attestation-service/eas-sdk": "2.1.4",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@nomicfoundation/hardhat-ethers": "^3.0.6",
"@ethereum-attestation-service/eas-sdk": "2.6.0",
"@ianvs/prettier-plugin-sort-imports": "^4.3.1",
"@nomicfoundation/hardhat-ethers": "^3.0.7",
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@nomiclabs/hardhat-solhint": "^3.1.0",
"@nomiclabs/hardhat-solhint": "^4.0.0",
"@openzeppelin/contracts": "5.0.2",
"@typechain/ethers-v6": "^0.5.1",
"@types/chai": "^4.3.16",
"@types/chai": "^4.3.19",
"@types/chance": "^1.1.6",
"@types/mocha": "^10.0.6",
"@types/node": "^20.12.12",
"@typescript-eslint/eslint-plugin": "^7.10.0",
"@typescript-eslint/parser": "^7.10.0",
"chai": "^4.4.1",
"@types/mocha": "^10.0.7",
"@types/node": "^22.5.1",
"@typescript-eslint/eslint-plugin": "^8.3.0",
"@typescript-eslint/parser": "^8.3.0",
"chai": "4.3.7",
"chai-bigint": "^0.2.0",
"decimal.js": "^10.4.3",
"eslint": "^8.57.0",
"eslint": "^9.9.1",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-chai-friendly": "^1.0.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-n": "^17.7.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"ethers": "^6.12.1",
"hardhat-dependency-compiler": "^1.1.4",
"mocha": "^10.4.0",
"prettier": "^3.2.5",
"eslint-plugin-promise": "^7.1.0",
"ethers": "^6.13.2",
"hardhat-dependency-compiler": "^1.2.1",
"mocha": "^10.7.3",
"prettier": "^3.3.3",
"prettier-package-json": "^2.8.0",
"prettier-plugin-solidity": "^1.3.1",
"prettier-plugin-solidity": "^1.4.1",
"solc": "0.8.26",
"solhint": "^5.0.1",
"solhint": "^5.0.3",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
"typescript": "^5.5.4",
"typescript-eslint": "^8.0.1"
}
}
Loading

0 comments on commit 0aa6baa

Please sign in to comment.