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