COTI V2 Documentation
  • Welcome
  • Networks
    • Faucet
    • Contracts Addresses
    • Adding the COTI Network to Metamask
  • How COTI Works
    • Introduction
      • EVM Introduction
      • Conceptual Overview
      • Use Cases and Applications
      • COTI Architecture
    • Advanced Topics
      • Garbled Circuits
      • AES Keys
      • Precompiles
      • Whitepaper
      • COTI vs others
  • Build on COTI
    • Core Concepts
      • Account Onboarding Procedure
      • Private Data Types
      • Supported Operations on Private Data Types
    • Quickstart
    • Guides
      • Basic Private Smart Contract
      • Account Onboard
      • Sending a Transaction with Encrypted Inputs
      • Resolving a Transaction's Encrypted Outputs
      • Writing a Private Smart Contract
      • Dos and Don'ts
        • Proper Use of Types
        • No Constant/Immutable Secret Types
        • No Public Contract Variables
      • Best Practices
        • Careful Onboarding
        • Careful Decrypting
        • Don't loop over an array without an index
        • Check Overflow
    • Tools
      • TypeScript SDK
      • Ethers.js
      • Python SDK
      • Web3.py
      • Contracts Library
        • MPC Core
        • Data Privacy Framework
        • Tokens
          • Private ERC20
          • Private ERC721
        • Onboard
      • Hardhat
      • Remix Plugin
      • COTI MetaMask Snap
      • Developer Sandbox
  • Running a COTI Node
    • COTI Node Ecosystem Litepaper
  • COTI Bridge
    • Swap COTI V1 Funds to COTI V2
  • Support and Community
    • Glossary
    • Telegram
    • Discord
    • GitHub
    • X
    • YouTube
  • COTI Builders Program
Powered by GitBook
On this page
  • Never save garbledtext in storage
  • Never Pass Ciphertext as Parameter to Another Contract or As User Input
  • Never Return a Ciphertext to Another Contract

Was this helpful?

Edit on GitHub
  1. Build on COTI
  2. Guides
  3. Dos and Don'ts

Proper Use of Types

Never save garbledtext in storage

Never save garbledtext in storage

Garbledtext is an intermediate random value, It's crucial to understand that these values are transient, existing only for the duration of the transaction's execution and promptly deleted once the execution is completed. Storing such a type will cause a loss of data as it has no meaning once the execution is completed.\

Don't

contract BadContract {
  gtUint64 private storedGarbledText;

  function setZero() public{
    storedGarbledText = mpcCore.SetPublic64(0);
  }
}  

Do

contract GoodContract {
  ctUint64 private storedCipherText;
                                                
  function setZero() public {
    gtUint64 gtZero = mpcCore.SetPublic64(0);
    storedCipherText = mpcCore.offboard(gtZero);  
  }
}

Never Pass Ciphertext as Parameter to Another Contract or As User Input

Sending a ciphertext from an Externally Owned Account (EOA) will fail unless it is accompanied by the correct signature to pass validation. Moreover, transmitting ciphertext between different contracts renders it invalid within the scope of the receiving contract and thus ineffective.

Don't

contract BadContract {
  ctUint8 private ctVal;
  
  function passCiphertext(ctUint8 val) public {
   ctVal = val;
  }
}

Do

contract GoodContract {
  ctUint8 private ctDouble;
  
  function passGarbledtext(gtUint8 val) public {
   gtUint8 gtDouble = MpcCore.add(val, val);
   ctDouble = MpcCore.offBoard(gtDouble)
  }
}

Or

contract GoodContract {
  ctUint8 private ct;
  
  function passInputtext(ctUint64 _itCT, bytes calldata _itSignature) public {
    itUint64 memory it;
    it.ciphertext = _itCT;
    it.signature = _itSignature;
    // validate the IT and
    gtUserInput = MpcCore.validateCiphertext(it);
    ct = MpcCore.offBoard(gtUserInput )
  }
}

Never Return a Ciphertext to Another Contract

Returning a ciphertext for future use in a different contract is not feasible, rendering such an action pointless. However, it is logical to return such a type to an Externally Owned Account (EOA) if it was specifically designated for that particular user.

Don't : do not return system encrypted ciphertext

contract BadContract {
  ctUint8 private ctVal;
  
  function passCiphertext(ctUint8 val) public returns (ctUint16){
   return ctVal;
  }
}

Do : return ciphertext to a specific user

contract GoodContract {
  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);
  }
}

Do : return** garbledtext **to a contract

contract GoodContract {
  function contractTransfer(address _to, gtUint64 _value) public returns (gtBool success){
    (gtUint64 fromBalance, gtUint64 toBalance) = getBalances(msg.sender, _to);
    (gtUint64 newFromBalance, gtUint64 newToBalance, gtBool result) = MpcCore.transfer(fromBalance, toBalance, _value);
  
    emit Transfer(msg.sender, _to);
    setNewBalances(msg.sender, _to, newFromBalance, newToBalance);
  
    return result;
   }
}
PreviousDos and Don'tsNextNo Constant/Immutable Secret Types

Was this helpful?