🧩Use Cases On-Chain Privacy
Private ERC20
A private ERC-20 on gcEVM enables confidential token transfers and balances directly on-chain, without sacrificing composability or compliance. Built on garbled-circuit-based decentralized confidential compute, gcEVM executes standard ERC-20 logic inside encrypted circuits, ensuring that transaction amounts, sender, and receiver remain hidden while the network still enforces validity and prevents double-spending. This allows enterprises, DAOs, and DeFi protocols to use fungible tokens for payroll, stablecoin payments, or trading with programmable privacy.
Illustration
The following illustrates the operation of garbled circuits to accomplish a private ERC20 transfer. 
On the left side there is a normal ERC20 transfer function, that given the balances of user A and B (i.e., balanceA and balanceB), as well as the amount to transfer from A to B, verifies that A's balance is equal or greater than the amount to transfer, in that case it decreases the amount from A's balance and increases that same amount from B's address. The transfer function results with new balances for A and B and a boolean that specifies whether the transfer succeeded or not.
On the right side you see the private analogue, now the transfer function is given encrypted values balanceA, balanceB and amount and returns updated encrypted amounts for balanceA, balanceB as well as an encrypted value for success (we note that  success can also be returned unencrypted). The encrypted values are fed into garbled circuits (the green boxes) to compute different operations that together represent the transfer functionality. Note that the balances and the amount remain encrypted at all time, and are inaccessible to any single party. It is a property of garbled circuits that they can get encrypted values, perform computation on them while encrypted, and return encrypted results. 

Private ERC20: The balanceOf and transfer Methods
balanceOf and transfer Methodscontract PrivateERC20Contract {
    // ... some variables and functions ...
    // The function returns the encrypted account balance utilizing the user's secret key. 
    // Since the balance is initially encrypted internally using the system's AES key, the user cannot access it. 
    // Thus, the balance undergoes re-encryption using the user's secret key. 
    // As a result, the function is not designated as a "view" function.
    function balanceOf() public returns (ctUint64 balance){
        ctUint64 balance = balances[msg.sender];
        // The balance is saved encrypted using the system key. However, to allow the user to access it, the balance needs to be re-encrypted using the user key. 
        // Therefore, we decrypt the balance (onBoard) and then encrypt it again using the user key (offBoardToUser).
        gtUint64 balanceGt = MpcCore.onBoard(balance);
        return MpcCore.offBoardToUser(balanceGt, msg.sender);
    }
    // Transfers the amount of tokens given inside the IT (encrypted and signed value) to address _to
    // params: _to: the address to transfer to
    //         _itCT: the encrypted value of the amount to transfer
    //         _itSignature: the signature of the amount to transfer
    //         revealRes: indicates if we should reveal the result of the transfer
    // returns: In case revealRes is true, returns the result of the transfer. In case revealRes is false, always returns true
    function transfer(address _to, ctUint64 _itCT, bytes calldata _itSignature, bool revealRes) public returns (bool success){
        // Create IT from ciphertext and signature
        itUint64 memory it;
        it.ciphertext = _itCT;
        it.signature = _itSignature;
        // Verify the IT and transfer the value
        gtBool result = contractTransfer(_to, MpcCore.validateCiphertext(it));
        if (revealRes){
            return MpcCore.decrypt(result);
        } else {
            return true;
        }
    }The MpcCore Solidity Library
Note that the above code example from the Private ERC20 uses functions from the MpcCore library, this library exposes to developers all required functionality in order to accomplish privacy preserving smart contracts. See below for a small subset of functions supported by the MpcCore library.
Explore this repository to get familiarity with the entire set of functions.
https://github.com/soda-mpc/soda-contracts/blob/master/lib/solidity/MpcCore.sol
contract SimpleSecretContract {
    uint256 public storedData;
    function PrecompileCheck(gtUint8 input) public {
        // Set public value to 5
        gtUint8 publicValue = MpcCore.setPublic8(uint8(5));
        // Add the input value to the public value
        gtUint8 sum = MpcCore.add(publicValue, input); 
        
        // Check if the sum is not equal to the original value
        gtBool isDifferent = MpcCore.ne(sum, publicValue);
        // Use a multiplexer based on the comparison result
        gtMux = MpcCore.mux(isDifferent, publicValue, sum);
        // Retrieve the selected value from the multiplexer
        ctUint8 selectedValue = MpcCore.offBoard(gtMux);
        // Store the selected value
        gtUint8 selectedGtUintValue = MpcCore.onBoard(selectedValue);
        
        // Negate the comparison result
        gtBool isSame = MpcCore.not(isDifferent);
        // Decrypt the negated boolean value
        bool isSameDecrypted = MpcCore.decrypt(isSame);
        // Use the decrypted boolean value to choose which data to store
        if (isSameDecrypted) {
            storedData = uint256(MpcCore.decrypt(selectedGtUintValue )); 
        } else {
            storedData = uint256(MpcCore.decrypt(sum));
        }
    }
}Last updated