diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index 982c645..a0d2210 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -2,25 +2,23 @@ - [What is fhEVM ecosystem?](README.md) -## fhevmjs - -- [Getting Started](sdk/getting_started.md) -- [Using the CLI](sdk/cli.md) -- [Instance](sdk/instance.md) -- [Parameters](sdk/parameters.md) -- [Reencryption](sdk/reencryption.md) -- ## [Examples](sdk/examples.md) - - - -## Solidity +## Contract - [Getting Started](solidity/getting_started.md) - [TFHE Library](solidity/library.md) - [Function specifications](solidity/functions.md) - [Decryption and control structures](solidity/requires.md) -## Examples +## fhevmjs + +- [Getting Started](sdk/getting_started.md) +- [Using the CLI](sdk/cli.md) +- [Setup an instance](sdk/instance.md) +- [Inputs](sdk/inputs.md) +- [Reencryption](sdk/reencryption.md) +- [Examples](sdk/examples.md) + +## Resources -- [ERC-20](examples/erc20.md) -- [Blind auction](examples/blindauction.md) -- [Other examples](examples/other.md) +- [Tutorials](resources/tutorials.md) +- [Examples](resources/examples.md) diff --git a/docs/examples/blindauction.md b/docs/examples/blindauction.md deleted file mode 100644 index f0123a4..0000000 --- a/docs/examples/blindauction.md +++ /dev/null @@ -1,164 +0,0 @@ -# Blind auction - -```solidity -// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity >=0.8.13 <0.8.20; - -import "fhevm/TFHE.sol"; - -import "fhevm/abstracts/EIP712WithModifier.sol"; - -import "./EncryptedERC20.sol"; - -contract BlindAuction is EIP712WithModifier { - uint public endTime; - - address public beneficiary; - - // Current highest bid. - euint32 internal highestBid; - - // Mapping from bidder to their bid value. - mapping(address => euint32) public bids; - - // Number of bid - uint public bidCounter; - - // The token contract used for encrypted bids. - EncryptedERC20 public tokenContract; - - // Whether the auction object has been claimed. - bool public objectClaimed; - - // If the token has been transferred to the beneficiary - bool public tokenTransferred; - - bool public stoppable; - - bool public manuallyStopped = false; - - // The owner of the contract. - address public contractOwner; - - // The function has been called too early. - // Try again at `time`. - error TooEarly(uint time); - // The function has been called too late. - // It cannot be called after `time`. - error TooLate(uint time); - - event Winner(address who); - - constructor( - address _beneficiary, - EncryptedERC20 _tokenContract, - uint biddingTime, - bool isStoppable - ) EIP712WithModifier("Authorization token", "1") { - beneficiary = _beneficiary; - tokenContract = _tokenContract; - endTime = block.timestamp + biddingTime; - objectClaimed = false; - tokenTransferred = false; - bidCounter = 0; - stoppable = isStoppable; - contractOwner = msg.sender; - } - - // Bid an `encryptedValue`. - function bid(bytes calldata encryptedValue) public onlyBeforeEnd { - euint32 value = TFHE.asEuint32(encryptedValue); - euint32 existingBid = bids[msg.sender]; - if (TFHE.isInitialized(existingBid)) { - ebool isHigher = TFHE.lt(existingBid, value); - // Update bid with value - bids[msg.sender] = TFHE.cmux(isHigher, value, existingBid); - // Transfer only the difference between existing and value - euint32 toTransfer = TFHE.sub(value, existingBid); - // Transfer only if bid is higher - euint32 amount = TFHE.mul(TFHE.asEuint8(isHigher), toTransfer); - tokenContract.transferFrom(msg.sender, address(this), amount); - } else { - bidCounter++; - bids[msg.sender] = value; - tokenContract.transferFrom(msg.sender, address(this), value); - } - euint32 currentBid = bids[msg.sender]; - if (!TFHE.isInitialized(highestBid)) { - highestBid = currentBid; - } else { - highestBid = TFHE.cmux(TFHE.lt(highestBid, currentBid), currentBid, highestBid); - } - } - - function getBid( - bytes32 publicKey, - bytes calldata signature - ) public view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - return TFHE.reencrypt(bids[msg.sender], publicKey, 0); - } - - // Returns the user bid - function stop() public onlyContractOwner { - require(stoppable); - manuallyStopped = true; - } - - // Returns an encrypted value of 0 or 1 under the caller's public key, indicating - // if the caller has the highest bid. - function doIHaveHighestBid( - bytes32 publicKey, - bytes calldata signature - ) public view onlyAfterEnd onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - if (TFHE.isInitialized(highestBid) && TFHE.isInitialized(bids[msg.sender])) { - return TFHE.reencrypt(TFHE.le(highestBid, bids[msg.sender]), publicKey); - } else { - return TFHE.reencrypt(TFHE.asEuint32(0), publicKey); - } - } - - // Claim the object. Succeeds only if the caller has the highest bid. - function claim() public onlyAfterEnd { - require(!objectClaimed); - TFHE.req(TFHE.le(highestBid, bids[msg.sender])); - - objectClaimed = true; - bids[msg.sender] = TFHE.NIL32; - emit Winner(msg.sender); - } - - // Transfer token to beneficiary - function auctionEnd() public onlyAfterEnd { - require(!tokenTransferred); - - tokenTransferred = true; - tokenContract.transfer(beneficiary, highestBid); - } - - // Withdraw a bid from the auction to the caller once the auction has stopped. - function withdraw() public onlyAfterEnd { - euint32 bidValue = bids[msg.sender]; - if (!objectClaimed) { - TFHE.req(TFHE.lt(bidValue, highestBid)); - } - tokenContract.transfer(msg.sender, bidValue); - bids[msg.sender] = TFHE.NIL32; - } - - modifier onlyBeforeEnd() { - if (block.timestamp >= endTime || manuallyStopped == true) revert TooLate(endTime); - _; - } - - modifier onlyAfterEnd() { - if (block.timestamp <= endTime && manuallyStopped == false) revert TooEarly(endTime); - _; - } - - modifier onlyContractOwner() { - require(msg.sender == contractOwner); - _; - } -} -``` diff --git a/docs/examples/erc20.md b/docs/examples/erc20.md deleted file mode 100644 index e2d568a..0000000 --- a/docs/examples/erc20.md +++ /dev/null @@ -1,129 +0,0 @@ -# ERC-20 - -```solidity -// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity >=0.8.13 <0.8.20; - -import "fhevm/abstracts/EIP712WithModifier.sol"; - -import "fhevm/TFHE.sol"; - -contract EncryptedERC20 is EIP712WithModifier { - euint32 private totalSupply; - string public constant name = "Naraggara"; // City of Zama's battle - string public constant symbol = "NARA"; - uint8 public constant decimals = 18; - - // used for output authorization - bytes32 private DOMAIN_SEPARATOR; - - // A mapping from address to an encrypted balance. - mapping(address => euint32) internal balances; - - // A mapping of the form mapping(owner => mapping(spender => allowance)). - mapping(address => mapping(address => euint32)) internal allowances; - - // The owner of the contract. - address public contractOwner; - - constructor() EIP712WithModifier("Authorization token", "1") { - contractOwner = msg.sender; - } - - // Sets the balance of the owner to the given encrypted balance. - function mint(bytes calldata encryptedAmount) public onlyContractOwner { - euint32 amount = TFHE.asEuint32(encryptedAmount); - balances[contractOwner] = TFHE.add(balances[contractOwner], amount); - totalSupply = TFHE.add(totalSupply, amount); - } - - // Transfers an encrypted amount from the message sender address to the `to` address. - function transfer(address to, bytes calldata encryptedAmount) public { - transfer(to, TFHE.asEuint32(encryptedAmount)); - } - - // Transfers an amount from the message sender address to the `to` address. - function transfer(address to, euint32 amount) public { - _transfer(msg.sender, to, amount); - } - - function getTotalSupply( - bytes32 publicKey, - bytes calldata signature - ) public view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - return TFHE.reencrypt(totalSupply, publicKey, 0); - } - - // Returns the balance of the caller encrypted under the provided public key. - function balanceOf( - bytes32 publicKey, - bytes calldata signature - ) public view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - return TFHE.reencrypt(balances[msg.sender], publicKey, 0); - } - - // Sets the `encryptedAmount` as the allowance of `spender` over the caller's tokens. - function approve(address spender, bytes calldata encryptedAmount) public { - address owner = msg.sender; - _approve(owner, spender, TFHE.asEuint32(encryptedAmount)); - } - - // Returns the remaining number of tokens that `spender` is allowed to spend - // on behalf of the caller. The returned ciphertext is under the caller public FHE key. - function allowance( - address spender, - bytes32 publicKey, - bytes calldata signature - ) public view onlySignedPublicKey(publicKey, signature) returns (bytes memory) { - address owner = msg.sender; - - return TFHE.reencrypt(_allowance(owner, spender), publicKey); - } - - // Transfers `encryptedAmount` tokens using the caller's allowance. - function transferFrom(address from, address to, bytes calldata encryptedAmount) public { - transferFrom(from, to, TFHE.asEuint32(encryptedAmount)); - } - - // Transfers `amount` tokens using the caller's allowance. - function transferFrom(address from, address to, euint32 amount) public { - address spender = msg.sender; - _updateAllowance(from, spender, amount); - _transfer(from, to, amount); - } - - function _approve(address owner, address spender, euint32 amount) internal { - allowances[owner][spender] = amount; - } - - function _allowance(address owner, address spender) internal view returns (euint32) { - if (TFHE.isInitialized(allowances[owner][spender])) { - return allowances[owner][spender]; - } else { - return TFHE.asEuint32(0); - } - } - - function _updateAllowance(address owner, address spender, euint32 amount) internal { - euint32 currentAllowance = _allowance(owner, spender); - TFHE.req(TFHE.le(amount, currentAllowance)); - _approve(owner, spender, TFHE.sub(currentAllowance, amount)); - } - - // Transfers an encrypted amount. - function _transfer(address from, address to, euint32 amount) internal { - // Make sure the sender has enough tokens. - TFHE.req(TFHE.le(amount, balances[from])); - - // Add to the balance of `to` and subract from the balance of `from`. - balances[to] = TFHE.add(balances[to], amount); - balances[from] = TFHE.sub(balances[from], amount); - } - - modifier onlyContractOwner() { - require(msg.sender == contractOwner); - _; - } -} -``` diff --git a/docs/examples/other.md b/docs/resources/examples.md similarity index 51% rename from docs/examples/other.md rename to docs/resources/examples.md index 242fd2d..d804576 100644 --- a/docs/examples/other.md +++ b/docs/resources/examples.md @@ -1,7 +1,10 @@ -# Other examples +# Examples -## Solidity +## Contracts +- [ERC-20](https://github.com/zama-ai/fhevm-solidity/blob/main/examples/EncryptedERC20.sol) +- [Blind Auction](https://github.com/zama-ai/fhevm-solidity/blob/main/examples/BlindAuction.sol) +- [Governor DAO](https://github.com/zama-ai/fhevm-solidity/tree/main/examples/Governor) - [Mixnet](https://github.com/anonymousGifter/mixnet-core) by [Remi Gai](https://github.com/remi-gai) - [Battleship](https://github.com/battleship-fhevm/battleship-hardhat) by [Owen Murovec](https://github.com/omurovec) - [Darkpool](https://github.com/omurovec/fhe-darkpools) by [Owen Murovec](https://github.com/omurovec) diff --git a/docs/resources/tutorials.md b/docs/resources/tutorials.md new file mode 100644 index 0000000..76d5fe4 --- /dev/null +++ b/docs/resources/tutorials.md @@ -0,0 +1,5 @@ +# Tutorials + +- [Workshop during ETHcc](https://www.youtube.com/watch?v=eivfVykPP8U) by Morten Dahl (Zama) +- [Confidential ERC-20 Tokens Using Homomorphic Encryption](https://www.zama.ai/post/confidential-erc-20-tokens-using-homomorphic-encryption) by Clément Danjou (Zama) +- [On-chain Blind Auctions Using Homomorphic Encryption](https://www.zama.ai/post/on-chain-blind-auctions-using-homomorphic-encryption) by Clément Danjou (Zama) diff --git a/docs/sdk/getting_started.md b/docs/sdk/getting_started.md index 7eca44f..5e8854a 100644 --- a/docs/sdk/getting_started.md +++ b/docs/sdk/getting_started.md @@ -4,7 +4,7 @@ Welcome to the documentation for fhevmjs, a JavaScript library that enables inte ## Installation -To get started with fhevmjs, you need to install it as a dependency in your JavaScript project. You can do this using npm (Node Package Manager) or Yarn. Open your terminal and navigate to your project's directory, then run one of the following commands: +To get started with fhevmjs, you need to install it as a dependency in your JavaScript project. You can do this using npm, Yarn or pnpm. Open your terminal and navigate to your project's directory, then run one of the following commands: ```bash # Using npm @@ -12,6 +12,9 @@ npm install fhevmjs # Using Yarn yarn add fhevmjs + +# Using pnpm +pnpm add fhevmjs ``` This will download and install the fhevmjs library and its dependencies into your project. @@ -66,18 +69,6 @@ You can take a look at [this template](https://github.com/zama-ai/fhevmjs-react- #### Troubleshooting -##### Module not found: Error: Can't resolve 'tfhe_bg.wasm' - -In the codebase, there is a `new URL('tfhe_bg.wasm')` which triggers a resolve by Webpack. If you encounter an issue, you can add a fallback for this file by adding a resolve configuration in your `webpack.config.js`: - -```javascript - resolve: { - fallback: { - 'tfhe_bg.wasm': require.resolve('tfhe/tfhe_bg.wasm'), - }, - }, -``` - ##### Issue with importing ESM version With a bundler such as Webpack or Rollup, imports will be replaced with the version mentioned in the `"browser"` field of the `package.json`. diff --git a/docs/sdk/parameters.md b/docs/sdk/inputs.md similarity index 98% rename from docs/sdk/parameters.md rename to docs/sdk/inputs.md index 1995e12..b874db0 100644 --- a/docs/sdk/parameters.md +++ b/docs/sdk/inputs.md @@ -1,4 +1,4 @@ -# Parameters +# Encrypted inputs The library provides a set of functions to encrypt integers of various sizes (8, 16, and 32 bits) using the blockchain's public key. These encrypted integers can then be securely used as parameters for smart contract methods within the blockchain ecosystem. diff --git a/docs/sdk/instance.md b/docs/sdk/instance.md index f841775..70e51d7 100644 --- a/docs/sdk/instance.md +++ b/docs/sdk/instance.md @@ -1,4 +1,9 @@ -# Instance +# Setup an instance + +First, you need to create an instance. An instance allows you to: + +- Encrypt inputs with blockchain public key +- Manage user keys to reencrypt contract's encrypted data ## createInstance