Skip to content

Commit

Permalink
Merge pull request #2514 from energywebfoundation/chore/batch-issuance
Browse files Browse the repository at this point in the history
chore(issuer): Enable the batchIssue() method in ERC1888
  • Loading branch information
josipbagaric authored Jun 18, 2021
2 parents 4f6c0db + eb89034 commit 75ec40b
Show file tree
Hide file tree
Showing 22 changed files with 2,608 additions and 1,576 deletions.
3,207 changes: 1,822 additions & 1,385 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

Binary file added docs/images/issuer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/traceability.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions docs/traceability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Traceability SDK

Traceability SDK is responsible for tracking (tracing) the exchange of Energy Attribute Certificates (EACs).

The main functions that the Traceability SDK deals with are:

1. Issuance
2. Transfer
3. Claiming / Redemption

## Components overview

### Layers

![Traceability](images/traceability.png)

### @energyweb/issuer

Package contains all the facades and entities that concern the on-chain presence of Certificates and Certification Requesting.

![@energyweb/issuer](images/issuer.png)

### Smart contracts

- [ERC-1888](traceability/contracts/ERC1888/ERC1888.md)
- [Registry](traceability/contracts/Registry.md)
- [Issuer](traceability/contracts/Issuer.md)
- [PrivateIssuer](traceability/contracts/PrivateIssuer.md)
23 changes: 23 additions & 0 deletions docs/traceability/contracts/ERC1888/ERC1888.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## `ERC1888`

### `issue(address _to, bytes _validityData, uint256 _topic, uint256 _value, bytes _issuanceData) → uint256` (external)

### `batchIssue(address _to, bytes _issuanceData, uint256 _topic, uint256[] _values, bytes[] _validityCalls) → uint256[]` (external)

### `safeTransferAndClaimFrom(address _from, address _to, uint256 _id, uint256 _value, bytes _data, bytes _claimData)` (external)

### `safeBatchTransferAndClaimFrom(address _from, address _to, uint256[] _ids, uint256[] _values, bytes _data, bytes[] _claimData)` (external)

### `getCertificate(uint256 _id) → address issuer, uint256 topic, bytes validityCall, bytes data` (external)

### `claimedBalanceOf(address _owner, uint256 _id) → uint256` (external)

### `claimedBalanceOfBatch(address[] _owners, uint256[] _ids) → uint256[]` (external)

### `IssuanceSingle(address _issuer, uint256 _topic, uint256 _id, uint256 _value)`

### `IssuanceBatch(address _issuer, uint256 _topic, uint256[] _ids, uint256[] _values)`

### `ClaimSingle(address _claimIssuer, address _claimSubject, uint256 _topic, uint256 _id, uint256 _value, bytes _claimData)`

### `ClaimBatch(address _claimIssuer, address _claimSubject, uint256[] _topics, uint256[] _ids, uint256[] _values, bytes[] _claimData)`
73 changes: 73 additions & 0 deletions docs/traceability/contracts/Issuer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
## `Issuer`

Used to manage the request/approve workflow for issuing ERC-1888 certificates.

### `initialize(uint256 _certificateTopic, address _registry)` (public)

Contructor.

Uses the OpenZeppelin `initializer` for upgradeability.
`_registry` cannot be the zero address.

### `setPrivateIssuer(address _privateIssuer)` (public)

Attaches a private issuance contract to this issuance contract.

`_privateIssuer` cannot be the zero address.

### `getCertificationRequest(uint256 _requestId) → struct Issuer.CertificationRequest` (public)

### `requestCertificationFor(bytes _data, address _owner) → uint256` (public)

### `requestCertificationForBatch(bytes[] _data, address[] _owners) → uint256[]` (public)

### `requestCertification(bytes _data) → uint256` (external)

### `revokeRequest(uint256 _requestId)` (external)

### `revokeCertificate(uint256 _certificateId)` (external)

### `approveCertificationRequest(uint256 _requestId, uint256 _value) → uint256` (public)

### `approveCertificationRequestBatch(uint256[] _requestIds, uint256[] _values) → uint256[]` (public)

### `issue(address _to, uint256 _value, bytes _data) → uint256` (public)

Directly issue a certificate without going through the request/approve procedure manually.

### `issueBatch(address[] _to, uint256[] _values, bytes[] _data) → uint256[]` (public)

Directly issue a batch of certificates without going through the request/approve procedure manually.

### `isRequestValid(uint256 _requestId) → bool` (external)

Validation for certification requests.

Used by other contracts to validate the token.
`_requestId` has to be an existing ID.

### `getRegistryAddress() → address` (external)

### `getPrivateIssuerAddress() → address` (external)

### `version() → string` (external)

### `_requestNotApprovedOrRevoked(uint256 _requestId) → bool` (internal)

### `_authorizeUpgrade(address)` (internal)

Needed for OpenZeppelin contract upgradeability.

Allow only to the owner of the contract.

### `CertificationRequested(address _owner, uint256 _id)`

### `CertificationRequestedBatch(address[] _owners, uint256[] _id)`

### `CertificationRequestApproved(address _owner, uint256 _id, uint256 _certificateId)`

### `CertificationRequestBatchApproved(address[] _owners, uint256[] _ids, uint256[] _certificateIds)`

### `CertificationRequestRevoked(address _owner, uint256 _id)`

### `CertificateRevoked(uint256 _certificateId)`
7 changes: 7 additions & 0 deletions docs/traceability/contracts/Migrations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## `Migrations`

### `restricted()`

### `setCompleted(uint256 completed)` (public)

### `upgrade(address new_address)` (public)
70 changes: 70 additions & 0 deletions docs/traceability/contracts/PrivateIssuer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
## `PrivateIssuer`

A privately issued certificate can later be migrated to be public.

Private certificate issuance differ from the public ones in a way that the fungible volumes that are being transferred/claimed are stored off-chain.

### `initialize(address _issuer)` (public)

Constructor.

Uses the OpenZeppelin `initializer` for upgradeability.
`_issuer` cannot be the zero address.

### `getCertificateCommitment(uint256 certificateId) → bytes32` (public)

Get the commitment (proof) for a specific certificate.

### `approveCertificationRequestPrivate(uint256 _requestId, bytes32 _commitment) → uint256` (public)

### `issuePrivate(address _to, bytes32 _commitment, bytes _data) → uint256` (public)

Directly issue a private certificate.

### `requestPrivateTransfer(uint256 _certificateId, bytes32 _ownerAddressLeafHash)` (external)

Request transferring a certain amount of tokens.

### `approvePrivateTransfer(uint256 _certificateId, struct PrivateIssuer.Proof[] _proof, bytes32 _previousCommitment, bytes32 _commitment) → bool` (external)

Approve a private transfer of certificates.

### `requestMigrateToPublic(uint256 _certificateId, bytes32 _ownerAddressLeafHash) → uint256 _migrationRequestId` (external)

Request the certificate volumes to be migrated from private to public.

### `requestMigrateToPublicFor(uint256 _certificateId, bytes32 _ownerAddressLeafHash, address _forAddress) → uint256 _migrationRequestId` (external)

Request the certificate volumes to be migrated from private to public for someone else.

### `getPrivateTransferRequest(uint256 _certificateId) → struct PrivateIssuer.PrivateTransferRequest` (external)

Get the private transfer request that is currently active for a specific certificate.

### `getMigrationRequest(uint256 _requestId) → struct PrivateIssuer.RequestStateChange` (external)

Get the migration request.

### `getMigrationRequestId(uint256 _certificateId) → uint256 _migrationRequestId` (external)

Get the migration request ID for a specific certificate.

### `migrateToPublic(uint256 _requestId, uint256 _volume, string _salt, struct PrivateIssuer.Proof[] _proof)` (external)

Migrate a private certificate to be public.

### `_authorizeUpgrade(address)` (internal)

### `getIssuerAddress() → address` (external)

### `version() → string` (external)

### `PrivateCertificationRequestApproved(address _owner, uint256 _id, uint256 _certificateId)`

### `CommitmentUpdated(address _owner, uint256 _id, bytes32 _commitment)`

### `MigrateToPublicRequested(address _owner, uint256 _id)`

### `PrivateTransferRequested(address _owner, uint256 _certificateId)`

### `CertificateMigratedToPublic(uint256 _certificateId, address _owner, uint256 _amount)`
67 changes: 67 additions & 0 deletions docs/traceability/contracts/Registry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
## `Registry`

Also complies to ERC-1155: https://eips.ethereum.org/EIPS/eip-1155.

### `constructor(string _uri)` (public)

### `issue(address _to, bytes _validityData, uint256 _topic, uint256 _value, bytes _issuanceData) → uint256` (external)

See {IERC1888-issue}.

`_to` cannot be the zero address.

### `batchIssue(address _to, bytes _issuanceData, uint256 _topic, uint256[] _values, bytes[] _validityCalls) → uint256[]` (external)

See {IERC1888-batchIssue}.

`_to` cannot be the zero address.
`_issuanceData`, `_values` and `_validityCalls` must have the same length.

### `batchIssueMultiple(address[] _to, bytes[] _issuanceData, uint256 _topic, uint256[] _values, bytes[] _validityCalls) → uint256[]` (external)

Similar to {IERC1888-batchIssue}, but not a part of the ERC-1888 standard.

Allows batch issuing to an array of \_to addresses.
`_to` cannot be the zero addresses.
`_to`, `_issuanceData`, `_values` and `_validityCalls` must have the same length.

### `mint(uint256 _id, address _to, uint256 _quantity)` (external)

Allows the issuer to mint more fungible tokens for existing ERC-188 certificates.

Allows batch issuing to an array of \_to addresses.
`_to` cannot be the zero address.

### `safeTransferAndClaimFrom(address _from, address _to, uint256 _id, uint256 _value, bytes _data, bytes _claimData)` (external)

See {IERC1888-safeTransferAndClaimFrom}.

`_to` cannot be the zero address.
`_from` has to have a balance above or equal `_value`.

### `safeBatchTransferAndClaimFrom(address _from, address _to, uint256[] _ids, uint256[] _values, bytes _data, bytes[] _claimData)` (external)

See {IERC1888-safeBatchTransferAndClaimFrom}.

`_to` and `_from` cannot be the zero addresses.
`_from` has to have a balance above 0.

### `getCertificate(uint256 _id) → address issuer, uint256 topic, bytes validityCall, bytes data` (public)

See {IERC1888-getCertificate}.

### `claimedBalanceOf(address _owner, uint256 _id) → uint256` (external)

See {IERC1888-claimedBalanceOf}.

### `claimedBalanceOfBatch(address[] _owners, uint256[] _ids) → uint256[]` (external)

See {IERC1888-claimedBalanceOfBatch}.

### `_burn(address _from, uint256 _id, uint256 _value)` (internal)

Burn certificates after they've been claimed, and increase the claimed balance.

### `_validate(address _verifier, bytes _validityData)` (internal)

Validate if the certificate is valid against an external `_verifier` contract.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CertificateUtils } from '@energyweb/issuer';
import { CertificateBatchOperations } from '@energyweb/issuer';
import { ISuccessResponse, ResponseFailure, ResponseSuccess } from '@energyweb/origin-backend-core';
import { BigNumber } from 'ethers';
import { HttpStatus } from '@nestjs/common';
Expand Down Expand Up @@ -38,7 +38,7 @@ export class BulkClaimCertificatesHandler implements ICommandHandler<BulkClaimCe
}

try {
const bulkClaimTx = await CertificateUtils.claimCertificates(
const bulkClaimTx = await CertificateBatchOperations.claimCertificates(
certificatesToClaim.map((cert) => cert.id),
claimData,
blockchainProperties.wrap(),
Expand Down
42 changes: 21 additions & 21 deletions packages/traceability/issuer/contracts/ERC1888/IERC1888.sol
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

interface ERC1888 is IERC1155 {
interface ERC1888 is IERC1155 {

struct Certificate {
int256 topic;
address issuer; // msg.sender
bytes validityData; // call data
uint256 topic;
address issuer;
bytes validityData;
bytes data;
}

event IssuanceSingle(address indexed _issuer, int256 indexed _topic, uint256 _id);
event IssuanceBatch(address indexed _issuer, int256[] indexed _topics, uint256[] _ids);

event ClaimSingle(address indexed _claimIssuer, address indexed _claimSubject, int256 indexed _topic, uint256 _id, uint256 _value, bytes _claimData);
event ClaimBatch(address indexed _claimIssuer, address indexed _claimSubject, int256[] indexed _topics, uint256[] _ids, uint256[] _values, bytes[] _claimData);

function issue(address _to, bytes calldata _validityData, int256 _topic, uint256 _value, bytes calldata _data) external returns (uint256);
// function batchIssue(bytes[] _data, uint256[] _topics, uint256[] _value, bytes32[] _signatures) external returns(uint256[]);

function safeTransferAndClaimFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data, bytes calldata _claimData) external;
function safeBatchTransferAndClaimFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data, bytes[] calldata _claimData) external;

function getCertificate(uint256 _id) external view returns (address issuer, int256 topic, bytes calldata validityCall, bytes calldata data);
function claimedBalanceOf(address _owner, uint256 _id) external view returns (uint256);
function claimedBalanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
event IssuanceSingle(address indexed _issuer, uint256 indexed _topic, uint256 _id, uint256 _value);
event IssuanceBatch(address indexed _issuer, uint256 indexed _topic, uint256[] _ids, uint256[] _values);
event ClaimSingle(address indexed _claimIssuer, address indexed _claimSubject, uint256 indexed _topic, uint256 _id, uint256 _value, bytes _claimData);
event ClaimBatch(address indexed _claimIssuer, address indexed _claimSubject, uint256[] indexed _topics, uint256[] _ids, uint256[] _values, bytes[] _claimData);
function issue(address _to, bytes calldata _validityData, uint256 _topic, uint256 _value, bytes calldata _issuanceData) external returns (uint256);
function batchIssue(address _to, bytes memory _issuanceData, uint256 _topic, uint256[] memory _values, bytes[] memory _validityCalls) external returns(uint256[] memory);
function safeTransferAndClaimFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data, bytes calldata _claimData) external;
function safeBatchTransferAndClaimFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data, bytes[] calldata _claimData) external;

function getCertificate(uint256 _id) external view returns (address issuer, uint256 topic, bytes memory validityCall, bytes memory data);
function claimedBalanceOf(address _owner, uint256 _id) external view returns (uint256);
function claimedBalanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);
}
Loading

0 comments on commit 75ec40b

Please sign in to comment.