hashgraph / hashgraph/asset-tokenization-studio

docs: mint() needs a KYC-granted recipient — the issuer minting to itself included — but only the web-app guide says so; the SDK README, the bond guide and the programmatic KYC order do not

Open
#1,403 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
33
Forks
28
Avg merge
15h 36m
Merged PRs (30d)
8

Description

## Summary

With `internalKycActivated: true`, the first `mint` on a fresh bond usually goes to the issuer's own address, and it reverts with `InvalidKycStatus()` until the issuer has granted KYC to itself. The rule is stated once, in the web-app user guide; every place a contract or SDK integrator reads instead is silent or says "transfers".

## Versions

- Contracts at tag `v.8.0.0-ats` (commit be4f860e408ec5b1a24d12feb6f872aabff69319), testnet factory `0.0.9213391`, bond config `0x…02` v1, `internalKycActivated: true`, `isWhiteList: false`.
- Docs on `main`, checked 2026-09-11.

## Where the check is

`packages/ats/contracts/contracts/facets/mint/Mint.sol`: both `issue(_tokenHolder, …)` and `mint(_to, …)` carry `onlyIdentifiedAddresses(address(0), _to)` and `onlyCompliant(address(0), _to, false)`. `onlyIdentifiedAddresses` goes through `ERC1594StorageWrapper.checkIdentity` → `_isIdentified(from, to)` → `_validateIdentifiedAccount(to)`, which requires KYC status `GRANTED` and reverts with `IKyc.InvalidKycStatus()` otherwise (`domain/core/KycStorageWrapper.sol`, `requireValidKycStatus`).

## Reproduce

1. `deployBond` with `internalKycActivated: true` and `rbacs` giving the deployer `DEFAULT_ADMIN_ROLE`, `ROLE_SSI_MANAGER`, `ROLE_KYC`, `ROLE_ISSUER`.
2. `mint(deployer, 100)` → reverts `InvalidKycStatus()`. Nothing about the role set-up is wrong; the issuer is simply not a KYC'd holder yet.
3. `addIssuer(deployer)`, then `grantKyc(deployer, "vc:issuer", validFrom, validTo, deployer)`, then `mint(deployer, 100)` → succeeds.

The order that works end to end, run against the factory above: `addIssuer(issuer)` → `grantKyc(issuer)` → `grantKyc(each investor)` → `mint(issuer, supply)` — https://github.com/AbhimanyuAjudiya/bond-desk/blob/main/ats/script/CreateBond.s.sol (`_issue()`), transactions linked from that repo's README.

## Expected vs actual (docs)

- `docs/ats/user-guides/token-operations.md`, "Mint (Issue) Tokens", line 33: "Recipient must have valid KYC". Correct, but it is the web-app guide, and the troubleshooting entry at lines 282–291 is keyed on the web app's error string, which a contract caller never sees (they get the `InvalidKycStatus()` selector, which appears nowhere in the docs).
- `packages/ats/sdk/README.md`: the `issue` entry (line ~280) says "Mints new assets to a given account", `mint` (line ~294) "Requires the Agent role", and the "Minting" how-to (line ~1413) lists only the Minter Role. No KYC prerequisite on the recipient.
- `docs/ats/user-guides/creating-bond.md`, "Internal KYC Activated" (lines 123–133): "When enabled: Token checks internal KYC registry before allowing **transfers**". Minting is not a transfer in the reader's head, and this is the page an integrator reads while choosing the flag.
- #1391's programmatic quick reference (context #1390) ends at `grantKyc`; the very next call is `mint`, and it fails unless step 3 was run for the recipient — including the issuer.
- #1399 is the whitelist-mode twin of this (`AccountIsBlocked` from the control list); the internal-KYC path has the same shape and the same surprise: the issuer feels exempt from its own compliance rules and is not.

## Suggested fix

1. `creating-bond.md`, "Internal KYC Activated": "before allowing transfers **and mints**: the recipient, including the issuer minting the initial supply to itself, must hold GRANTED KYC".
2. SDK README `issue` / `mint` entries and the "Minting" how-to: one line, "the target account must already hold KYC (internal or external) when KYC is active".
3. #1391's quick reference: add step 4, `grantKyc(recipient)` → `mint(recipient, amount)`, with `InvalidKycStatus` as the revert name so it is searchable.

Contributor guide

Open the contributing guide

Research direction

Read docs/ats/user-guides/creating-bond.md, packages/ats/sdk/README.md, and the #1391 quick reference, then compare their minting guidance with packages/ats/contracts/contracts/facets/mint/Mint.sol and the KYC wrappers named in the issue. Done means all three documentation entry points state that the recipient, including the issuer, needs GRANTED KYC when KYC is active and make InvalidKycStatus searchable.

Written by the indexing model from the issue text.

Assessment

Tech stack
solidity, typescript
Domain
blockchain, documentation
Issue type
Documentation
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.