Constructor

The constructor sets up the initial token configuration:

constructor() Ownable(msg.sender) {
    _name = "Confidential USD";
    _symbol = "cUSD";
}

Minting Tokens

There are two minting functions for different use cases:

// Standard minting with plaintext amount
function mint(uint256 mintedAmount) public virtual onlyOwner {
    balances[owner()] = e.add(
        balances[owner()],
        e.asEuint256(mintedAmount)
    );
    e.allow(balances[owner()], address(this));
    e.allow(balances[owner()], owner());
    _totalSupply += mintedAmount;
    emit Mint(owner(), mintedAmount);
}

// Minting with encrypted amount
function _mint(bytes calldata encryptedAmount) public virtual onlyOwner {
    balances[msg.sender] = e.add(
        balances[msg.sender],
        e.newEuint256(encryptedAmount, msg.sender)
    );
    e.allow(balances[msg.sender], address(this));
    e.allow(balances[msg.sender], owner());
    e.allow(balances[msg.sender], msg.sender);
}

The _mint function accepts encrypted amounts for enhanced privacy.

Transfer Functions

Two versions of transfer are available:

// For EOAs using encrypted inputs
function transfer(
    address to,
    bytes calldata encryptedAmount
) public virtual returns (bool) {
    transfer(to, e.newEuint256(encryptedAmount, msg.sender));
    return true;
}

// For contract interactions
function transfer(
    address to,
    euint256 amount
) public virtual returns (bool) {
    ebool canTransfer = e.ge(balances[msg.sender], amount);
    _transfer(msg.sender, to, amount, canTransfer);
    return true;
}

Approval System

The approval system allows delegated spending:

// Approve for EOAs
function approve(
    address spender,
    bytes calldata encryptedAmount
) public virtual returns (bool) {
    approve(spender, e.newEuint256(encryptedAmount, msg.sender));
    return true;
}

// Approve for contracts
function approve(
    address spender,
    euint256 amount
) public virtual returns (bool) {
    _approve(msg.sender, spender, amount);
    emit Approval(msg.sender, spender);
    return true;
}

// Internal approval logic
function _approve(
    address owner,
    address spender,
    euint256 amount
) internal virtual {
    allowances[owner][spender] = amount;
    e.allow(amount, address(this));
    e.allow(amount, owner);
    e.allow(amount, spender);
}

TransferFrom Functions

For spending approved tokens:

// TransferFrom for EOAs
function transferFrom(
    address from,
    address to,
    bytes calldata encryptedAmount
) public virtual returns (bool) {
    transferFrom(from, to, e.newEuint256(encryptedAmount, msg.sender));
    return true;
}

// TransferFrom for contracts
function transferFrom(
    address from,
    address to,
    euint256 amount
) public virtual returns (bool) {
    ebool isTransferable = _updateAllowance(from, msg.sender, amount);
    _transfer(from, to, amount, isTransferable);
    return true;
}

View Functions

Functions to check balances and allowances:

// Get encrypted balance
function balanceOf(address wallet) public view virtual returns (euint256) {
    return balances[wallet];
}

// Get encrypted allowance
function allowance(
    address owner,
    address spender
) public view virtual returns (euint256) {
    return _allowance(owner, spender);
}

Owner Functions

Special functions for the contract owner:

// Request balance decryption
function requestUserBalanceDecryption(
    address user
) public onlyOwner returns (uint256) {
    euint256 encryptedBalance = balances[user];
    e.allow(encryptedBalance, address(this));

    uint256 requestId = e.requestDecryption(
        encryptedBalance,
        this.onDecryptionCallback.selector,
        ""
    );
    requestIdToUserAddress[requestId] = user;
    return requestId;
}

// Decryption callback
function onDecryptionCallback(
    uint256 requestId,
    bytes32 _decryptedAmount,
    bytes memory data
) public returns (bool) {
    address userAddress = requestIdToUserAddress[requestId];
    emit UserBalanceDecrypted(userAddress, uint256(_decryptedAmount));
    return true;
}

Next Steps

See how all these functions come together in the complete contract