From 3ec98e7e9acb05a630386d361a7a7b8521748c6c Mon Sep 17 00:00:00 2001 From: 0xjba Date: Tue, 15 Jul 2025 15:37:08 +0530 Subject: [PATCH] Revamp documentation structure - reorganize content and fix broken links --- .../for-developers/_category_.json | 2 +- .../for-developers/dapp-ideas.md | 2 +- .../for-developers/develop-deploy-dapp.md | 20 - .../explore-contracts-in-ten.md | 104 ----- .../explore-contracts-in-ten/_category_.json | 8 + .../explore-contracts-in-ten/index.md | 332 ++++++++++++++ .../for-developers/game-security.md | 111 +++++ .../for-developers/setup-dev-env.md | 7 +- .../getting-started/for-users/_category_.json | 7 - docs/getting-started/for-users/get-tokens.md | 16 - .../for-users/setup-you-wallet.md | 21 - .../for-validators/node-architecture.md | 0 .../for-validators/overview.md | 0 .../for-validators/rewards.md | 0 .../for-validators/running-a-node.md | 93 +++- docs/introduction/developer-quickstart.md | 416 +----------------- docs/introduction/overview.md | 2 - docs/standards-primitives/session-keys.md | 71 +++ docs/testnet/for-developers/_category_.json | 7 - docs/testnet/for-validators/_category_.json | 7 - docs/testnet/for-validators/running-a-node.md | 93 ---- docs/troubleshooting/faq.md | 2 +- 22 files changed, 636 insertions(+), 685 deletions(-) rename docs/{testnet => getting-started}/for-developers/dapp-ideas.md (99%) delete mode 100644 docs/getting-started/for-developers/develop-deploy-dapp.md delete mode 100644 docs/getting-started/for-developers/explore-contracts-in-ten.md create mode 100644 docs/getting-started/for-developers/explore-contracts-in-ten/_category_.json create mode 100644 docs/getting-started/for-developers/explore-contracts-in-ten/index.md create mode 100644 docs/getting-started/for-developers/game-security.md delete mode 100644 docs/getting-started/for-users/_category_.json delete mode 100644 docs/getting-started/for-users/get-tokens.md delete mode 100644 docs/getting-started/for-users/setup-you-wallet.md rename docs/{testnet => getting-started}/for-validators/node-architecture.md (100%) rename docs/{testnet => getting-started}/for-validators/overview.md (100%) rename docs/{testnet => getting-started}/for-validators/rewards.md (100%) create mode 100644 docs/standards-primitives/session-keys.md delete mode 100644 docs/testnet/for-developers/_category_.json delete mode 100644 docs/testnet/for-validators/_category_.json delete mode 100644 docs/testnet/for-validators/running-a-node.md diff --git a/docs/getting-started/for-developers/_category_.json b/docs/getting-started/for-developers/_category_.json index 4137740d..4c2e60fa 100644 --- a/docs/getting-started/for-developers/_category_.json +++ b/docs/getting-started/for-developers/_category_.json @@ -1,6 +1,6 @@ { "label": "For Developers", - "position": 2, + "position": 1, "link": { "type": "generated-index" } diff --git a/docs/testnet/for-developers/dapp-ideas.md b/docs/getting-started/for-developers/dapp-ideas.md similarity index 99% rename from docs/testnet/for-developers/dapp-ideas.md rename to docs/getting-started/for-developers/dapp-ideas.md index 2353491d..25268a50 100644 --- a/docs/testnet/for-developers/dapp-ideas.md +++ b/docs/getting-started/for-developers/dapp-ideas.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- # DApp Ideas diff --git a/docs/getting-started/for-developers/develop-deploy-dapp.md b/docs/getting-started/for-developers/develop-deploy-dapp.md deleted file mode 100644 index 4640809c..00000000 --- a/docs/getting-started/for-developers/develop-deploy-dapp.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -sidebar_position: 3 ---- -# Develop & Deploy dApp - -## 1. Develop Smart Contracts -Smart contracts are the backbone of your dApp, defining its rules and operations. Begin your development in Solidity based on the instructions [here](/docs/getting-started/for-developers/explore-contracts-in-ten). - -## 2. Develop the Frontend -Use common web tools like HTML, CSS, and JavaScript. You can consider ReactJs, VueJs to enhance development. To connect your frontend to Ethereum, choose a library such as Web3.js or Ether.js. See supported libraries [here](#). - -## 3. Integrating TEN Gateway -Users need to configure their wallets to connect with TEN the first time they access your dApp. - - **Gateway**: During the initial user onboarding, prompt users to visit the [TEN Gateway](https://gateway.ten.xyz/). By clicking "Connect to TEN Testnet" and following the on-screen instructions, they can easily configure their wallets. Learn more about the Hosted TEN Gateway [here](/docs/tools-infrastructure/hosted-gateway). - -## 4. Test & Deploy the Dapp -Before the final deployment, test your dApp in a controlled environment. This ensures that it interacts correctly with the blockchain and provides the desired user experience. Once satisfied with your dApp's functionality and performance, deploy it for public access. - -## 5. Verify & Track the Deployment -Post-Deployment it's essential to monitor your dApps performance and user interactions. Use the TENScan block explorer to verify and inspect the details of your deployed contract. This tool provides insights into transactions, contract interactions, and more. Learn how to use the block explorer [here](/docs/tools-infrastructure/tenscan). diff --git a/docs/getting-started/for-developers/explore-contracts-in-ten.md b/docs/getting-started/for-developers/explore-contracts-in-ten.md deleted file mode 100644 index 05ac4f2a..00000000 --- a/docs/getting-started/for-developers/explore-contracts-in-ten.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -sidebar_position: 1 ---- -# Explore Contracts in TEN - -TEN offers a distinct environment for smart contract development so you'll need to consider how to design your dApps slightly differently from how you would a transparent dApp. This guide explains these differences: - -## 1. Accessing Storage Values - -While both Ethereum and TEN allow easy access to public variables, their handling of private variables differs significantly, highlighting Ethereum's transparency challenges and TEN's privacy solutions. - -### Ethereum's Transparency Challenge - -In Ethereum, private variables are intended to be accessed solely through functions. However, due to Ethereum's transparent nature, a workaround exists using the `getStorageAt` function. This method can bypass the designated functions, making true private data storage unattainable. - -**Example**: -Accessing a private variable in Ethereum: -```solidity -uint256 value = eth.getStorageAt(contractAddress, position); -``` - -### TEN's Privacy Solution - -To provide privacy on Ethereum, TEN has disabled the `getStorageAt` function. This ensures that private variables can only be accessed via their associated functions, providing genuine programmable privacy. - -**Example**: -Accessing a private variable in TEN: -```solidity -private uint256 privateVariable; - -function getPrivateVariable() public view returns (uint256) { - return privateVariable; -} -``` - -In summary, while Ethereum's transparency poses challenges for true data privacy, TEN offers a robust solution by ensuring that private data remains genuinely private. - -## 2. Access Control for Functions - -In smart contract development, it's essential to ensure that only authorized entities can access certain functions. This is achieved using access control mechanisms. - -### Access Control Using `require` - -The `require` statement in Solidity is a straightforward way to enforce access control. It checks a condition, and if the condition is not met, the function execution stops, and an optional error message is thrown. - -**Example**: -```solidity -address owner = msg.sender; - -function restrictedFunction() public { - require(msg.sender == owner, "Only the owner can call this function."); - // Rest of the function logic -} -``` - -This example ensures that only the contract's owner can call the `restrictedFunction`. - -## 3. Event Visibility - -TEN has specific event visibility rules: - -- Lifecycle events without an address parameter are public. -- Events with an address parameter related to an account are private. - -**Example**: -```solidity -// Public event on TEN -event LifecycleEvent(uint256 indexed value); - -// Private event on TEN -event AccountEvent(address indexed account, uint256 value); -``` - -## 4. Secure Random Number Generation in TEN - -Random number generation on blockchains is challenging due to timing, delay, complexity, and fees. TEN offers a unique, immediate, and secure solution. - -### Challenges with On-Chain Randomness - -1. **Timing**: If block producers predict randomness, they can manipulate results. -2. **Delay**: Many solutions introduce a delay, affecting user experience. -3. **Complexity & Fees**: Solutions like oracles add overhead and costs. - -### TEN's Solution - -TEN nodes run on secure enclave's, ensuring: - -- **Immediate Randomness**: No delays. -- **Unpredictability**: Random numbers are based on an inaccessible private seed. -- **Simplicity & No Extra Fees**: Every transaction gets its random seed. - -**Example**: -```solidity -function getRandomNumber() public view returns (uint256) { - // TEN network injects a secure and unique seed to the prevrandao property, note: on other EVM chains this code would be exploitable by MEV bots - return uint256(block.prevrandao); -} -``` - -TEN's approach ensures secure and straightforward random number generation. For more information on using randomness in TEN, take a look at the [Random Numbers page](/docs/standards-primitives/random-numbers.md). - -## 5. Gas Consumption - -Gas consumption is a vital consideration in smart contract development. On TEN, it's essential to optimize your contract functions to ensure efficient gas usage. Always test your contracts in a simulated environment before deploying to gauge gas consumption. diff --git a/docs/getting-started/for-developers/explore-contracts-in-ten/_category_.json b/docs/getting-started/for-developers/explore-contracts-in-ten/_category_.json new file mode 100644 index 00000000..065d79a0 --- /dev/null +++ b/docs/getting-started/for-developers/explore-contracts-in-ten/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Smart Contracts", + "position": 2, + "link": { + "type": "generated-index", + "description": "Learn how to develop smart contracts for TEN and understand the key differences from Ethereum development." + } +} \ No newline at end of file diff --git a/docs/getting-started/for-developers/explore-contracts-in-ten/index.md b/docs/getting-started/for-developers/explore-contracts-in-ten/index.md new file mode 100644 index 00000000..c7d3c511 --- /dev/null +++ b/docs/getting-started/for-developers/explore-contracts-in-ten/index.md @@ -0,0 +1,332 @@ +--- +sidebar_position: 1 +--- + +# TEN vs Ethereum: Key Differences + +TEN offers a distinct environment for smart contract development so you'll need to consider how to design your dApps slightly differently from how you would a transparent dApp. This guide explains these differences: + +## 1. Accessing Storage Values + +While both Ethereum and TEN allow easy access to public variables, their handling of private variables differs significantly, highlighting Ethereum's transparency challenges and TEN's privacy solutions. + +### Ethereum's Transparency Challenge + +In Ethereum, private variables are intended to be accessed solely through functions. However, due to Ethereum's transparent nature, a workaround exists using the `getStorageAt` function. This method can bypass the designated functions, making true private data storage unattainable. + +**Example**: +Accessing a private variable in Ethereum: +```solidity +uint256 value = eth.getStorageAt(contractAddress, position); +``` + +### TEN's Privacy Solution + +To provide privacy on Ethereum, TEN has disabled the `getStorageAt` function. This ensures that private variables can only be accessed via their associated functions, providing genuine programmable privacy. + +**Example**: +Accessing a private variable in TEN: +```solidity +private uint256 privateVariable; + +function getPrivateVariable() public view returns (uint256) { + return privateVariable; +} +``` + +In summary, while Ethereum's transparency poses challenges for true data privacy, TEN offers a robust solution by ensuring that private data remains genuinely private. + +## 2. Access Control for Functions + +In smart contract development, it's essential to ensure that only authorized entities can access certain functions. This is achieved using access control mechanisms. + +### Access Control Using `require` + +The `require` statement in Solidity is a straightforward way to enforce access control. It checks a condition, and if the condition is not met, the function execution stops, and an optional error message is thrown. + +**Example**: +```solidity +address owner = msg.sender; + +function restrictedFunction() public { + require(msg.sender == owner, "Only the owner can call this function."); + // Rest of the function logic +} +``` + +This example ensures that only the contract's owner can call the `restrictedFunction`. + +## 3. Event Visibility + +TEN has specific event visibility rules: + +- Lifecycle events without an address parameter are public. +- Events with an address parameter related to an account are private. + +**Example**: +```solidity +// Public event on TEN +event LifecycleEvent(uint256 indexed value); + +// Private event on TEN +event AccountEvent(address indexed account, uint256 value); +``` + +## 4. Secure Random Number Generation in TEN + +Random number generation on blockchains is challenging due to timing, delay, complexity, and fees. TEN offers a unique, immediate, and secure solution. + +### Challenges with On-Chain Randomness + +1. **Timing**: If block producers predict randomness, they can manipulate results. +2. **Delay**: Many solutions introduce a delay, affecting user experience. +3. **Complexity & Fees**: Solutions like oracles add overhead and costs. + +### TEN's Solution + +TEN nodes run on secure enclave's, ensuring: + +- **Immediate Randomness**: No delays. +- **Unpredictability**: Random numbers are based on an inaccessible private seed. +- **Simplicity & No Extra Fees**: Every transaction gets its random seed. + +**Example**: +```solidity +function getRandomNumber() public view returns (uint256) { + // TEN network injects a secure and unique seed to the prevrandao property, note: on other EVM chains this code would be exploitable by MEV bots + return uint256(block.prevrandao); +} +``` + +TEN's approach ensures secure and straightforward random number generation. For more information on using randomness in TEN, take a look at the [Random Numbers page](/docs/standards-primitives/random-numbers.md). + +## 5. Gas Consumption + +Gas consumption is a vital consideration in smart contract development. On TEN, it's essential to optimize your contract functions to ensure efficient gas usage. Always test your contracts in a simulated environment before deploying to gauge gas consumption. + +## 6. Writing Smart Contracts for TEN + +TEN executes smart contracts within the EVM similarly to Ethereum, so you can reuse your existing code. +However, the execution and the internal state are hidden from everyone, including node operators and the sequencer. + +:::info +TEN encrypts both the execution and its internal database using Trusted Execution Environments (TEEs). +::: + +The [getStorageAt](https://docs.alchemy.com/reference/eth-getstorageat) method is disabled by default on TEN, so data access relies on view functions that you define. +Public variables remain accessible as Solidity automatically creates getters for them. + +Let's illustrate with a basic storage dApp example where users can store and retrieve a number. + +At every step, we'll add a new feature and explain the difference between `TEN` and `Ethereum`. + +### Step 1: Basic contract with a Public Variable + +#### Code + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +contract StorageExample { + mapping(address => uint256) public storedValues; + + function storeValue(uint256 value) public { + storedValues[tx.origin] = value; + } +} +``` + +#### Explanation + +In this step, we created a public variable `storedValues` that maps the provided value to the address of the user who called the `storeValue` function. + +Because the variable is public, Solidity will provide a default public getter for it. + +Since there are no data access restrictions, on both Ethereum and TEN, everyone will be able to read the values of all users. + +### Step 2: Converting to a Private Variable with an explicit Getter Function + +#### Code + +```solidity +contract StorageExample { + mapping(address => uint256) private _storedValues; + + function storeValue(uint256 value) public { + _storedValues[tx.origin] = value; + } + + function getValue(address account) public view returns (uint256) { + return _storedValues[account]; + } +} +``` + +#### Explanation + +The `storedValues` variable is now private, and we added a basic `getValue` function for users to retrieve their value. + +On both Ethereum and TEN, anyone can call `getValue` to retrieve any value. +On Ethereum, `_storedValues` can also be accessed directly with `getStorageAt` + +### Step 3: Data Access Control + +In this step, we'll add restrictions so users can only access their own data. + +#### Code + +```solidity +contract StorageExample { + mapping(address => uint256) private _storedValues; + + function storeValue(uint256 value) public { + _storedValues[tx.origin] = value; + } + + function getValue(address account) public view returns (uint256) { + require(tx.origin == account, "Not authorized!"); + return _storedValues[account]; + } +} +``` + +#### Explanation + +The key line is: ``require(tx.origin == account, "Not authorized!");``, which ensures that the caller of the view function is the owner of the data. + +:::info +TEN uses "Viewing Keys" to authenticate view function calls. +::: + +**When deployed on TEN, this code guarantees that all users can only access their own values, and nobody can read the `_storedValues`.** + +### Step 4: Emitting Events - Default Visibility + +Event logs notify UIs about state changes in smart contracts. + +To improve our smart contract, we'll emit an event when a user stores a value and milestone events when a specific size threshold is met. + +#### Code + +```solidity +contract StorageExample { + mapping(address => uint256) private _storedValues; + uint256 private totalCalls = 0; + + event DataChanged(address indexed account, uint256 newValue); + event MilestoneReached(uint256 noStoredValues); + + function storeValue(uint256 value) public { + _storedValues[tx.origin] = value; + emit DataChanged(tx.origin, value); + totalCalls++; + if (totalCalls % 1000 == 0) { + emit MilestoneReached(totalCalls); + } + } + + function getValue(address account) public view returns (uint256) { + require(tx.origin == account, "Not authorized!"); + return _storedValues[account]; + } +} +``` + +#### Explanation + +Notice how we defined the two events: `DataChanged` and `MilestoneReached`, and are emitting them in the `storeValue` function. + +In Ethereum, everyone can query and subscribe to these events. This obviously can't be the case for TEN because it would completely break the functionality. + +Notice how in this version, we have no configuration for event log visibility, so we are relying on the default rules. + +Rule 1: Event logs that contain EOAs as indexed fields (topics) are only visible to those EOAs. +Rule 2: Event logs that don't contain any EOA are visible to everyone. + +In our case, the default rules ensure that: +- `DataChanged` is visible only to the address that is storing the value. +- `MilestoneReached` is publicly visible. + + +### Step 5: Customizing Event Visibility + +The default visibility rules are a good starting point, but complex dApps require greater flexibility. + +TEN give you explicit control over event visibility. + +#### Code + +```solidity +interface ContractTransparencyConfig { + enum Field { TOPIC1, TOPIC2, TOPIC3, SENDER, EVERYONE } + enum ContractCfg { TRANSPARENT, PRIVATE } + + struct EventLogConfig { + bytes32 eventSignature; + Field[] visibleTo; + } + + struct VisibilityConfig { + ContractCfg contractCfg; + EventLogConfig[] eventLogConfigs; + } + + function visibilityRules() external pure returns (VisibilityConfig memory); +} + +contract StorageExample is ContractTransparencyConfig { + mapping(address => uint256) private _storedValues; + uint256 private totalCalls = 0; + + event DataChanged(address indexed account, uint256 newValue); + event MilestoneReached(uint256 noStoredValues); + + function storeValue(uint256 value) public { + _storedValues[tx.origin] = value; + emit DataChanged(tx.origin, value); + totalCalls++; + if (totalCalls % 1000 == 0) { + emit MilestoneReached(totalCalls); + } + } + + function getValue(address account) public view returns (uint256) { + require(tx.origin == account, "Not authorized!"); + return _storedValues[account]; + } + + function visibilityRules() external pure override returns (VisibilityConfig memory) { + EventLogConfig[] memory eventLogConfigs = new EventLogConfig[](2); + + // the signature of "event DataChanged(address indexed account, uint256 newValue);" + bytes32 dataChangedEventSig = hex"0xec851d5c322f7f1dd5581f7432e9f6683a8709a4b1ca754ccb164b82a7d2f"; + Field[] memory relevantTo = new Field[](2); + relevantTo[0] = Field.TOPIC1; + relevantTo[1] = Field.SENDER; + eventLogConfigs[0] = EventLogConfig(dataChangedEventSig, relevantTo); + + // the signature of "event MilestoneReached(uint256 noStoredValues);" + bytes32 milestoneReachedEventSig = hex"0xd41033274424d56dd572e7196fb4230cf4141d546b91fc00555cab8403965924"; + Field[] memory relevantTo = new Field[](1); + relevantTo[0] = Field.EVERYONE; + eventLogConfigs[1] = EventLogConfig(milestoneReachedEventSig, relevantTo); + + return VisibilityConfig(ContractCfg.PRIVATE, eventLogConfigs); + } +} +``` + +#### Explanation + +The `ContractTransparencyConfig` interface is known by the TEN platform. +When a contract is deployed, the platform will call the `visibilityRules` function, and store the `VisibilityConfig`. + +For each event type, you can configure which fields can access it. +This allows the developer to configure an event to be public even if it has EOAs or to allow the sender of the transaction to access events emitted even if the address is not in the event. + +Notice how in the `visibilityRules` above, we configure the `DataChanged` event to be visible to the first field and the sender, and the `MilestoneReached` to be visible to everyone. + +The other configuration: `VisibilityConfig.contractCfg` applies to the entire contract: +- `ContractCfg.TRANSPARENT`: The contracts will have public storage and events, behaving exactly like Ethereum. +- `ContractCfg.PRIVATE`: The default TEN behaviour, where the storage is not accessible and the events are individually configurable. \ No newline at end of file diff --git a/docs/getting-started/for-developers/game-security.md b/docs/getting-started/for-developers/game-security.md new file mode 100644 index 00000000..5c38a2f8 --- /dev/null +++ b/docs/getting-started/for-developers/game-security.md @@ -0,0 +1,111 @@ +--- +sidebar_position: 3 +--- + +# Game Security + +Every on-chain game developer knows that every move that relies on entropy must be executed in two steps. + +Imagine you implement an on-chain coin flip game. The player pays 0.1ETH to choose `Heads` or `Tails`. +If they win, they receive 0.2ETH, otherwise they lose the 0.1ETH. +Even if randomness is unpredictable, this simple game can be exploited in several ways: + +- The attacker can create a "proxy" smart contract to play on their behalf. Using a similar mechanism to flash loans in DeFi: the proxy is programmed to make multiple actions, and only "commit" if it can obtain a profit. In our case, if the coin flip is losing, the proxy can just revert. The only cost will be the gas burned. +- Transactions consume gas, and the gas cost can inadvertently reveal information. For instance, if a winning move is more computationally intensive than a losing one, players could deduce optimal moves by estimating gas costs for various actions. + +The typical solution is to use a commit-reveal scheme. The player commits to a move, and then reveals it. This way, the player can't change their mind after seeing the result. +This solution has the major drawback that it introduces extra complexity, latency and cost. + +## The on-block-end callback + +The best solution is to decouple the move from the execution without increasing the latency or the cost. +This way, the side-channel attacks are no longer possible because the move is not executed immediately. +To avoid increasing the latency, the move must be executed at the end of the block. +Note that contracts can define the handleRefund function, which will be called with value equal to what is left from the gas processing paid for. +This is called with enough gas to save locally how much should be refunded to whoever paid for the callback. + +See below a simple implementation of the coin flip game using the TEN platform: + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +// this interface is known by the TEN system contract +interface TenCallbacks { + function register(bytes calldata) external payable returns (uint256); +} + +interface Refunds { + function handleRefund(uint256 callbackId) external payable; +} + +contract CoinFlip { + // Event to emit the result of the coin flip + event CoinFlipResult(address indexed player, bool didWin, uint256 randomNumber); + + private TenCallbacks tenCallbacks; + mapping(uint256 callbackId => address player) public callbackToPlayer; + mapping(address player => uint256 refundAmount) public playerToRefundAmount; + + + + modifier onlyTenSystemCall() { + require(msg.sender == address(tenCallbacks)); + _; + } + + // you have to pass in the address of the callbacks contract + constructor(address _tenCallbacksAddress) { + tenCallbacks = TenCallbacks(_tenCallbacksAddress); + } + + // Function to initiate a coin flip. + // Notice how it doesn't execute the coin flip directly, but instead registers a callback. + function flipCoin(bool isHeads) external payable { + // Assume doFlipCoin costs 50_000 gas; + // We deduct a predetermined amount from the bet to pay for delayed execution. + uint256 etherGasForCoinFlip = 50_000*block.basefee; + require(msg.value > etherGasForCoinFlip, "Insufficent gas"); + + // Encode the function we want to be called by the TEN system contract. + bytes memory callbackTargetInfo = abi.encodeWithSelector(this.doFlipCoin.selector, msg.sender, msg.value - etherGasForCoinFlip, isHeads); + + tenCallbacks.register{value: etherGasForCoinFlip}(callbackTargetInfo); + } + + // Function to simulate a coin flip - notice that this must only be callable by the ten system contract. + // This function is called by the TEN platform as a synthetic transaction in the same block as the user transaction. + function doFlipCoin(address bettor, uint256 stake, bool wantsHeads) external onlyTenSystemCall { + // Assume getRandomNumber() is a function that returns a random number + uint256 randomNumber = getRandomNumber(); + + // Simulate a coin flip: 0 for tails, 1 for heads + bool isHeads = (randomNumber % 2) == 1; + + if (wantsHeads == isHeads) { + //pay out to winner + (bool success, ) = payable(bettor).call{value: stake*2}(""); + require(success, "Payment failed."); + } + // Emit the result of the coin flip + emit CoinFlipResult(msg.sender, isHeads, randomNumber); + } + + function getRandomNumber() internal view returns (uint256) { + return block.prevrandao; + } + + function handleRefund(uint256 callbackId) external payable { + address player = callbackToPlayer[callbackId]; + playerToRefundAmount[player] += msg.value; + } + + function claimRefund() external { + uint256 refundAmount = playerToRefundAmount[msg.sender]; + require(refundAmount > 0, "No refunds to claim"); + playerToRefundAmount[msg.sender] = 0; + (bool success, ) = payable(msg.sender).call{value: refundAmount}(""); + require(success, "Transfer failed"); + } + +} \ No newline at end of file diff --git a/docs/getting-started/for-developers/setup-dev-env.md b/docs/getting-started/for-developers/setup-dev-env.md index 59a82c61..f519c181 100644 --- a/docs/getting-started/for-developers/setup-dev-env.md +++ b/docs/getting-started/for-developers/setup-dev-env.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 1 --- # Set Up Dev Environment @@ -20,8 +20,3 @@ Once your wallet is ready, you can proceed with the development and deployment o 1. **Choose an IDE**: Use your preferred development environment or Integrated Development Environment (IDE) like Truffle, Remix, Hardhat, or Foundry. Check out IDE compatibility and its features [here](/docs/tools-infrastructure/compatible-tools). 2. **Connect IDE to MetaMask**: Ensure your chosen IDE is connected to your MetaMask wallet. - -## 3. Docker Configuration - -For developers running a node and infrastructure using Docker on a Mac, please be aware that you must **disable** the -“Use Rosetta for x86_64/amd64 emulation on Apple Silicon” setting. Failing to do so will prevent the testnet from running correctly. diff --git a/docs/getting-started/for-users/_category_.json b/docs/getting-started/for-users/_category_.json deleted file mode 100644 index 92b3329c..00000000 --- a/docs/getting-started/for-users/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "For Users", - "position": 1, - "link": { - "type": "generated-index" - } -} diff --git a/docs/getting-started/for-users/get-tokens.md b/docs/getting-started/for-users/get-tokens.md deleted file mode 100644 index 72a1598c..00000000 --- a/docs/getting-started/for-users/get-tokens.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Get Tokens - -## Use TEN Gas Station - -To obtain TEN ETH directly on the TEN testnet, utilize the TEN Gas Station. Remember, Follow these steps: - -1. Head over to [TEN Gas Station](https://faucet.ten.xyz/). -2. Paste your EVM wallet address into the wallet address field. -3. Log in with your Discord and X (Twitter) accounts. -4. Then, complete the available tasks. - -If your wallet balance remains unchanged, double-check your wallet configuration or refer to the [set up your wallet](/docs/getting-started/for-users/setup-you-wallet) page. diff --git a/docs/getting-started/for-users/setup-you-wallet.md b/docs/getting-started/for-users/setup-you-wallet.md deleted file mode 100644 index 85965c63..00000000 --- a/docs/getting-started/for-users/setup-you-wallet.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -sidebar_position: 1 ---- - -# Set up your wallet - -TEN is fully compatible with Ethereum and seamlessly integrates with MetaMask. If you're unfamiliar with MetaMask or wallets, start here. - -To engage with TEN: - -1. [Install](https://metamask.io/download/) MetaMask as a browser extension or mobile app. -2. To use TEN, you have to configure the wallet using the TEN Gateway. Go to the [TEN Gateway](https://gateway.ten.xyz/) for wallet setup, click 'Connect to TEN Testnet', and follow the setup steps. Know more about the TEN Gateway [here](/docs/tools-infrastructure/hosted-gateway). - -No matter your activity on TEN, you'll probably need tokens to make transactions. See our following section: [Getting tokens.](/docs/getting-started/for-users/get-tokens) - -## Facing a problem with configuring MetaMask? -When using a dApp on TEN, start by checking its documentation and resources. If that doesn't help, consult the TEN docs' [troubleshooting](/docs/category/troubleshooting) section or seek assistance on the TEN [Discord](http://discord.gg/yQfmKeNzNd). If the issue appears to be with MetaMask, head to MetaMask's [Help Center](https://support.metamask.io/hc/en-us) to browse their forums or engage with their Support team. - -## Other wallets - -TEN currently supports MetaMask and will soon extend compatibility to all EVM-based wallets. diff --git a/docs/testnet/for-validators/node-architecture.md b/docs/getting-started/for-validators/node-architecture.md similarity index 100% rename from docs/testnet/for-validators/node-architecture.md rename to docs/getting-started/for-validators/node-architecture.md diff --git a/docs/testnet/for-validators/overview.md b/docs/getting-started/for-validators/overview.md similarity index 100% rename from docs/testnet/for-validators/overview.md rename to docs/getting-started/for-validators/overview.md diff --git a/docs/testnet/for-validators/rewards.md b/docs/getting-started/for-validators/rewards.md similarity index 100% rename from docs/testnet/for-validators/rewards.md rename to docs/getting-started/for-validators/rewards.md diff --git a/docs/getting-started/for-validators/running-a-node.md b/docs/getting-started/for-validators/running-a-node.md index 21bf8295..61a4aaf2 100644 --- a/docs/getting-started/for-validators/running-a-node.md +++ b/docs/getting-started/for-validators/running-a-node.md @@ -1,12 +1,93 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- -# Running a node +# Running a TEN Validator Node on Azure -Thank you for your interest in running a node on TEN! +This guide provides detailed instructions to set up and manage a TEN Validator Node on Azure using Terraform and Ansible. Due to TEN’s use of SGX architecture and cloud-specific security assurances, all current deployments are limited to cloud infrastructure to mitigate risks associated with physical attacks. A proof-of-cloud assertion, provided by TEN, certifies the security and reliability of each validator node running in the cloud. -Currently, the capability to run individual nodes is not available publicly. However, we're actively working on this feature and will be launching it soon. +--- + +## Overview + +The deployment process leverages **Terraform** for Azure infrastructure provisioning and **Ansible** for configuring the Validator Node. By following this guide, you’ll set up a secure, compliant environment that meets TEN’s standards for validator operations. + +- **Terraform**: Automates the creation of Azure resources for a TEN Validator Node. +- **Ansible**: Configures and deploys node software on the provisioned infrastructure. + +--- + +## Requirements + +Before starting, ensure the following dependencies are installed on your local machine: + +- [**Terraform**](https://www.terraform.io/downloads.html) (version >= 0.12) + - [Terraform Installation Guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) +- [**Ansible**](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) + - [Ansible Installation guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) + - **Required Ansible Collections**: Install with: + ```sh + ansible-galaxy collection install community.docker community.crypto + ``` +- [**Azure CLI**](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli): For authenticating and managing Azure resources. +- [**Docker**](https://docs.docker.com/get-docker/): Required for node deployment. +- [**Docker Compose**](https://docs.docker.com/compose/install/): Used for managing containerized services. +- [**Git**](https://git-scm.com/downloads): For repository cloning and version control. + +--- +## Clone the TEN Validator Repository +``` +git clone https://github.com/ten-protocol/ten-validator.git +cd ten-validator +``` +## Azure Setup Instructions (Terraform) + +### Step 1: Authenticate and Configure Azure + +1. **Log into Azure**: + ```sh + az login +2. Set Your Azure Subscription: Specify the Azure subscription for deploying the resources: + ```sh + az account set --subscription + ``` + +### Step 2: Configure Terraform Variables (optional) +``` +cp terraform.tfvars.example terraform.tfvars +``` + +### Step 3: Deploy the Terraform Script +``` +terraform init +terraform apply +``` + +### Step 4: Access the Validator Node (Optional) +1. ```chmod +x get-key.sh ./get-key.sh``` +2. ```ssh -i @``` + +## TEN Validator Setup Instructions (Ansible) +1. Network Configuration: Node network settings are located in `ansible/files/network_vars.yml`. These settings are typically not changed and are specific to the L2 network. One will be provided by the TEN team for ITN (testnet) and another for mainnet. +2. Run the Installation Script: Use Ansible to configure and deploy the TEN Validator Node: + ``` + chmod +x install-ten.sh + ./install-ten.sh + ``` + During deployment, you will be prompted to enter: + + - Host ID: Public key of the validator node wallet + + - Private Key: Private key of the validator node wallet + + - Host Public P2P Address: Public IP or DNS of the node + + - SSH Details: Username and key path (or password if applicable) + + - L1 WS URL: WebSocket URL for the Layer 1 node (e.g., Infura) + + - Postgres DB Host: Leave blank to provision a new database -If you are interested in running a TEN validator - use [the form on Coinlist](https://coinlist.co/ten-testnet) to submit your application. + Note: If Terraform provisioned the VM, default values are often applicable—just press Enter to accept. -The deadline to apply is set for 1 March 2024. +## Managing the Validator Node +Coming soon! (monitoring, backups, tear down, etc.) diff --git a/docs/introduction/developer-quickstart.md b/docs/introduction/developer-quickstart.md index cdb0ec4e..c432bd84 100644 --- a/docs/introduction/developer-quickstart.md +++ b/docs/introduction/developer-quickstart.md @@ -6,7 +6,7 @@ sidebar_position: 4 Migrating to TEN enables your dApp to leverage "Programmable Encryption". Below are steps to help you transition smoothly. -### Key Migration Steps +## Key Migration Steps - Update your Hardhat deployment to support the `--network ten` option. - Add data protection logic to your view functions (if applicable). @@ -29,7 +29,7 @@ _You can use `npm` or `yarn` to install plugins._ ### 1.2 Configuring `hardhat.config.js` -Modify `hardhat.config.js` in your project’s root directory as follows: +Modify `hardhat.config.js` in your project's root directory as follows: ```javascript import { HardhatUserConfig } from "hardhat/config"; @@ -55,7 +55,7 @@ export default config; Once configured, you can start writing or migrating your smart contracts. -## 2. Writing Smart Contracts for TEN +## 2. Understanding TEN Contract Development TEN executes smart contracts within the EVM similarly to Ethereum, so you can reuse your existing code. However, the execution and the internal state are hidden from everyone, including node operators and the sequencer. @@ -64,401 +64,31 @@ However, the execution and the internal state are hidden from everyone, includin TEN encrypts both the execution and its internal database using Trusted Execution Environments (TEEs). ::: -The [getStorageAt](https://docs.alchemy.com/reference/eth-getstorageat) method is disabled by default on TEN, so data access relies on view functions that you define. -Public variables remain accessible as Solidity automatically creates getters for them. +For detailed guidance on writing smart contracts for TEN, including: +- Data access control patterns +- Event visibility configuration +- Privacy-preserving contract design -Let's illustrate with a basic storage dApp example where users can store and retrieve a number. +See the comprehensive guide: [Smart Contracts](/docs/getting-started/for-developers/explore-contracts-in-ten/) -At every step, we'll add a new feature and explain the difference between `TEN` and `Ethereum`. +## 3. Advanced TEN Features -### Step 1: Basic contract with a Public Variable +### Session Keys for Smooth UX +TEN supports native session keys for seamless user experiences without requiring transaction signing for every action. This is particularly useful for games and interactive dApps. -#### Code +Learn more: [Session Keys](/docs/standards-primitives/session-keys) -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +### Secure Game Development +Building secure on-chain games requires special considerations for randomness and preventing exploits. TEN provides unique solutions for these challenges. -contract StorageExample { - mapping(address => uint256) public storedValues; +Learn more: [Game Security](/docs/getting-started/for-developers/game-security) - function storeValue(uint256 value) public { - storedValues[tx.origin] = value; - } -} -``` - -#### Explanation - -In this step, we created a public variable `storedValues` that maps the provided value to the address of the user who called the `storeValue` function. - -Because the variable is public, Solidity will provide a default public getter for it. - -Since there are no data access restrictions, on both Ethereum and TEN, everyone will be able to read the values of all users. - -### Step 2: Converting to a Private Variable with an explicit Getter Function - -#### Code - -```solidity -contract StorageExample { - mapping(address => uint256) private _storedValues; - - function storeValue(uint256 value) public { - _storedValues[tx.origin] = value; - } - - function getValue(address account) public view returns (uint256) { - return _storedValues[account]; - } -} -``` - -#### Explanation - -The `storedValues` variable is now private, and we added a basic `getValue` function for users to retrieve their value. - -On both Ethereum and TEN, anyone can call `getValue` to retrieve any value. -On Ethereum, `_storedValues` can also be accessed directly with `getStorageAt` - -### Step 3: Data Access Control - -In this step, we'll add restrictions so users can only access their own data. - -#### Code - -```solidity -contract StorageExample { - mapping(address => uint256) private _storedValues; - - function storeValue(uint256 value) public { - _storedValues[tx.origin] = value; - } - - function getValue(address account) public view returns (uint256) { - require(tx.origin == account, "Not authorized!"); - return _storedValues[account]; - } -} -``` - -#### Explanation - -The key line is: ``require(tx.origin == account, "Not authorized!");``, which ensures that the caller of the view function is the owner of the data. - -:::info -TEN uses "Viewing Keys" to authenticate view function calls. -::: - -**When deployed on TEN, this code guarantees that all users can only access their own values, and nobody can read the `_storedValues`.** - -### Step 4: Emitting Events - Default Visibility - -Event logs notify UIs about state changes in smart contracts. - -To improve our smart contract, we’ll emit an event when a user stores a value and milestone events when a specific size threshold is met. - -#### Code - -```solidity -contract StorageExample { - mapping(address => uint256) private _storedValues; - uint256 private totalCalls = 0; - - event DataChanged(address indexed account, uint256 newValue); - event MilestoneReached(uint256 noStoredValues); - - function storeValue(uint256 value) public { - _storedValues[tx.origin] = value; - emit DataChanged(tx.origin, value); - totalCalls++; - if (totalCalls % 1000 == 0) { - emit MilestoneReached(totalCalls); - } - } - - function getValue(address account) public view returns (uint256) { - require(tx.origin == account, "Not authorized!"); - return _storedValues[account]; - } -} -``` - -#### Explanation - -Notice how we defined the two events: `DataChanged` and `MilestoneReached`, and are emitting them in the `storeValue` function. - -In Ethereum, everyone can query and subscribe to these events. This obviously can't be the case for TEN because it would completely break the functionality. - -Notice how in this version, we have no configuration for event log visibility, so we are relying on the default rules. - -Rule 1: Event logs that contain EOAs as indexed fields (topics) are only visible to those EOAs. -Rule 2: Event logs that don't contain any EOA are visible to everyone. - -In our case, the default rules ensure that: -- `DataChanged` is visible only to the address that is storing the value. -- `MilestoneReached` is publicly visible. - - -### Step 5: Customizing Event Visibility - -The default visibility rules are a good starting point, but complex dApps require greater flexibility. - -TEN give you explicit control over event visibility. - -#### Code - -```solidity -interface ContractTransparencyConfig { - enum Field { TOPIC1, TOPIC2, TOPIC3, SENDER, EVERYONE } - enum ContractCfg { TRANSPARENT, PRIVATE } - - struct EventLogConfig { - bytes32 eventSignature; - Field[] visibleTo; - } - - struct VisibilityConfig { - ContractCfg contractCfg; - EventLogConfig[] eventLogConfigs; - } - - function visibilityRules() external pure returns (VisibilityConfig memory); -} - -contract StorageExample is ContractTransparencyConfig { - mapping(address => uint256) private _storedValues; - uint256 private totalCalls = 0; - - event DataChanged(address indexed account, uint256 newValue); - event MilestoneReached(uint256 noStoredValues); - - function storeValue(uint256 value) public { - _storedValues[tx.origin] = value; - emit DataChanged(tx.origin, value); - totalCalls++; - if (totalCalls % 1000 == 0) { - emit MilestoneReached(totalCalls); - } - } - - function getValue(address account) public view returns (uint256) { - require(tx.origin == account, "Not authorized!"); - return _storedValues[account]; - } - - function visibilityRules() external pure override returns (VisibilityConfig memory) { - EventLogConfig[] memory eventLogConfigs = new EventLogConfig[](2); - - // the signature of "event DataChanged(address indexed account, uint256 newValue);" - bytes32 dataChangedEventSig = hex"0xec851d5c322f7f1dd5581f7432e9f6683a8709a4b1ca754ccb164742b82a7d2f"; - Field[] memory relevantTo = new Field[](2); - relevantTo[0] = Field.TOPIC1; - relevantTo[1] = Field.SENDER; - eventLogConfigs[0] = EventLogConfig(dataChangedEventSig, relevantTo); - - // the signature of "event MilestoneReached(uint256 noStoredValues);" - bytes32 milestoneReachedEventSig = hex"0xd41033274424d56dd572e7196fb4230cf4141d546b91fc00555cab8403965924"; - Field[] memory relevantTo = new Field[](1); - relevantTo[0] = Field.EVERYONE; - eventLogConfigs[1] = EventLogConfig(milestoneReachedEventSig, relevantTo); - - return VisibilityConfig(ContractCfg.PRIVATE, eventLogConfigs); - } -} -``` - -#### Explanation - -The `ContractTransparencyConfig` interface is known by the TEN platform. -When a contract is deployed, the platform will call the `visibilityRules` function, and store the `VisibilityConfig`. - -For each event type, you can configure which fields can access it. -This allows the developer to configure an event to be public even if it has EOAs or to allow the sender of the transaction to access events emitted even if the address is not in the event. - -Notice how in the `visibilityRules` above, we configure the `DataChanged` event to be visible to the first field and the sender, and the `MilestoneReached` to be visible to everyone. - -The other configuration: `VisibilityConfig.contractCfg` applies to the entire contract: -- `ContractCfg.TRANSPARENT`: The contracts will have public storage and events, behaving exactly like Ethereum. -- `ContractCfg.PRIVATE`: The default TEN behaviour, where the storage is not accessible and the events are individually configurable. - - -## Account Abstraction - Native Session Keys - -The key feature of ["Account Abstraction"](https://medium.com/p/2e85bde4c54d) (EIP-4337) is "Session keys"(SK) through a proxy smart contract. -SKs allow users to interact with the blockchain without having to sign every transaction, which is a major UX improvement. - -TEN supports "native" SKs - these are managed by the platform and do not require a proxy contract. - -In TEN, SKs are managed by dApp developers through dedicated RPC endpoints. - -### Solution overview - -Imagine you're developing an on-chain game, and you want a smooth UX without the distraction of signing every move. - -Conceptually, the game will create a session key (SK) for the user, then ask the user to move some funds to that address, and then create "move" transactions signed with the SK. - -If the game were to create the SK in the browser, there would be a risk of the user losing the SK, and the funds associated with it, in case of an accidental exit. -With TEN, the dApp developer doesn't have to worry about this, because the SKs are managed by TEEs. - -### Usage - -The below describe the implementation steps for the game developer - which is the main usecase for SKs. -Note that it can be used for any dApp that requires a no-click UX. - -#### When the game starts - -Before the user can start playing, the game must create the SK and ask the user to move some funds to that address. -The funds will be used to pay for moves. - -- Call the RPC ``sessionkeys_Create`` - without any parameters. This will return a hex-encoded address of the SK. -- Create a normal transaction that transfers some ETH to the SK. The amount depends on how many "moves" the user is prepared to prepay for. -- Ask the user to sign this transaction with their normal wallet, and submit it to the network using the library of your choice. -- Once the receipt is received, call ``sessionkeys_Activate``. - -#### The game - -After activation of the SK, create a transaction for each move, but don't ask the user to sign them. -Instead, submit them to the network unsigned using the RPCs: ``eth_sendRawTransaction`` or ``eth_sendTransaction``. - -Because the SK is active, the platform will sign the transactions on behalf of the user. - -As a game developer, you are responsible to keep track of the balance of the SK. You can also query the network for the balance of the address. -If the SK runs out of balance, you have to ask the user to move more funds to the SK. - - -#### Managing Session Keys - -TEN provides additional RPC endpoints for managing session keys: - -- `sessionkeys_Delete` - Permanently removes the session key. This can only be called after deactivating the key. This is useful when you want to clean up unused session keys or when a user wants to completely remove their session key. - -- `sessionkeys_List` - Returns the address of the current session key, or an empty response if no session key exists. This is useful for checking if a user has an active session key and getting its address. - - -The session key management endpoints can be called through both HTTP API and RPC methods. For RPC, you can use `eth_getStorageAt` with specific addresses: - -- Create: `0x0000000000000000000000000000000000000003` -- Activate: `0x0000000000000000000000000000000000000004` -- Deactivate: `0x0000000000000000000000000000000000000005` -- Delete: `0x0000000000000000000000000000000000000006` -- List: `0x0000000000000000000000000000000000000007` - - - -#### Finishing the game - -When a game ends, you have to move the remaining funds back to the main address and deactivate the key. - -- create a Tx that moves the funds back from the SK to the main address. Submit it unsigned, because the funds are controlled by the SK. -- call the RPC: ``sessionkeys_Deactivate``- from now on, unsigned transactions will no longer be signed by the SK. - - -## Game Security - -Every on-chain game developer knows that every move that relies on entropy must be executed in two steps. - -Imagine you implement an on-chain coin flip game. The player pays 0.1ETH to choose `Heads` or `Tails`. -If they win, they receive 0.2ETH, otherwise they lose the 0.1ETH. -Even if randomness is unpredictable, this simple game can be exploited in several ways: - -- The attacker can create a “proxy” smart contract to play on their behalf. Using a similar mechanism to flash loans in DeFi: the proxy is programmed to make multiple actions, and only “commit” if it can obtain a profit. In our case, if the coin flip is losing, the proxy can just revert. The only cost will be the gas burned. -- Transactions consume gas, and the gas cost can inadvertently reveal information. For instance, if a winning move is more computationally intensive than a losing one, players could deduce optimal moves by estimating gas costs for various actions. - -The typical solution is to use a commit-reveal scheme. The player commits to a move, and then reveals it. This way, the player can't change their mind after seeing the result. -This solution has the major drawback that it introduces extra complexity, latency and cost. - -### The on-block-end callback - -The best solution is to decouple the move from the execution without increasing the latency or the cost. -This way, the side-channel attacks are no longer possible because the move is not executed immediately. -To avoid increasing the latency, the move must be executed at the end of the block. -Note that contracts can define the handleRefund function, which will be called with value equal to what is left from the gas processing paid for. -This is called with enough gas to save locally how much should be refunded to whoever paid for the callback. - -See below a simple implementation of the coin flip game using the TEN platform: - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// this interface is known by the TEN system contract -interface TenCallbacks { - function register(bytes calldata) external payable returns (uint256); -} - -interface Refunds { - function handleRefund(uint256 callbackId) external payable; -} - -contract CoinFlip { - // Event to emit the result of the coin flip - event CoinFlipResult(address indexed player, bool didWin, uint256 randomNumber); - - private TenCallbacks tenCallbacks; - mapping(uint256 callbackId => address player) public callbackToPlayer; - mapping(address player => uint256 refundAmount) public playerToRefundAmount; - - - - modifier onlyTenSystemCall() { - require(msg.sender == address(tenCallbacks)); - _; - } - - // you have to pass in the address of the callbacks contract - constructor(address _tenCallbacksAddress) { - tenCallbacks = TenCallbacks(_tenCallbacksAddress); - } - - // Function to initiate a coin flip. - // Notice how it doesn't execute the coin flip directly, but instead registers a callback. - function flipCoin(bool isHeads) external payable { - // Assume doFlipCoin costs 50_000 gas; - // We deduct a predetermined amount from the bet to pay for delayed execution. - uint256 etherGasForCoinFlip = 50_000*block.basefee; - require(msg.value > etherGasForCoinFlip, "Insufficent gas"); - - // Encode the function we want to be called by the TEN system contract. - bytes memory callbackTargetInfo = abi.encodeWithSelector(this.doFlipCoin.selector, msg.sender, msg.value - etherGasForCoinFlip, isHeads); - - tenCallbacks.register{value: etherGasForCoinFlip}(callbackTargetInfo); - } - - // Function to simulate a coin flip - notice that this must only be callable by the ten system contract. - // This function is called by the TEN platform as a synthetic transaction in the same block as the user transaction. - function doFlipCoin(address bettor, uint256 stake, bool wantsHeads) external onlyTenSystemCall { - // Assume getRandomNumber() is a function that returns a random number - uint256 randomNumber = getRandomNumber(); - - // Simulate a coin flip: 0 for tails, 1 for heads - bool isHeads = (randomNumber % 2) == 1; - - if (wantsHeads == isHeads) { - //pay out to winner - (bool success, ) = payable(bettor).call{value: stake*2}(""); - require(success, "Payment failed."); - } - // Emit the result of the coin flip - emit CoinFlipResult(msg.sender, isHeads, randomNumber); - } - - function getRandomNumber() internal view returns (uint256) { - return block.prevrandao; - } - - function handleRefund(uint256 callbackId) external payable { - address player = callbackToPlayer[callbackId]; - playerToRefundAmount[player] += msg.value; - } +## 4. Migration Checklist - function claimRefund() external { - uint256 refundAmount = playerToRefundAmount[msg.sender]; - require(refundAmount > 0, "No refunds to claim"); - playerToRefundAmount[msg.sender] = 0; - (bool success, ) = payable(msg.sender).call{value: refundAmount}(""); - require(success, "Transfer failed"); - } - -} -``` \ No newline at end of file +- [ ] Install and configure the TEN Hardhat plugin +- [ ] Update your contracts to use TEN's privacy features +- [ ] Configure event visibility rules (if needed) +- [ ] Test your contracts on TEN testnet +- [ ] Implement session keys (if applicable) +- [ ] Add TEN Gateway integration to your frontend +- [ ] Deploy and verify your contracts \ No newline at end of file diff --git a/docs/introduction/overview.md b/docs/introduction/overview.md index bfd5b1a6..9bb68e4f 100644 --- a/docs/introduction/overview.md +++ b/docs/introduction/overview.md @@ -3,8 +3,6 @@ sidebar_position: 1 --- # Overview -![TEN in Web3](../assets/overview-banner.png) - _The full Litepaper is available to view [here](https://ten.xyz/litepaper)._ TEN is revolutionizing Ethereum with encrypted layer 2 solution. Just as HTTPS transformed Web 2.0, ushering in a new era of secure applications and enhanced user trust, TEN is set to redefine the Ethereum ecosystem. By introducing an encrypted Ethereum Layer 2, TEN not only amplifies transaction speed and efficiency but also fortifies it with the robust security and consensus mechanisms inherent to Ethereum. diff --git a/docs/standards-primitives/session-keys.md b/docs/standards-primitives/session-keys.md new file mode 100644 index 00000000..2a40d5b1 --- /dev/null +++ b/docs/standards-primitives/session-keys.md @@ -0,0 +1,71 @@ +--- +sidebar_position: 3 +--- + +# Session Keys + +The key feature of ["Account Abstraction"](https://medium.com/p/2e85bde4c54d) (EIP-4337) is "Session keys"(SK) through a proxy smart contract. +SKs allow users to interact with the blockchain without having to sign every transaction, which is a major UX improvement. + +TEN supports "native" SKs - these are managed by the platform and do not require a proxy contract. + +In TEN, SKs are managed by dApp developers through dedicated RPC endpoints. + +## Solution overview + +Imagine you're developing an on-chain game, and you want a smooth UX without the distraction of signing every move. + +Conceptually, the game will create a session key (SK) for the user, then ask the user to move some funds to that address, and then create "move" transactions signed with the SK. + +If the game were to create the SK in the browser, there would be a risk of the user losing the SK, and the funds associated with it, in case of an accidental exit. +With TEN, the dApp developer doesn't have to worry about this, because the SKs are managed by TEEs. + +## Usage + +The below describe the implementation steps for the game developer - which is the main usecase for SKs. +Note that it can be used for any dApp that requires a no-click UX. + +### When the game starts + +Before the user can start playing, the game must create the SK and ask the user to move some funds to that address. +The funds will be used to pay for moves. + +- Call the RPC ``sessionkeys_Create`` - without any parameters. This will return a hex-encoded address of the SK. +- Create a normal transaction that transfers some ETH to the SK. The amount depends on how many "moves" the user is prepared to prepay for. +- Ask the user to sign this transaction with their normal wallet, and submit it to the network using the library of your choice. +- Once the receipt is received, call ``sessionkeys_Activate``. + +### The game + +After activation of the SK, create a transaction for each move, but don't ask the user to sign them. +Instead, submit them to the network unsigned using the RPCs: ``eth_sendRawTransaction`` or ``eth_sendTransaction``. + +Because the SK is active, the platform will sign the transactions on behalf of the user. + +As a game developer, you are responsible to keep track of the balance of the SK. You can also query the network for the balance of the address. +If the SK runs out of balance, you have to ask the user to move more funds to the SK. + + +### Managing Session Keys + +TEN provides additional RPC endpoints for managing session keys: + +- `sessionkeys_Delete` - Permanently removes the session key. This can only be called after deactivating the key. This is useful when you want to clean up unused session keys or when a user wants to completely remove their session key. + +- `sessionkeys_List` - Returns the address of the current session key, or an empty response if no session key exists. This is useful for checking if a user has an active session key and getting its address. + + +The session key management endpoints can be called through both HTTP API and RPC methods. For RPC, you can use `eth_getStorageAt` with specific addresses: + +- Create: `0x0000000000000000000000000000000000000003` +- Activate: `0x0000000000000000000000000000000000000004` +- Deactivate: `0x0000000000000000000000000000000000000005` +- Delete: `0x0000000000000000000000000000000000000006` +- List: `0x0000000000000000000000000000000000000007` + +### Finishing the game + +When a game ends, you have to move the remaining funds back to the main address and deactivate the key. + +- create a Tx that moves the funds back from the SK to the main address. Submit it unsigned, because the funds are controlled by the SK. +- call the RPC: ``sessionkeys_Deactivate``- from now on, unsigned transactions will no longer be signed by the SK. \ No newline at end of file diff --git a/docs/testnet/for-developers/_category_.json b/docs/testnet/for-developers/_category_.json deleted file mode 100644 index 4137740d..00000000 --- a/docs/testnet/for-developers/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "For Developers", - "position": 2, - "link": { - "type": "generated-index" - } -} diff --git a/docs/testnet/for-validators/_category_.json b/docs/testnet/for-validators/_category_.json deleted file mode 100644 index 12050991..00000000 --- a/docs/testnet/for-validators/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "For Validators", - "position": 3, - "link": { - "type": "generated-index" - } -} diff --git a/docs/testnet/for-validators/running-a-node.md b/docs/testnet/for-validators/running-a-node.md deleted file mode 100644 index 61a4aaf2..00000000 --- a/docs/testnet/for-validators/running-a-node.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -sidebar_position: 4 ---- -# Running a TEN Validator Node on Azure - -This guide provides detailed instructions to set up and manage a TEN Validator Node on Azure using Terraform and Ansible. Due to TEN’s use of SGX architecture and cloud-specific security assurances, all current deployments are limited to cloud infrastructure to mitigate risks associated with physical attacks. A proof-of-cloud assertion, provided by TEN, certifies the security and reliability of each validator node running in the cloud. - ---- - -## Overview - -The deployment process leverages **Terraform** for Azure infrastructure provisioning and **Ansible** for configuring the Validator Node. By following this guide, you’ll set up a secure, compliant environment that meets TEN’s standards for validator operations. - -- **Terraform**: Automates the creation of Azure resources for a TEN Validator Node. -- **Ansible**: Configures and deploys node software on the provisioned infrastructure. - ---- - -## Requirements - -Before starting, ensure the following dependencies are installed on your local machine: - -- [**Terraform**](https://www.terraform.io/downloads.html) (version >= 0.12) - - [Terraform Installation Guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) -- [**Ansible**](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) - - [Ansible Installation guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html) - - **Required Ansible Collections**: Install with: - ```sh - ansible-galaxy collection install community.docker community.crypto - ``` -- [**Azure CLI**](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli): For authenticating and managing Azure resources. -- [**Docker**](https://docs.docker.com/get-docker/): Required for node deployment. -- [**Docker Compose**](https://docs.docker.com/compose/install/): Used for managing containerized services. -- [**Git**](https://git-scm.com/downloads): For repository cloning and version control. - ---- -## Clone the TEN Validator Repository -``` -git clone https://github.com/ten-protocol/ten-validator.git -cd ten-validator -``` -## Azure Setup Instructions (Terraform) - -### Step 1: Authenticate and Configure Azure - -1. **Log into Azure**: - ```sh - az login -2. Set Your Azure Subscription: Specify the Azure subscription for deploying the resources: - ```sh - az account set --subscription - ``` - -### Step 2: Configure Terraform Variables (optional) -``` -cp terraform.tfvars.example terraform.tfvars -``` - -### Step 3: Deploy the Terraform Script -``` -terraform init -terraform apply -``` - -### Step 4: Access the Validator Node (Optional) -1. ```chmod +x get-key.sh ./get-key.sh``` -2. ```ssh -i @``` - -## TEN Validator Setup Instructions (Ansible) -1. Network Configuration: Node network settings are located in `ansible/files/network_vars.yml`. These settings are typically not changed and are specific to the L2 network. One will be provided by the TEN team for ITN (testnet) and another for mainnet. -2. Run the Installation Script: Use Ansible to configure and deploy the TEN Validator Node: - ``` - chmod +x install-ten.sh - ./install-ten.sh - ``` - During deployment, you will be prompted to enter: - - - Host ID: Public key of the validator node wallet - - - Private Key: Private key of the validator node wallet - - - Host Public P2P Address: Public IP or DNS of the node - - - SSH Details: Username and key path (or password if applicable) - - - L1 WS URL: WebSocket URL for the Layer 1 node (e.g., Infura) - - - Postgres DB Host: Leave blank to provision a new database - - Note: If Terraform provisioned the VM, default values are often applicable—just press Enter to accept. - -## Managing the Validator Node -Coming soon! (monitoring, backups, tear down, etc.) diff --git a/docs/troubleshooting/faq.md b/docs/troubleshooting/faq.md index f38c07b4..b145e5d2 100644 --- a/docs/troubleshooting/faq.md +++ b/docs/troubleshooting/faq.md @@ -13,7 +13,7 @@ Keep in mind that you will not be able to query data on accounts that have not b ### How can I port my dApp from other networks to TEN? You need to follow the following steps: -1. Change the functions of your smart contracts according to the instructions given [here](/docs/getting-started/for-developers/explore-contracts-in-ten). +1. Change the functions of your smart contracts according to the instructions given [here](/docs/getting-started/for-developers/explore-contracts-in-ten/). 2. Integrate TEN Gateway into your dApp. 3. Deploy your SCs into TEN using [compatible tools](/docs/tools-infrastructure/compatible-tools) (e.g. Truffle Suite). 4. Invite your users to learn more about encryption!