Skip to content

Commit

Permalink
feat: As a user, I want to differentiate the Attestations from each n…
Browse files Browse the repository at this point in the history
…etwork
  • Loading branch information
alainncls committed Nov 24, 2023
1 parent 725e022 commit adbb81d
Show file tree
Hide file tree
Showing 8 changed files with 206 additions and 37 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/website-build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Deploy website
name: Build website

on:
pull_request:
Expand All @@ -13,7 +13,7 @@ on:
- release/*

jobs:
website-deploy:
website-build:
runs-on: ubuntu-latest

defaults:
Expand Down
8 changes: 8 additions & 0 deletions contracts/script/deploy/deployEverything.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ethers, run, upgrades } from "hardhat";
import dotenv from "dotenv";
import { getChainPrefix } from "../utils";

dotenv.config({ path: "../.env" });

Expand Down Expand Up @@ -135,6 +136,13 @@ async function main() {
await attestationRegistry.updateRouter(routerProxyAddress);
console.log("AttestationRegistry updated!");

console.log("Updating AttestationRegistry with the chain prefix...");
const network = await ethers.provider.getNetwork();
const chainPrefix = getChainPrefix(network.chainId);
console.log(`Chain prefix for chain ID ${network.chainId} is ${chainPrefix}`);
await attestationRegistry.updateChainPrefix(chainPrefix);
console.log("AttestationRegistry updated!");

console.log("Updating ModuleRegistry with the Router address...");
await moduleRegistry.updateRouter(routerProxyAddress);
console.log("ModuleRegistry updated!");
Expand Down
31 changes: 31 additions & 0 deletions contracts/script/updateChainPrefix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { ethers } from "hardhat";
import dotenv from "dotenv";
import { getChainPrefix } from "./utils";

dotenv.config({ path: "../.env" });

async function main() {
console.log("Updating AttestationRegistry with the chain prefix...");

const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS;
if (!attestationProxyAddress) {
throw new Error("Attestation proxy address not found");
}

const attestationRegistry = await ethers.getContractAt("AttestationRegistry", attestationProxyAddress);

const network = await ethers.provider.getNetwork();
const chainPrefix = getChainPrefix(network.chainId);
console.log(`Chain prefix for chain ID ${network.chainId} is ${chainPrefix}`);

await attestationRegistry.updateChainPrefix(chainPrefix);

console.log("AttestationRegistry updated!");
}

// We recommend this pattern to be able to use async/await everywhere
// and properly handle errors.
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
10 changes: 5 additions & 5 deletions contracts/script/upgrade/forceUpgradeEverything.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ async function main() {
throw new Error("Router proxy address not found");
}

const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? "";
const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS;
if (!attestationProxyAddress) {
throw new Error("Attestation proxy address not found");
}

const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? "";
const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS;
if (!moduleProxyAddress) {
throw new Error("Module proxy address not found");
}

const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? "";
const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS;
if (!portalProxyAddress) {
throw new Error("Portal proxy address not found");
}

const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? "";
const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS;
if (!schemaProxyAddress) {
throw new Error("Schema proxy address not found");
}

const attestationReaderProxyAddress = process.env.ATTESTATION_READER_ADDRESS ?? "";
const attestationReaderProxyAddress = process.env.ATTESTATION_READER_ADDRESS;
if (!attestationReaderProxyAddress) {
throw new Error("Attestation reader proxy address not found");
}
Expand Down
10 changes: 5 additions & 5 deletions contracts/script/upgrade/upgradeEverything.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,27 @@ async function main() {
throw new Error("Router proxy address not found");
}

const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS ?? "";
const attestationProxyAddress = process.env.ATTESTATION_REGISTRY_ADDRESS;
if (!attestationProxyAddress) {
throw new Error("Attestation proxy address not found");
}

const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS ?? "";
const moduleProxyAddress = process.env.MODULE_REGISTRY_ADDRESS;
if (!moduleProxyAddress) {
throw new Error("Module proxy address not found");
}

const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS ?? "";
const portalProxyAddress = process.env.PORTAL_REGISTRY_ADDRESS;
if (!portalProxyAddress) {
throw new Error("Portal proxy address not found");
}

const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS ?? "";
const schemaProxyAddress = process.env.SCHEMA_REGISTRY_ADDRESS;
if (!schemaProxyAddress) {
throw new Error("Schema proxy address not found");
}

const attestationReaderProxyAddress = process.env.ATTESTATION_READER_ADDRESS ?? "";
const attestationReaderProxyAddress = process.env.ATTESTATION_READER_ADDRESS;
if (!attestationReaderProxyAddress) {
throw new Error("Attestation reader proxy address not found");
}
Expand Down
14 changes: 14 additions & 0 deletions contracts/script/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export const getChainPrefix = (chainId: bigint): bigint => {
switch (chainId) {
case 59140n: // Linea testnet
return 0n;
case 59144n: // Linea mainnet
return 0n;
case 421613n: // Arbitrum testnet
return 1000000000000000000000000000000000000000000000000000000000000n;
case 42161n: // Arbitrum mainnet
return 1000000000000000000000000000000000000000000000000000000000000n;
default:
throw new Error("Unknown network");
}
};
51 changes: 45 additions & 6 deletions contracts/src/AttestationRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ contract AttestationRegistry is OwnableUpgradeable {

mapping(bytes32 attestationId => Attestation attestation) private attestations;

uint256 private chainPrefix;

/// @notice Error thrown when a non-portal tries to call a method that can only be called by a portal
error OnlyPortal();
/// @notice Error thrown when an invalid Router address is given
Expand Down Expand Up @@ -82,6 +84,14 @@ contract AttestationRegistry is OwnableUpgradeable {
router = IRouter(_router);
}

/**
* @notice Changes the chain prefix for the attestation IDs
* @dev Only the registry owner can call this method
*/
function updateChainPrefix(uint256 _chainPrefix) public onlyOwner {
chainPrefix = _chainPrefix;
}

/**
* @notice Registers an attestation to the AttestationRegistry
* @param attestationPayload the attestation payload to create attestation and register it
Expand All @@ -98,7 +108,8 @@ contract AttestationRegistry is OwnableUpgradeable {
if (attestationPayload.attestationData.length == 0) revert AttestationDataFieldEmpty();
// Auto increment attestation counter
attestationIdCounter++;
bytes32 id = bytes32(abi.encode(attestationIdCounter));
// Generate the full attestation ID, padded with the chain prefix
bytes32 id = generateAttestationId(attestationIdCounter);
// Create attestation
attestations[id] = Attestation(
id,
Expand Down Expand Up @@ -131,7 +142,8 @@ contract AttestationRegistry is OwnableUpgradeable {
for (uint256 i = 0; i < attestationsPayloads.length; i = uncheckedInc256(i)) {
// Auto increment attestation counter
attestationIdCounter++;
bytes32 id = bytes32(abi.encode(attestationIdCounter));
// Generate the full attestation ID, padded with the chain prefix
bytes32 id = generateAttestationId(attestationIdCounter);
// Create attestation
attestations[id] = Attestation(
id,
Expand Down Expand Up @@ -160,7 +172,7 @@ contract AttestationRegistry is OwnableUpgradeable {
function replace(bytes32 attestationId, AttestationPayload calldata attestationPayload, address attester) public {
attest(attestationPayload, attester);
revoke(attestationId);
bytes32 replacedBy = bytes32(abi.encode(attestationIdCounter));
bytes32 replacedBy = generateAttestationId(attestationIdCounter);
attestations[attestationId].replacedBy = replacedBy;

emit AttestationReplaced(attestationId, replacedBy);
Expand Down Expand Up @@ -257,21 +269,29 @@ contract AttestationRegistry is OwnableUpgradeable {
}

/**
* @notice Gets the attestation id counter
* @return The attestationIdCounter
* @notice Gets the attestation counter
* @return The attestation counter
*/
function getAttestationIdCounter() public view returns (uint32) {
return attestationIdCounter;
}

/**
* @notice Gets the chain prefix used to generate the attestation IDs
* @return The chain prefix
*/
function getChainPrefix() public view returns (uint256) {
return chainPrefix;
}

/**
* @notice Checks if an address owns a given attestation following ERC-1155
* @param account The address of the token holder
* @param id ID of the attestation
* @return The _owner's balance of the attestations on a given attestation ID
*/
function balanceOf(address account, uint256 id) public view returns (uint256) {
bytes32 attestationId = bytes32(abi.encode(id));
bytes32 attestationId = generateAttestationId(id);
Attestation memory attestation = attestations[attestationId];
if (attestation.subject.length > 20 && keccak256(attestation.subject) == keccak256(abi.encode(account))) {
return 1;
Expand All @@ -296,4 +316,23 @@ contract AttestationRegistry is OwnableUpgradeable {
}
return result;
}

/**
* @notice Generate an attestation ID, prefixed by the Verax chain identifier
* @param id The attestation ID (coming after the chain prefix)
* @return The attestation ID
*/
function generateAttestationId(uint256 id) public view returns (bytes32) {
// Convert the basic attestation ID to a bytes32 value
bytes32 originalCounterValue = bytes32(abi.encode(id));

// Clear the first byte of the original bytes32 to make room for the chain ID
bytes32 clearedCounterValue = (originalCounterValue << 8) >> 8;

// Shift the chain ID to the left by 240 bits to position it as the first byte
bytes32 shiftedChainPrefix = bytes32(chainPrefix) << 240;

// Combine the shifted chain ID and the cleared counter value to form the attestation ID
return shiftedChainPrefix | clearedCounterValue;
}
}
Loading

0 comments on commit adbb81d

Please sign in to comment.