Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(issuer): Enable the batchIssue() method in ERC1888 #2514

Merged
merged 11 commits into from
Jun 18, 2021
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`
josipbagaric marked this conversation as resolved.
Show resolved Hide resolved

### `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