Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions arc-0020/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
69 changes: 69 additions & 0 deletions arc-0022/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading