diff --git a/arc-0020/README.md b/arc-0020/README.md index 1c5754a..bb5917e 100644 --- a/arc-0020/README.md +++ b/arc-0020/README.md @@ -34,6 +34,53 @@ Without a standard interface, every DeFi program must import each token at compi The fungible token interface. Every ARC-20 token must implement these functions and **`view fn`** accessors: +```leo +interface IARC20 { + record Token { + owner: address, + amount: u128, + .. + } + //============================================================= + // TRANSFER FUNCTIONS + //============================================================= + fn transfer_public(public recipient: address, public amount: u128) -> Final; + fn transfer_private(private input: Token, private recipient: address, private amount: u128) -> (Token, Token); + fn transfer_private_to_public(private input: Token, public recipient: address, public amount: u128) -> (Token, Final); + fn transfer_public_to_private(private recipient: address, public amount: u128) -> (Token, Final); + fn transfer_public_as_signer(public recipient: address, public amount: u128) -> Final; + fn transfer_from_public(public owner: address, public recipient: address, public amount: u128) -> Final; + fn transfer_from_public_to_private( + public owner: address, + private recipient: address, + public amount: u128, + ) -> (Token, Final); + + //============================================================= + // APPROVAL FUNCTIONS + //============================================================= + fn approve_public(public spender: address, public amount: u128) -> Final; + fn unapprove_public(public spender: address, public amount: u128) -> Final; + + //============================================================= + // JOIN/SPLIT FUNCTIONS + //============================================================= + fn join(private input_1: Token, private input_2: Token) -> Token; + fn split(private input: Token, private amount: u128) -> (Token, Token); + + //============================================================= + // VIEW FUNCTIONS + //============================================================= + view fn balance_of(account: address) -> u128; + view fn allowance(owner: address, spender: address) -> u128; + view fn supply() -> u128; + view fn max_supply() -> u128; + view fn decimals() -> u8; + view fn name() -> identifier; + view fn symbol() -> identifier; +} +``` + ### Record Types **Token** -- Represents a private token balance. Implementations may add additional fields beyond `owner` and `amount`: diff --git a/arc-0022/README.md b/arc-0022/README.md index c641d21..8d340e9 100644 --- a/arc-0022/README.md +++ b/arc-0022/README.md @@ -40,6 +40,75 @@ The ARC-22 standard provides a library ([`IARC22`](./IARC22)), which is composed The compliant token surface adds freeze-list enforcement (via Merkle non-inclusion proofs on private sends) and investigator-visible **`ComplianceRecord`** outputs on every transition that materially changes a balance. Mappings and storage variables are intentionally **not** part of the interface; only function signatures and the records (**`Token`**, **`ComplianceRecord`**) form the contract. +```leo +interface IARC22 { + record Token { + owner: address, + amount: u128, + .. + } + + record ComplianceRecord { + owner: address, // INVESTIGATOR_ADDRESS + amount: u128, + sender: address, // ZERO_ADDRESS for mint paths + recipient: address, // ZERO_ADDRESS for burn paths + .. + } + + //============================================================= + // APPROVAL FUNCTIONS + //============================================================= + fn approve_public(public spender: address, public amount: u128) -> Final; + fn unapprove_public(public spender: address, public amount: u128) -> Final; + + //============================================================= + // TRANSFER FUNCTIONS + //============================================================= + fn transfer_public(public recipient: address, public amount: u128) -> Final; + fn transfer_private( + private recipient: address, + private amount: u128, + private input_record: Token, + private sender_merkle_proofs: [MerkleProof; 2u32], + ) -> (ComplianceRecord, Token, Token, Final); + fn transfer_private_to_public( + public recipient: address, + public amount: u128, + private input_record: Token, + private sender_merkle_proofs: [MerkleProof; 2u32], + ) -> (ComplianceRecord, Token, Final); + fn transfer_public_to_private(recipient: address, public amount: u128) -> ( + ComplianceRecord, Token, Final, + ); + fn transfer_from_public(public owner: address, public recipient: address, public amount: u128) -> Final; + fn transfer_from_public_to_private( + public owner: address, + private recipient: address, + public amount: u128, + ) -> (ComplianceRecord, Token, Final); + fn transfer_public_as_signer(public recipient: address, public amount: u128) -> Final; + + //============================================================= + // JOIN/SPLIT FUNCTIONS + //============================================================= + fn join(input_1: Token, input_2: Token) -> Token; + fn split(input: Token, amount: u128) -> (Token, Token); + + //============================================================= + // VIEW FUNCTIONS + //============================================================= + view fn balance_of(account: address) -> u128; + view fn allowance(owner: address, spender: address) -> u128; + view fn supply() -> u128; + view fn max_supply() -> u128; + view fn decimals() -> u8; + view fn name() -> identifier; + view fn symbol() -> identifier; +} + +``` + **Merkle non-inclusion proofs** are required only on transitions where the sender is private -- **`transfer_private`** and **`transfer_private_to_public`**. Transitions where the sender is public -- **`transfer_public_to_private`** and **`transfer_from_public_to_private`** -- check the sender against the freeze list directly via **`is_frozen_address`** (or the equivalent **`verify_non_inclusion_pub`** helper). **Compliance coverage.** Every transition that moves balances on a private path -- **`transfer_private`**, **`transfer_private_to_public`**, **`transfer_public_to_private`**, and **`transfer_from_public_to_private`** -- emits a **`ComplianceRecord`** owned by **`INVESTIGATOR_ADDRESS`**, so the investigator can decrypt the full sender / recipient / amount tuple whenever at least one side is private.