From ec983a4e5d327403edefa191d49ae0a53460ccd7 Mon Sep 17 00:00:00 2001 From: Oxydixi Date: Fri, 1 Dec 2023 09:58:52 +0300 Subject: [PATCH 1/4] added ERC20 --- docs/integrations/contracts.md | 193 +++++++++++++++++-------- docs/integrations/l2.md | 231 +++++++----------------------- docs/static/checker.abi.json | 250 +++++++++++++++++++++++++++++++++ 3 files changed, 439 insertions(+), 235 deletions(-) create mode 100644 docs/static/checker.abi.json diff --git a/docs/integrations/contracts.md b/docs/integrations/contracts.md index fde9961..2660cda 100644 --- a/docs/integrations/contracts.md +++ b/docs/integrations/contracts.md @@ -13,12 +13,14 @@ { .ml-params } -[**getAccess**](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.sol#L353)() returns(mapping(uint256 => uint8)) + +**getAccess**() returns(mapping(uint256 => uint8)) + RETURNS: the list of all the user's public keys with their numbers. -It is necessary to take the zeroth pubkey from the list +It is necessary **to take the zeroth pubkey** from the list { .ml-params } + + **getProfileAddr**(string name) returns(address) @@ -92,10 +96,7 @@ the address of the user's **Profile** contract 0x54a858bBD5968Eb755e54C45a3fe5B002bE3c254 ``` - - - **deposit**(uint256 pubkey) @@ -111,10 +112,32 @@ user's token wallet for minting wrapped tokens to it. { .ml-params } -**depositERC20**(address token, uint256 value, uint256 pubkey) +!!! exsample annotate "example of calling the ELock contract in Ethereum" + + ``` cpp + const elock = new data.web3.instance.eth.Contract( + ELockAbi.abi, + AppConfig.elockaddr, + ) + + const edata = elock.methods.deposit(data.summary.to.user.value.pubkey).encodeABI() + + const receipt = await data.web3.instance.eth.sendTransaction({ + from: data.web3.address, + to: AppConfig.elockaddr, + value: data.web3.instance.utils.toWei(data.summary.from.amount, 'ether'), + data: edata, + gasLimit: 100000, + maxPriorityFeePerGas: 25000, + }) + ``` + + -Allows a user to deposit ERC20 tokens into the Elock-contract for locking in it. The corresponding -amount of wrapped tokens in GOSH will be minted for the amount of the blocked funds. +**depositERC20**(address token, uint256 value, uint256 pubkey) + +***Allows a user to deposit ERC20 tokens into the Elock-contract for locking in it. The corresponding +amount of wrapped tokens in GOSH will be minted for the amount of the blocked funds.*** Before calling deposit, the specified number of tokens must be available for transfer for the Elock address. { .ml-params } @@ -122,83 +145,135 @@ address. PARAMETERS: -**token** (*address*) - address of the ERC20 token contract. -**value** (*uint256*) - deposited number of tokens. -**pubkey** (*uint256*) - the recipient's public key in GOSH. Used to derive the address of the +* **`token`** (*address*) - address of the ERC20 token contract. +* **`value`** (*uint256*) - deposited number of tokens. +* **`pubkey`** (*uint256*) - the recipient's public key in GOSH. Used to derive the address of the user's token wallet for minting wrapped tokens to it. { .ml-params } -**getERC20Approvement**(address token, address recipient) returns (uint value, uint commission) -For the specified token and recipient, it returns the number of tokens available for withdrawal -(withdrawERC20) and the commission to be transferred for the withdrawal function. + + + + +**withdrawERC20**(address token) + +***Requests the withdrawal of the specified tokens for the caller (`msg.sender`).*** +Tokens must be approved for withdrawal. The commission must be attached to the function call. { .ml-params } PARAMETERS: -**token** (*address*) - address of the ERC20 token contract. -**recipient** (*address*) - the address of the recipient of the withdrawed tokens +* **`token`** (*address*) - address of the ERC20 token contract. { .ml-params } -RETURNS: -**value** (*uint256*) - the number of tokens approved for withdrawal. -**commission** (*uint256*) - the amount of commission for withdrawal. -{ .ml-params } +**getERC20Approvement**(address token, address recipient) returns (uint value, uint commission) +***For the specified token and recipient, it returns the number of tokens available for withdrawal +(withdrawERC20) and the commission to be transferred for the withdrawal function.*** +{ .ml-params } -**withdrawERC20**(address token) +PARAMETERS: -Requests the withdrawal of the specified tokens for the caller (`msg.sender`). Tokens must be -approved for withdrawal. The commission must be attached to the function call. +* **`token`** (*address*) - address of the ERC20 token contract. +* **`recipient`** (*address*) - the address of the recipient of the withdrawed tokens { .ml-params } -PARAMETERS: -**token** (*address*) - address of the ERC20 token contract. +RETURNS: + +**value** (*uint256*) - the number of tokens approved for withdrawal. +**commission** (*uint256*) - the amount of commission for withdrawal. { .ml-params } -**getTokenRoots**() -This function returns an array of addresses where each address represents a supported ERC 20 token in GOSH Ethereum L2. + + + +**getTokenRoots**() returns (address[] memory roots) + +The function returns an array of addresses where each address represents a supported ERC20 token in GOSH Ethereum L2. RETURNS: **roots** (*address[]*) - list of addresses of ERС20 tokens +{ .ml-params } + + + + - - +[[ABI]](../static/checker.abi.json){:download="checker.abi.json"} +{ .ml-params } + +!!! info + **address in GOSH:** + + ``` + 0:17eb654c5fca0027d47a4564139df71bec46b2277d71f6674ecd9dc55e52fb78 + ``` + + +**getRootAddr**(RootData data) returns(address) + +The function returns TIP-3 root contract address + PARAMETERS + +* **`RootData.name`** (*string*) - ERC20 token name; +* **`RootData.symbol`** (*string*) - ERC20 token symbol; +* **`RootData.decimals`** (*uint8*) - ERC20 token decimals; +* **`RootData.ethroot`** (*uint256*)- ERC20 token address; +{ .ml-params } + + RETURNS -RETURN TYPE -### **Proposal.sol** +address TIP-3 root for wrapped ERС20 token in GOSH +{ .ml-params } - - +RETURN TYPE --> + + -## **RootTokenContract** + + +## **RootTokenContract** **is a smart contract on GOSH that manages user withdrawals. It receives TIP-3 transactions, verifies them and adds transactions to the counter index.** **Also it deploys the TIP-3 wallet contract (`TONTokenWallet.cpp`) and sends wrapped tokens there.** @@ -216,9 +291,10 @@ RETURN TYPE --> ``` + **getWalletAddress**(uint256 pubkey, address_opt owner) -The function for getting the user's TIP-3 wallet address +***The function for getting the user's TIP-3 wallet address*** { .ml-params } @@ -255,9 +331,9 @@ user's wallet address bool deploy, uint128 return_ownership, opt notify_payload -) +) -The function for deploying empty TIP-3 wallet to another user +***The function for deploying empty TIP-3 wallet to another user*** PARAMETERS: @@ -276,6 +352,8 @@ RETURN TYPE --> + + **transfer**( address_opt answer_addr, address to, @@ -285,6 +363,7 @@ RETURN TYPE --> opt notify_payload ) +***The function transfers the TIP3-tokens between TIP-3 user wallets.*** PARAMETERS: @@ -299,33 +378,32 @@ PARAMETERS: +**burnTokens**(uint128 tokens, uint256 to) +***The function burns tokens for transfer to Ethereum*** +{ .ml-params } + +PARAMETERS: -For transfer "WETH" to Ethereum, you need to call the `burnTokens` method in the user contract **TONTokenWallet** - -``` cpp -void burnTokens(uint128 tokens, uint256 to) -``` +* **`tokens`** - amount WETH, which will be transferred to Ethereum +* **`to`** - the address of the recipient's wallet in Ethereum +{ .ml-params } -where: -`tokens` - amount WETH, which will be transferred to Ethereum -`to` - the address of the recipient's wallet in Ethereum -{ .ml-params } -Then wait for the transfer of `ETH` to the recipient's wallet in Ethereum. +**getDetails**() +***The function returns information about the TIP-3 wallet*** +{ .ml-params } -For get information about the TIP-3 wallet in the contract **TONTokenWallet**, the `getDetails` method is called: +RETURNS: -``` -details_info getDetails() -``` +the data structure: +{ .ml-params } -and you get the data structure: ``` struct details_info { @@ -348,6 +426,9 @@ struct details_info { int8 workchain_id; // Workchain id. } ``` + + + diff --git a/docs/integrations/l2.md b/docs/integrations/l2.md index e880609..7e88db4 100644 --- a/docs/integrations/l2.md +++ b/docs/integrations/l2.md @@ -11,37 +11,13 @@ network main: https://network.gosh.sh To explore the GOSH blockchain, you can use the [GOSH explorer](https://gosh.live) -The contract [**Profile**](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.sol) (1) is deployed for each user when registering with GOSH. -{ .annotate } - -1. The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.abi.json) - -To get its address, you need to call the method: - -``` -getProfileAddr(string name) returns(address) -``` - -where: - -`name` - user's name -{ .ml-params } - -from the contract [**VersionController**](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/gosh/versioncontroller.sol), (1) -{ .annotate } - -1. is a contract version manager used when upgrading GOSH smart contracts - - address (permanent) - ``` - 0:5cbbbce41fc4290f3d4b085ab30912831b710fa2c681f6ea227d4a22f2b304f5 - ``` - - The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/gosh/versioncontroller.abi.json) - + +First you need to get the address of user's profile. +The contract [**Profile**](contracts.md#profile) is deployed for each user when registering with GOSH. +To get its address, you need to call the method [**`getProfileAddr`**](contracts.md#getprofileaddr) of the [**VersionController**](contracts.md#versioncontroller) contract -The result is the address of the user's **Profile** contract. + ## **Transfer tokens** @@ -50,40 +26,11 @@ The result is the address of the user's **Profile** contract. ### **from GOSH to GOSH** -Before transferring to another TIP3-wallet, you need to check whether the recipient's TIP3-wallet is already deployed. +Before transferring to another TIP-3 wallet, you need to check whether the recipient's TIP-3 wallet is already deployed. -To do this, you need to call the method [`getWalletAddress`](l2.md#using-the-users-public-key) in the **RootTokenContract**, the recipient's public key is specified. +To do this, you need to call the method [**`getWalletAddress`**](contracts.md#getwalletaddress) in the [**RootTokenContract**](contracts.md#roottokencontract), the recipient's public key is specified. -If the recipient's TIP3-wallet is not deployed, you need to call the method `transferToRecipient` in the TIP3-wallet contract **"TONTokenWallet"** (1) (from which the transfer will be made). -{ .annotate } - -1. ABI [here](../static/TONTokenWallet.abi){:download="TONTokenWallet.abi"} - - -``` cpp -void transferToRecipient( - address_opt answer_addr, - Tip3Creds to, - uint128 tokens, - uint128 evers, - uint128 keep_evers, - bool deploy, - uint128 return_ownership, - opt notify_payload -) -``` - -where: - -`answer_addr` - Answer address, **(should be `null`)** -`to` - Recipient credentials (pubkey + owner **(should be `null`)**) -`tokens` - Amount of tokens to transfer, **(should be `0`)** -`evers` - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value -`keep_evers` - Evers to keep in destination wallet -`deploy` - **(should be `true`)** then the contract will send acceptTransfer message with StateInit to also deploy new tip3 wallet (if it doesn't already exist) with the provided recipient public key and recipient internal owner -`return_ownership` - Return ownership - to decrease lend ownership for the caller contract (additionally), **(should be `0`)** -`notify_payload` - (optional) < Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification, **(should be `0`)** -{ .ml-params } +If the recipient's TIP-3 wallet is not deployed, you need to call the method [**`transferToRecipient`**](contracts.md#transfertorecipient) in the TIP-3 wallet contract [**"TONTokenWallet"**](contracts.md#tontokenwallet) (from which the transfer will be made). !!! example @@ -103,35 +50,15 @@ where: ``` -As a result, an empty TIP3-wallet will be deployed to the recipient. +As a result, an empty TIP-3 wallet will be deployed to the recipient. !!! Warning - **It is important to wait until the contract status changes to "Аctive".** + **It is important to wait until the contract status changes to "Active".** -Then, for transfer the TIP3-tokens to the user, you need to call the method `transfer` in the **TONTokenWallet** contract. +Then, for transfer the TIP-3 tokens to the user, you need to call the method [**`transfer`**](contracts.md#transfer) in the [**TONTokenWallet**](contracts.md#tontokenwallet) contract. -``` cpp -void transfer( - address_opt answer_addr, - address to, - uint128 tokens, - uint128 evers, - uint128 return_ownership, - opt notify_payload -) -``` - -where: - -`answer_addr` - (опциональный) Answer address **(should be `null`)** -`to` - Destination TIP3-wallet address -`tokens` - Amount of tokens to transfer -`evers` - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value -`return_ownership` - Return ownership - to decrease lend ownership provided for the caller contract (additionally) **(should be `0`)** -`notify_payload` - Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification **(should be `null`)** -{ .ml-params } !!! example @@ -151,94 +78,58 @@ where: ### **from Ethereum to GOSH** -For transfer `ETH` to GOSH, you need to call the method `deposit` in the **ELOCK** (1) contract, with attached value (the number of `ETH`, that will be transferred to GOSH). -{ .annotate } - -1. is a GOSH L2 smart contract on Ethereum Blockchain. - It receives deposits from users, manage withdrawals and locks user funds. ELOCK is also counting its total balance, total transaction count and stores root Merkle proofs, withdrawal smart contract code hash, etc. for L2 synchronization. - - address in Ethereum: - ``` - 0x135d03AF576633B0C99FB9F0A0c6Aa9cE8D3C67E - ``` - - ABI [here](../static/Elock.json){:download="Elock.json"} - - -``` -deposit(uint256 pubkey) public payable -``` - -where: +For transfer tokens to GOSH, you need to call the method: -`pubkey` - the recipient's public key in GOSH -{ .ml-params } +* for `ETH`: [**`deposit`**](contracts.md#deposit) +* for `ERC20` tokens: [**`depositERC20`**](contracts.md#depositerc20) -Then it is necessary [to calculate the address of the user's TIP3-wallet in GOSH](l2.md#using-the-users-public-key) and wait the transfer of `WETH` tokens (wrapped `ETH`) to the received address. +in the [**ELOCK**](contracts.md#elock) contract. -!!! exsample annotate "example of calling the ELock contract in Ethereum" +Then it is necessary [to calculate the address of the user's TIP-3 wallet in GOSH](l2.md#using-the-users-public-key) and wait the transfer of tokens to the received TIP3 user wallet in GOSH. - ``` cpp - const elock = new data.web3.instance.eth.Contract( - ELockAbi.abi, - AppConfig.elockaddr, - ) - const edata = elock.methods.deposit(data.summary.to.user.value.pubkey).encodeABI() - - const receipt = await data.web3.instance.eth.sendTransaction({ - from: data.web3.address, - to: AppConfig.elockaddr, - value: data.web3.instance.utils.toWei(data.summary.from.amount, 'ether'), - data: edata, - gasLimit: 100000, - maxPriorityFeePerGas: 25000, - }) - ``` ### **from GOSH to Ethereum** -For transfer "WETH" to Ethereum, you need to call the `burnTokens` method in the user contract **TONTokenWallet** +To transfer tokens to Ethereum, you will need to call method: -``` cpp -void burnTokens(uint128 tokens, uint256 to) -``` +* for `ETH`: [**`burnTokens`**](contracts.md#burntokens) +* for `ERC20` tokens: [**`withdrawERC20`**](contracts.md#withdrawerc20) -where: + (then to call [**`getERC20Approvement`**](contracts.md#geterc20approvement) to determine the commission that needs to be attached to the withdrawal function call) + { .ml-params } -`tokens` - amount WETH, which will be transferred to Ethereum -`to` - the address of the recipient's wallet in Ethereum -{ .ml-params } -Then wait for the transfer of `ETH` to the recipient's wallet in Ethereum. +in the user contract [**TONTokenWallet**](contracts.md#tontokenwallet) -## **Getting the user's TIP3-wallet address:** - -### **using by user name** -Knowing the address of the user's contract **Profile** (1) you call the method `getAccess()` in it. -{ .annotate } +Then wait for the receipt of tokens to the recipient's Ethereum wallet. -1. The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.abi.json) +## **Getting the user's TIP-3 wallet address:** + +### **using by user name** -``` -getAccess() returns(mapping(uint256 => uint8)) -``` +Knowing the address of the user's contract [**Profile**](contracts.md#profile) you call the method [**`getAccess`**](contracts.md#getaccess) in it. As a result, you get a list of all the user's public keys with their numbers. !!! warning annotate "Important" It is necessary to take the zeroth pubkey from the list -Then, using the received user's public key, it will be possible [to determine the address of the user's TIP3-wallet](l2.md#using-the-users-public-key) +Then, using the received user's public key, it will be possible [to determine the address of the user's TIP-3 wallet](l2.md#using-the-users-public-key) + + - ### **using the user's public key** +To do this, in the [**RootTokenContract**](contracts.md#roottokencontract) calling method [**`getWalletAddress`**](contracts.md#getwalletaddress) + + -calling method: - -``` -address getWalletAddress(uint256 pubkey, address_opt owner) -``` -where: -`pubkey` - user's public key -`owner` - optional parameter, not used -{ .ml-params } ## **Getting a list of incoming messages of the contract** @@ -274,34 +157,24 @@ where: -## **Get info about TIP3-wallet details** +## **Get info about TIP-3 wallet details** -For get information about the TIP3-wallet in the contract **TONTokenWallet**, the `getDetails` method is called: + +To get information about the TIP-3 wallet you will need to call the [**`getDetails`**](contracts.md#getdetails) method in the contract [**TONTokenWallet**](contracts.md#tontokenwallet) -``` -details_info getDetails() -``` -and you get the data structure: -``` -struct details_info { - string name; ///< Token name. - string symbol; ///< Token short symbol. - uint8 decimals; ///< Decimals for ui purposes. ex: balance 100 with decimals 2 will be printed as 1.00. - uint128 balance; ///< Token balance of the wallet. - uint128 locked; ///< Locked token balance of the wallet. - uint256 root_pubkey; ///< Public key of the related RootTokenContract. - address root_address; ///< Address of the related RootTokenContract. - uint256 wallet_pubkey; ///< Public key of wallet owner (User id for FlexWallet). - address_opt owner_address; ///< Owner contract address for internal ownership, will be 0:0..0 otherwise. - opt lend_pubkey; ///< Lend ownership pubkey. - lend_owners_array lend_owners; ///< All lend ownership records of the contract. - uint128 lend_balance; ///< Summarized lend balance to all targets. - ///< Actual active balance will be `balance - lend_balance`. - opt binding; ///< Flex binding info. - uint256 code_hash; ///< TIP3 wallet code hash to verify other wallets. - uint16 code_depth; ///< TIP3 wallet code depth to verify other wallets. - int8 workchain_id; ///< Workchain id. -} -``` + +## **Get TIP-3 root list** + + +To get a list of ERC20 token addresses that are supported in GOSH Ethereum L2, you need to call the [**`getTokenRoots`**](contracts.md#gettokenroots) method in the [**ELOCK**](contracts.md#elock) contract. + +For every ERC20 token in the given list, execute the following get-methods: +[**`name`**]() +[**`symbol`**]() +[**`decimals`**]() + + +After that, you need to call the method [**`getRootAddr`**](contracts.md#getrootaddr) in the [**Сhecker**](contracts.md#checker) contract with the received data + diff --git a/docs/static/checker.abi.json b/docs/static/checker.abi.json new file mode 100644 index 0000000..1ef6232 --- /dev/null +++ b/docs/static/checker.abi.json @@ -0,0 +1,250 @@ +{ + "ABI version": 2, + "version": "2.3", + "header": ["pubkey", "time", "expire"], + "functions": [ + { + "name": "constructor", + "inputs": [ + {"name":"prevhash","type":"uint256"}, + {"name":"receiver","type":"address"} + ], + "outputs": [ + ] + }, + { + "name": "askEvers", + "id": "0x3F8", + "inputs": [ + {"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"} + ], + "outputs": [ + ] + }, + { + "name": "deployIndex", + "id": "0x401", + "inputs": [ + {"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"}, + {"name":"pubkey","type":"uint256"} + ], + "outputs": [ + ] + }, + { + "name": "setHashRoot", + "inputs": [ + {"name":"hash","type":"uint256"} + ], + "outputs": [ + ] + }, + { + "name": "setReady", + "inputs": [ + {"name":"ready","type":"bool"} + ], + "outputs": [ + ] + }, + { + "name": "setProposalCode", + "inputs": [ + {"name":"code","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "setIndexWalletCode", + "inputs": [ + {"name":"code","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "setRootCode", + "inputs": [ + {"name":"code","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "setWalletCode", + "inputs": [ + {"name":"code","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "setCommission", + "inputs": [ + {"name":"a_from_ax_div10000_plus_b","type":"uint128"}, + {"name":"b_from_ax_div10000_plus_b","type":"uint128"} + ], + "outputs": [ + ] + }, + { + "name": "deployRootContract", + "inputs": [ + {"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"} + ], + "outputs": [ + ] + }, + { + "name": "checkData", + "inputs": [ + {"components":[{"name":"data","type":"bytes"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple[]"}, + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"transactions","type":"tuple[]"} + ], + "outputs": [ + ] + }, + { + "name": "checkDataIndex", + "inputs": [ + {"components":[{"name":"data","type":"bytes"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple[]"}, + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"transactions","type":"tuple[]"}, + {"name":"index","type":"uint128"} + ], + "outputs": [ + ] + }, + { + "name": "setNewHash", + "inputs": [ + {"name":"prevhash","type":"uint256"}, + {"name":"newhash","type":"uint256"}, + {"name":"index","type":"uint128"}, + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"transactions","type":"tuple[]"} + ], + "outputs": [ + ] + }, + { + "name": "sendBatch", + "inputs": [ + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"transactions","type":"tuple[]"}, + {"name":"index","type":"uint128"} + ], + "outputs": [ + ] + }, + { + "name": "destroyTrash", + "inputs": [ + {"name":"prevhash","type":"uint256"}, + {"name":"indexmax","type":"uint128"}, + {"name":"index","type":"uint128"} + ], + "outputs": [ + ] + }, + { + "name": "updateCode", + "inputs": [ + {"name":"newcode","type":"cell"}, + {"name":"cell","type":"cell"} + ], + "outputs": [ + ] + }, + { + "name": "getVersion", + "inputs": [ + ], + "outputs": [ + {"name":"value0","type":"string"}, + {"name":"value1","type":"string"} + ] + }, + { + "name": "getIndexWalletAddr", + "inputs": [ + {"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"data","type":"tuple"}, + {"name":"pubkey","type":"uint256"} + ], + "outputs": [ + {"name":"value0","type":"address"} + ] + }, + { + "name": "getIndexWalletCode", + "inputs": [ + {"name":"pubkey","type":"uint256"} + ], + "outputs": [ + {"name":"value0","type":"cell"} + ] + }, + { + "name": "getRootAddr", + "inputs": [ + {"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"data","type":"tuple"} + ], + "outputs": [ + {"name":"value0","type":"address"} + ] + }, + { + "name": "getProposalAddr", + "inputs": [ + {"name":"index","type":"uint128"} + ], + "outputs": [ + {"name":"value0","type":"address"} + ] + }, + { + "name": "getAllProposalAddr", + "inputs": [ + ], + "outputs": [ + {"name":"value0","type":"address[]"} + ] + }, + { + "name": "getTransactions", + "inputs": [ + ], + "outputs": [ + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"value0","type":"tuple[]"} + ] + }, + { + "name": "getStatus", + "inputs": [ + ], + "outputs": [ + {"name":"prevhash","type":"uint256"}, + {"name":"index","type":"uint128"}, + {"name":"receiver","type":"address"} + ] + } + ], + "data": [ + ], + "events": [ + ], + "fields": [ + {"name":"_pubkey","type":"uint256"}, + {"name":"_timestamp","type":"uint64"}, + {"name":"_constructorFlag","type":"bool"}, + {"name":"_prevhash","type":"uint256"}, + {"name":"_proposalCount","type":"uint128"}, + {"name":"a","type":"uint128"}, + {"name":"b","type":"uint128"}, + {"name":"_proposalCode","type":"cell"}, + {"name":"_rootCode","type":"cell"}, + {"name":"_walletCode","type":"cell"}, + {"name":"_indexWalletcode","type":"cell"}, + {"name":"_receiver","type":"address"}, + {"components":[{"components":[{"name":"name","type":"string"},{"name":"symbol","type":"string"},{"name":"decimals","type":"uint8"},{"name":"ethroot","type":"uint256"}],"name":"root","type":"tuple"},{"components":[{"name":"pubkey","type":"uint256"},{"name":"value","type":"uint128"},{"name":"hash","type":"uint256"}],"name":"data","type":"tuple"}],"name":"_transactions","type":"tuple[]"}, + {"name":"_isReady","type":"bool"} + ] +} From ed14bfbda6dca6911d663be7f25d3de4443e5d41 Mon Sep 17 00:00:00 2001 From: Oxydixi Date: Fri, 1 Dec 2023 09:59:30 +0300 Subject: [PATCH 2/4] different --- docs/ethereum-L2.md | 299 ----------------------------------- docs/ethereum-L2/overview.md | 4 +- 2 files changed, 2 insertions(+), 301 deletions(-) delete mode 100644 docs/ethereum-L2.md diff --git a/docs/ethereum-L2.md b/docs/ethereum-L2.md deleted file mode 100644 index 6c19f12..0000000 --- a/docs/ethereum-L2.md +++ /dev/null @@ -1,299 +0,0 @@ -# **GOSH Ethereum L2** - - -## **Integration with GOSH L2** - - -### **Introduction** - -Endpoint for use with [Ever-SDK](https://docs.everos.dev/ever-sdk/) - -``` -network main: https://network.gosh.sh -``` - -The contract [**Profile**](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.sol) (1) is deployed for each user when registering with GOSH. -{ .annotate } - -1. The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.abi.json) - -To get its address, you need to call the method: - -``` -getProfileAddr(string name) returns(address) -``` - -where: - -`name` - user's name -{ .ml-params } - -from the contract [**VersionController**](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/gosh/versioncontroller.sol), (1) -{ .annotate } - -1. is a contract version manager used when upgrading GOSH smart contracts - - address (permanent) - ``` - 0:5cbbbce41fc4290f3d4b085ab30912831b710fa2c681f6ea227d4a22f2b304f5 - ``` - - The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/gosh/versioncontroller.abi.json) - - - -The result is the address of the user's **Profile** contract. - - -### **Transfer tokens** - - -#### **from GOSH to GOSH** - - -Before transferring to another TIP3-wallet, you need to check whether the recipient's TIP3-wallet is already deployed. - -To do this, you need to call the method [`getWalletAddress`](ethereum-L2.md#getting-the-users-tip3-wallet-address-using-the-users-public-key) in the **RootTokenContract**, the recipient's public key is specified. - - -If the recipient's TIP3-wallet is not deployed, you need to call the method `transferToRecipient` in the TIP3-wallet contract **"TONTokenWallet"** (1) (from which the transfer will be made). -{ .annotate } - -1. ABI [here](../static/TONTokenWallet.abi){:download="TONTokenWallet.abi"} - - -``` cpp -void transferToRecipient( - address_opt answer_addr, - Tip3Creds to, - uint128 tokens, - uint128 evers, - uint128 keep_evers, - bool deploy, - uint128 return_ownership, - opt notify_payload -) -``` - -where: - -`answer_addr` - Answer address, **(should be `null`)** -`to` - Recipient credentials (pubkey + owner **(should be `null`)**) -`tokens` - Amount of tokens to transfer, **(should be `0`)** -`evers` - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value -`keep_evers` - Evers to keep in destination wallet -`deploy` - **(should be `true`)** then the contract will send acceptTransfer message with StateInit to also deploy new tip3 wallet (if it doesn't already exist) with the provided recipient public key and recipient internal owner -`return_ownership` - Return ownership - to decrease lend ownership for the caller contract (additionally), **(should be `0`)** -`notify_payload` - (optional) < Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification, **(should be `0`)** -{ .ml-params } - - - -As a result, an empty TIP3-wallet will be deployed to the recipient. - - -!!! Warning - **It is important to wait until the contract status changes to "Аctive".** - - -Then, for transfer the TIP3-tokens to the user, you need to call the method `transfer` in the **TONTokenWallet** contract. - -``` cpp -void transfer( - address_opt answer_addr, - address to, - uint128 tokens, - uint128 evers, - uint128 return_ownership, - opt notify_payload -) -``` - -where: - -`answer_addr` - (опциональный) Answer address **(should be `null`)** -`to` - Destination TIP3-wallet address -`tokens` - Amount of tokens to transfer -`evers` - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value -`return_ownership` - Return ownership - to decrease lend ownership provided for the caller contract (additionally) **(should be `0`)** -`notify_payload` - Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification **(should be `null`)** -{ .ml-params } - - - -#### **from Ethereum to GOSH** - - -For transfer `ETH` to GOSH, you need to call the method `deposit` in the **ELOCK** (1) contract, with attached value (the number of `ETH`, that will be transferred to GOSH). -{ .annotate } - -1. is a GOSH L2 smart contract on Ethereum Blockchain. - It receives deposits from users, manage withdrawals and locks user funds. ELOCK is also counting its total balance, total transaction count and stores root Merkle proofs, withdrawal smart contract code hash, etc. for L2 synchronization. - - address in Ethereum: - ``` - 0x135d03AF576633B0C99FB9F0A0c6Aa9cE8D3C67E - ``` - - ABI [here](../static/Elock.json){:download="Elock.json"} - - -``` -deposit(uint256 pubkey) public payable -``` - -where: - -`pubkey` - the recipient's public key in GOSH -{ .ml-params } - -Then it is necessary [to calculate the address of the user's TIP3-wallet in GOSH](ethereum-L2.md#getting-the-users-tip3-wallet-address-using-the-users-public-key) and wait the transfer of `WETH` tokens (wrapped `ETH`) to the received address. - -!!! exsample annotate "example of calling the ELock contract in Ethereum" - - ``` cpp - const elock = new data.web3.instance.eth.Contract( - ELockAbi.abi, - AppConfig.elockaddr, - ) - - const edata = elock.methods.deposit(data.summary.to.user.value.pubkey).encodeABI() - - const receipt = await data.web3.instance.eth.sendTransaction({ - from: data.web3.address, - to: AppConfig.elockaddr, - value: data.web3.instance.utils.toWei(data.summary.from.amount, 'ether'), - data: edata, - gasLimit: 100000, - maxPriorityFeePerGas: 25000, - }) - ``` - - -#### **from GOSH to Ethereum** - - -For transfer "WETH" to Ethereum, you need to call the `burnTokens` method in the user contract **TONTokenWallet** - -``` cpp -void burnTokens(uint128 tokens, uint256 to) -``` - -where: - -`tokens` - amount WETH, which will be transferred to Ethereum -`to` - the address of the recipient's wallet in Ethereum -{ .ml-params } - -Then wait for the transfer of `ETH` to the recipient's wallet in Ethereum. - - -### **Getting the TIP3-wallet address by user name** - - -Knowing the address of the user's contract **Profile** (1) you call the method `getAccess()` in it. -{ .annotate } - -1. The ABI can be obtained by [link](https://github.com/gosh-sh/gosh/blob/dev/v6_x/v6.1.0/contracts/profile.abi.json) - - -``` -getAccess() returns(mapping(uint256 => uint8)) -``` - -As a result, you get a list of all the user's public keys with their numbers. - -!!! warning annotate "Important" - It is necessary to take the zeroth pubkey from the list - -Then, using the received user's public key, it will be possible [to determine the address of the user's TIP3-wallet](ethereum-L2.md#getting-the-users-tip3-wallet-address-using-the-users-public-key) - - -### **Getting the user's TIP3-wallet address using the user's public key** - - -To do this, in the **RootTokenContract** (1) -{ .annotate } - -1. address - - ``` - 0:1792014440934b9c4024c97221b49c50bd2e2db1426b612ba4c6694b144f5e77 - ``` - - ABI [here](../static/RootTokenContract.abi){:download="RootTokenContract.abi"} - -calling method: - -``` -address getWalletAddress(uint256 pubkey, address_opt owner) -``` - -where: - -`pubkey` - user's public key -`owner` - optional parameter, not used -{ .ml-params } - - -### **Getting a list of incoming messages of the contract** - - -!!! example - [of how to receive account messages](https://github.com/gosh-sh/gosh/blob/dev/web/src/blockchain/contract.ts#L90) - -!!! info - [Using](https://docs.everplatform.dev/samples/graphql-samples/accounts#pagination-parameters) pagination in the SDK - - - -### **Get info about TIP3-wallet details** - -For get information about the TIP3-wallet in the contract **TONTokenWallet**, the `getDetails` method is called: - -``` -details_info getDetails() -``` - -and you get the data structure: - -``` -struct details_info { - string name; ///< Token name. - string symbol; ///< Token short symbol. - uint8 decimals; ///< Decimals for ui purposes. ex: balance 100 with decimals 2 will be printed as 1.00. - uint128 balance; ///< Token balance of the wallet. - uint128 locked; ///< Locked token balance of the wallet. - uint256 root_pubkey; ///< Public key of the related RootTokenContract. - address root_address; ///< Address of the related RootTokenContract. - uint256 wallet_pubkey; ///< Public key of wallet owner (User id for FlexWallet). - address_opt owner_address; ///< Owner contract address for internal ownership, will be 0:0..0 otherwise. - opt lend_pubkey; ///< Lend ownership pubkey. - lend_owners_array lend_owners; ///< All lend ownership records of the contract. - uint128 lend_balance; ///< Summarized lend balance to all targets. - ///< Actual active balance will be `balance - lend_balance`. - opt binding; ///< Flex binding info. - uint256 code_hash; ///< TIP3 wallet code hash to verify other wallets. - uint16 code_depth; ///< TIP3 wallet code depth to verify other wallets. - int8 workchain_id; ///< Workchain id. -} -``` diff --git a/docs/ethereum-L2/overview.md b/docs/ethereum-L2/overview.md index 38af401..04e2c39 100644 --- a/docs/ethereum-L2/overview.md +++ b/docs/ethereum-L2/overview.md @@ -99,7 +99,7 @@ Contract `Checker.sol` receives an external message from `Proposer` with Ethereu * **RootTokenContract** - is a smart contract on GOSH that manages user withdrawals. It receives TIP-3 transactions, verifies them and adds transactions to the counter index. -Also it deploys the contract TIP3 wallet contract (`TONTokenWallet.cpp`) and sends wrapped tokens there. +Also it deploys the contract TIP-3 wallet contract (`TONTokenWallet.cpp`) and sends wrapped tokens there. * **TONTokenWallet** - is a custom TIP-3 contract that runs in GOSH Masterchain and in addition to standard functions has `burnTokens` method. It is called when WETH needs to be transferred to Ethereum Blockchain. Burn is proven to ELOCK contract in order to allow for ETH native token withdrawals. @@ -110,7 +110,7 @@ Also it deploys the contract TIP3 wallet contract (`TONTokenWallet.cpp`) and sen ### **for deposit to GOSH** -When transferring assets to GOSH, `checker.sol` sends the transfer amount and coefficients `a` and `b` to the `RootTokenContract.cpp` and it calculates the commission amount. Then mints the wrapped tokens to the user TIP3-wallet minus the commission. And the commission is sent to the wallet by the commission in GOSH. +When transferring assets to GOSH, `checker.sol` sends the transfer amount and coefficients `a` and `b` to the `RootTokenContract.cpp` and it calculates the commission amount. Then mints the wrapped tokens to the user TIP-3 wallet minus the commission. And the commission is sent to the wallet by the commission in GOSH. calculated as: From d1d57187c99f618e2af18d4ec40b02f16562633a Mon Sep 17 00:00:00 2001 From: Oxydixi Date: Fri, 1 Dec 2023 15:18:37 +0300 Subject: [PATCH 3/4] added usage for ERS20 --- docs/ethereum-L2/user-guide.md | 169 +++++++++++++++++- docs/hacks-and-grants/user-guide.md | 2 +- ...ethereum_usage_withdraw_usdc_6_pending.jpg | Bin 0 -> 8930 bytes ...usage_withdraw_usdc_7_metamask_confirm.jpg | Bin 0 -> 43641 bytes ...ereum_usage_withdraw_usdc_8_no_pending.jpg | Bin 0 -> 8066 bytes ...ithdraw_usdc_9_accounts_after_withdraw.jpg | Bin 0 -> 10570 bytes 6 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 docs/images/ethereum_usage_withdraw_usdc_6_pending.jpg create mode 100644 docs/images/ethereum_usage_withdraw_usdc_7_metamask_confirm.jpg create mode 100644 docs/images/ethereum_usage_withdraw_usdc_8_no_pending.jpg create mode 100644 docs/images/ethereum_usage_withdraw_usdc_9_accounts_after_withdraw.jpg diff --git a/docs/ethereum-L2/user-guide.md b/docs/ethereum-L2/user-guide.md index bdfdaeb..87affbf 100644 --- a/docs/ethereum-L2/user-guide.md +++ b/docs/ethereum-L2/user-guide.md @@ -7,6 +7,7 @@ Any DAO on GOSH can become Ethereum Layer 2 with a click of a button. This is only possible in the GOSH version of at least 6.1.0 ## Deposit ETH to GOSH + To make a transfer between wallets, go to the **Ethereum** tab: ![](../images/ethereum_usage_begin2.jpg) @@ -29,7 +30,7 @@ In the **Accounts** section, click **Connect** to log into a software cryptocurr ![](../images/ethereum_usage_connect.jpg) -Choose the amount you want to send +Enter the amount you want to send !!! note The amount must be greater than or equal to 0.01 @@ -40,7 +41,8 @@ Choose the amount you want to send ![](../images/ethereum_usage_from.jpg) -Enter the wallet address or select the GOSH username for easy transfer +Enter the wallet address or GOSH username of the recipient for the transfer. +The **Amount** field will indicate the transferred amount (minus the commission) that will be credited to the recipient's wallet in GOSH. ![](../images/ethereum_usage_to.jpg) @@ -77,7 +79,7 @@ In the **From** section, select the **GOSH** blockchain and enter the sender's w ![](../images/ethereum_usage_withdraw_from.jpg) -In the**To**section, make sure to choose the **Ethereum** blockchain network and verify the Receiver's wallet address for accuracy before proceeding. The ETH amount will be automatically calculated. +In the **To**section, make sure to choose the **Ethereum** blockchain network and verify the Receiver's wallet address for accuracy before proceeding. The `ETH` amount will be automatically calculated. ![](../images/ethereum_usage_withdraw_to.jpg) @@ -94,17 +96,168 @@ The amount of the expected commission for the transfer and and the time before t Tokens are withdrawn every 3 hours + - -Please wait until the process of sending WETH tokens and receiving ETH fully completed -![](../images/ethereum_usage_withdraw_step3_compl.jpg) +## Deposit ERC20 to GOSH + +To make a transfer `ERC20` tokens, go to the **Ethereum** tab: + +![](../images/ethereum_usage_begin2.jpg) + +or select this section by clicking on your profile in the right corner: + +![](../images/ethereum_usage_begin1.jpg) + +Click on: + +![](../images/ethereum_usage_begin3.jpg) + +the **Cross-chain transfer** page will open for you. + +Let's look at the token transfer using the example of the USDC. + +In the **From** section, select the token to transfer to GOSH + +![](../images/ethereum_usage_transfer_usdc-to-gosh_1_from.jpg) + +To log into a software cryptocurrency wallet **MetaMask**, you can either click on **Connect wallet** or go to the **Accounts** section and click on **Connect**. + +![](../images/ethereum_usage_transfer_usdc-to-gosh_2_accounts.jpg) + +Enter the amount you want to send + +!!! note + The amount must be greater than or equal to 0.011 + + +![](../images/ethereum_usage_transfer_usdc-to-gosh_3_from_sum.jpg) + +Enter the wallet address or GOSH username of the recipient for the transfer. + +The **Amount** field will indicate the transferred amount (minus the commission) that will be credited to the recipient's wallet in GOSH. + +The Summary section will display detailed information about the transfer + +![](../images/ethereum_usage_transfer_usdc-to-gosh_4_to.jpg) + + +![](../images/ethereum_usage_transfer_usdc-to-gosh_5_summary.jpg) + +And click **Next** button + +The transfer process has three sub-steps. +The first one is to approve tokens, followed by deposit tokens, and finally, waiting for the transfer to be completed. + +Once you click on the **`Approve`** button, you'll be authorizing the ELOCK contract to initiate the transfer of the specified amount. + +![](../images/ethereum_usage_transfer_usdc-to-gosh_6_aprove_tokems.jpg) + + +In the opened **MetaMask** window, confirm the necessary parameters for the transfer. + +![](../images/ethereum_usage_transfer_usdc-to-gosh_7_spending_cap.jpg) + +![](../images/ethereum_usage_transfer_usdc-to-gosh_8_approve.jpg) + + + + +Click on the **Deposit** button and then check and confirm the transfer parameters in your **MetaMask** wallet. + +![](../images/ethereum_usage_transfer_usdc-to-gosh_9_deposit_tokens_elock.jpg) + +It's important to ensure that the transfer is being made to the **ELOCK** contract at this step. + +!!! info annotate "**address of the ELOCK contract in Ethereum:**" + + ``` + 0x54a858bBD5968Eb755e54C45a3fe5B002bE3c254 + ``` + + +![](../images/ethereum_usage_transfer_usdc-to-gosh_10_confirm.jpg) + + + +After that, you just need to wait for the transfer to be completed. + +![](../images/ethereum_usage_transfer_usdc-to-gosh_11_receive_tokens.jpg) + +After successful completion of the transfer, you will see a confirmation: + +![](../images/ethereum_usage_transfer_usdc-to-gosh_12_completed.jpg) + + +If you want to view your asset balance, you can find it in the **Accounts** section. To do this select the relevant token in the "From" tab. + +![](../images/ethereum_usage_balance_1.jpg) +![](../images/ethereum_usage_balance_2.jpg) + + + + +## Withdraw ERC20 to Ethereum + + + +To withdraw ERC20 tokens from GOSH to Ethereum, go to the **Ethereum** tab on the DAO page +and log into a software cryptocurrency wallet **MetaMask** + +![](../images/ethereum_usage_withdraw_usdc_1_connection_metamask.jpg) + +In the **From** section, select the asset that you want to withdraw to Ethereum + +![](../images/ethereum_usage_withdraw_usdc_1-2_usdc-gosh.jpg) + +The available assets will be displayed in the **Accounts** section + +![](../images/ethereum_usage_withdraw_usdc_2_accounts.jpg) + +Enter the desired number of tokens to withdraw + +![](../images/ethereum_usage_withdraw_usdc_3_from.jpg) + +The Summary section will display detailed information about the withdraw + +!!! info + + Tokens are withdrawn every 3 hours + +![](../images/ethereum_usage_withdraw_usdc_4_summury.jpg) + +In the **To** section, in the **Recipient** field, you must specify the recipient's Ethereum wallet address. +The number of tokens will be calculated automatically. + +Please click on the Next button to proceed. + +![](../images/ethereum_usage_withdraw_usdc_5_to.jpg) + + +The transfer of the ERC20 tokens from GOSH to Ethereum will take some time. + + + +After the transfer process, you will be able to view the list of your assets that have been transferred from GOSH to Ethereum in the **Your pending withdrawals** section. +These assets are now located in Ethereum on the balance **ELOCK** contract, and you can withdraw them to your wallets by clicking on the **Withdraw** button. + +![](../images/ethereum_usage_withdraw_usdc_6_pending.jpg) + +Confirm the withdrawal of tokens to your wallet + +![](../images/ethereum_usage_withdraw_usdc_7_metamask_confirm.jpg) + +Wait for the tokens to arrive on the balance of your Ethereum wallet + + - +![](../images/ethereum_usage_withdraw_usdc_9_accounts_after_withdraw.jpg) \ No newline at end of file diff --git a/docs/hacks-and-grants/user-guide.md b/docs/hacks-and-grants/user-guide.md index e434bc6..1a886ca 100644 --- a/docs/hacks-and-grants/user-guide.md +++ b/docs/hacks-and-grants/user-guide.md @@ -196,7 +196,7 @@ Then, in the form that opens, click **Add application form DAO** ![](../images/H&G_hacks_18_add_2.jpg) -and enter the name of your DAO and the names of the repository that you require. +and enter the name of your DAO and the name of the repository that you require. diff --git a/docs/images/ethereum_usage_withdraw_usdc_6_pending.jpg b/docs/images/ethereum_usage_withdraw_usdc_6_pending.jpg new file mode 100644 index 0000000000000000000000000000000000000000..be651b1bd2604345c5b68a1c177e93fd4a04cc50 GIT binary patch literal 8930 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 literal 0 HcmV?d00001 diff --git a/docs/images/ethereum_usage_withdraw_usdc_7_metamask_confirm.jpg b/docs/images/ethereum_usage_withdraw_usdc_7_metamask_confirm.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5950221134715279299c41e7ccc1313e84e80975 GIT binary patch literal 43641 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®uPbR0O03girz~ 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 JJ@I4YzW^g~tDFD; literal 0 HcmV?d00001 diff --git a/docs/images/ethereum_usage_withdraw_usdc_8_no_pending.jpg b/docs/images/ethereum_usage_withdraw_usdc_8_no_pending.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2780e3287c91b486087290bfbe0d606377c5fdca GIT binary patch literal 8066 zcmeHscTiN%m+!z3B?yukMvx#NNumS+k(@!2gaOG6Fr*nI2T{p6$3Z}b43c4xAW^a; z2}4H7Suz5Pe&1HTs;zo&x9YclY}NLyI-gs0Zl6zg-&5VE&$*epSp<-&C@3ocu&@9C ztlI~0g8|3_@NjVPaB=YPaPjc*@d)ma-MK?Zc!!eoE-@JmB`qxtB{elYn2nJh#KJ&L z&BV>b@{pbL5hooZ&to2r$7~#&9Dj^p;p5}qA-F?v=MDu2JvBYYf4SYX0mume3E0no zSj+%yax5S@)=ejX;m=U9fq%yP?+qIl9|w;B_(v;A2EYOWv2n3+aPR;)_M zt1yR%rnppNinfDB6uEsG*RFFZlIQn+Jz6y4_*vidyUz_XcWwQchw?9q!FF!|0;$yD z|GZ?@od%?-5y>rTP~wU{5ttdXw$;ZwYrwyuZG>>u!%7>Yt(6RDT1oAD2C{ynNpDK9@N#G?XCp zUn`iMQ7gN1H-OPv3O_oj(K1L|E@K|!3{_#sde6zbSsrqNukC>m%65{9klbeZ32)h# zbH&AlUK*c`N*qv#=(AUZKBAe*Pni%mfViGHKR@~wlX3)o_PC!Rq6Af`ugp@&$(}YF zZvS#zUF||?NJ97?T@8|FvM>KzGCP!4PLu922KMAbqSvMG(o||@$PIgF?Q}eCIW~9MxpPYgc;>N~RNHmm&_iaA8^A{!UXU_% z@hGx#Y}Q>*Ds%ke^-lio#9JX)h3(;{^s{Y}ixo#$f-FV6w9=mbd9%X3RKL5CJ)5K5W-XkOYsevcufU_ zb9s)7ahdLhG1`8*A4X}?RjH`Tm;A@w)m9aqKG;&E5AS-NtZTF#^|sAvDj%Dfl7vTS zeDmIre~7ArVo+%{J7>5(h$5gLi-lsP z{N=3hmFP!R75s+oxfXOu5Dc7IIv^uVH8*Q>8I|cOuJ3=q%(uyl7!NKBxSffwJea-# zVEOA`RM?@8(n-AbC+_BCJ{CyI|2+DO9UtGsis9B*WHfzOyPEjfP$O~&MT?_aJ+l((+878ymal?e+| z_4O8V6%~A@omyKOsQJ{`k@D~cz$@8yJz>G?;O`H8XwUarif8?uso~KcL>KC;b)}V8 z55;unG>p$%#U&nb_ghBAD-j`g&H^3-EtAk!LdU$5<%Q)M*1~$lOAZ0Jek5>NMyv(+ zh2v5S!I!Uh`>T?vX+2YU8L( zGJ`v}^D*pgBfejozN;`NT}1Gjd?CyqJ;OVrqq|82K`m*^o5zcMmC{GsNOt1a+z-Tx zzgso9wV+peA^m*DU0z;N9>O-zwSVy3=)UZfDd`#r3#}otzx63{du7bQJa>JjVBE(q zya!dz|6<%AOXew=whW;iJhE&V=f?_=MH=0)#rKla@d5=AE^wrQsQVV!`KeJ7pL6#7 z9{RH2x)XJfxt$PJ@r5qpcU?G--p6KWoxLPnJ|AS=gxRg?JRJr*T0GH_jDkln2qwg0 z;rNImAey6~E}j?@?+FBY$Ra1VfiT~zcgX?5FUolRaIoo-ZDJ>=a*KR$ozh6*uGz-a zj6@Vhag)d?wKP@{ci!$xWQf0kSl$PTtgtCqQj^i*YKTzKr~tvKKB|mQ=t@qWQcey> z?%DrCkUtqo*m*Rreq?p2QtNShR7D2Z>Hj@AC|qjfw7gCaBB1%%DjQpI4rwO+33l%W zp7Q?a>p7@7#eWyD& z1bruEWRued{q573v7tI!*$~6wNjJSExjR!_RWvh1 z{0RLJ^lXC`C(29UNy%eSOa>@v|M)?a|HmWT3Ol%0<+g&NiZvQ~L>f~Nj^Yq13l=SY z<~RUrVVVX!XcKkW6~O9op?-ntvMWwrU{fy+g7T~hImc&33-vgol+LBOye&U$r*mnP ztWfklBy0>{;vbANwVyCb9?1`&j%={U54D@Kx5CaJ?0@AG49uDe(C}+$vi8=4iXrCo zJeJ*-3|*?#wO=9IITxND)EO1ChZ(99DewZ}MvvznwSr#!gpS1ri3Ey=ze(&~mybP0^8sGx#+ zeL3IL$R;hcC2|GJ?#AP!$+J3 zSydtn8%>?|Z+I_;ZR-pSqa$gSoz=sH4M*ni^tbjg|@=Z|&A zrh7=A3{g+lP46T(+JCGwE?oanl8~Xb=?S7sy8+A|eiMyegSTvfsl!M2=hTOI z#B8iP8(Nn$uwvhJ$Zu}ndV4V8S$6ZRFrqB)Lknibx~0WDG~I}W)Z9a1w!GF-c9 zmt})Vr<{G`>ReI2f)w4}or?RjJ>l##;_9_~#YP>Pn=ueS!MB=vGA{18UvjPWM_;PiIl$J&+>^+mri*98js@Cvl|iimQ{kLndwUjMAgI; zrp>aGgu*7GW^G@&!2_GAYst+D=xx7yR||UYy$j%DnJ)Z6-yJeaX9+Lja92wam;|=l zWiSdyN$2$502~g#DDvo6*IlS{F+h2Ya&y<1nD&2z=vku*j$GlbQ>I0*=uymA1xcM& zM0HxfaBf!S;jHDm-e~SuBvo;SJldw#Ow#W~F0+NqEEP$gG1fa8UT^ zA)b_D^VuT)FL$s+^pPydqu9z`V6Z1b0{#-3c(G$N|-!0eOGU|liU~HyHmF*uDr#%I^L@Zv_$O9 z9y|>sy7l$hd`aZAI-;m?%(!r=VLWhpGw)4VvKD{f+M5)tH{+MwXRpn!d?h)ZVcrYI zP(B$y7IEJXWL zLwCNn(HR=rmxOb}QW{6!T=#BP&Ies2eB?GwdSSF@prR_=H^dfR6<;=6q}nm7>_EE5 zE=f-~)bC{sJ9>?#Ei6k+JVLl)vjibUdO%oW(`5jXUM?z^k#vinh-)^Nu{!UPV41VD z!aU!1(eD}}?3m2}gP^o3&79K*1OYL0#75B^J`rss0doN`z;4X#?pSOv9 z$QaOT1(a@E{X@uaDJapNk9OscC-H%AS&-&2on(sJ&3aDN7@mZQVOYJk_TbBFm|Eh# z$PyymY``_b%;J(Tbo3JjK-0ZHbH(KTA1Cf zzuGYOEAy9E!iaKlty9fN9ajW{!n=Q;SJR>P+o?G&q>6B&UzG=I)dgAOxQYnk#T^EJ149PKfuMsN#@GCyuH@5UpSK>G&l7BlRpT0cp>1I zZxq%NnGMx1U(~)k60>vXpA3W(b!a#?GZQoOzgGN1mFt|xKBHICK>0V>QA>73d;Klr zzbobOhpI4Rz4s)^ei!#IRhgW$f^^NpCA-iM|8ag_AiME~<*@WRlbO}fH-|Al`@U%i z?sW=AUdBw=>OavkUT~|gBRKbcZujHbR!w*@+o`P#TGFS{gAK}uu~AVx%JGAIuR$y5 z)YJxv9DjK&LV`n_8Lua;P0Q&p2%}gm&3l!!4+p-T(Ez3|jR(B%{j8~hBrgJ&}Jl90s>%eA+6il-+S&Y5hq z;tHdzA?8o{ZPHFA(?e>c5wKl}F0RUrE*^jybH6{959XNb7&r$9`c-CvFZmMdE+=4m zMaK(R3gcfs1Q8*spyHaE#x>x30cBwJP-3ugO*_~}iH-)vn$9FHdH|RtGx@%<3Iww&3wJj*_p=Y8N?3~@C#(zlGLD< zBH~f=)~K2?yW6S8PU6D;&b6`AYDH>gT9aEX4o-GCVfs-xo5(&_cuYj3|A9d0RCm+i zF1)cvjTeGk?oSf@;piOva^51DeI@)!bRH~b@1oR_Ck5nZUR3v+dv={A+7soIDw_J3 zVG{7Vr%p0Oyu&#;2s3W%tg zCuz`D25qeYk!wQTySz=nPH|XOkx*=~IDQuu*f;S&oYS(z3B*p(5RrZxiYuQ;P!*4X ze0rwg>3h70nN*!`x~h_tWhJPz*nTwzLfjv(YL1xJoFaB`cl8bKIFym+@P&eEpHPC})VcM$vB*lamAt*L* z=9!D+lwlPOqsPPezgOP({q0xob9!OUH+gZ6n1DbeTXK=fO1Bq18-`a5=3RNO-(JQy zPCT(O-rS=ir4mRtva>?in8mJ1Ct6z8tA;^JhksB1~4ukOGJ z)>`R`3|x)rQv&y$NoWskdTl{rZo`fd5$DVLAy1z$HI{C5#7&A_(TMLjC07~iHlZbj0VMN3jfPu?Iww%Os(#&mxSL)3%z z^vA1lV?ROMV5!vN-~|YyIE8liaM0_ssJI67htQf@I~+dibqM@j0J&$T*@T(d)i%E=fpW5fR(J-H-Kn^iOJ0{ zMjbYiDx-9IkH(lxmG3Fk*G_oZgE6zV(~!C`NuC+{B1ZD4dk$$)K|;-)=&aAAS3JC$y7 zqiy|j6XIKclnxQ&v2DO{A3ifN_vULH`QFgir#SPm1c5cZZsd(%r@OOUJI}HHh$m4q zSIC)*|B5oDswR6{HpnaS{8SN~C;hn84%d(Rj~oz4Y!D&c2GAd71~+RL)#p8Dw? zBPPSHX?#+Ztgv2+z$PYxav)ZvT|)HDVb%@6%U2mTuz-POt`=;O_1Lf2e4 z9+v=e08DfYObm2PObkpcEX*g^gxJ_mpJJ2X6W|h(lK_F_BxGci)J!y#R16?8GFnbr z24)sEb~XwcE?zEHUM5yH*1w#fU}0flKfxx(#wKQ^B%@^gzm~@?0MQe`8LBiI3OxXo z2nCG@<*^R{`fIAFXn)Q3AA*X3iH44a^5l;oobdxfKBz`7i6nJSR_-80N%3tyipMPsnP|^MvxQYJw0H9%F zqN1Xr{fixi2$fFu8J}h1=M#GEKc1#SHqiKqYhUX8dRzqHqW$Slghm9A2HfjJ6ixuv zQO&jqby&yX;dhPPmfAZ`=6?w z3=E68dmUHGXMcaFUN1M0S6iXc4RWoN@0hv}xx${2kyk(=55JsQ(sy}3H+Lsh7Mj@z zV>QzE@cVWp4$P)?STtUzboH0r-K~CGoGBi`0LNI%C}hT1O@)*)%zkoM@i+=t?%MHfRzK-B`%$c~x1+S}OA$EBHC-@2sm zw?^TLlBb#G;SJ@j(Yn+3`QPt#O&uyIL&Iyo;6_lM&Nt(?8L#8i+}L_~*wxOoDgw8W zX;Bj1X^#LZyCB3PfPXGNJ!Dg6I~jH=uso61yC17*Gpom3r?JAuEqEjf%}o&fawF;i z{vCmn)Lp_Q9uD_8^f}Cr!>^bUA0z3u(zKOp~{p^&-DM<+*)@E82b#b2v$d`VO z_6Yd>4gL3nX=c#$yknc`BuQTSc-fJ62}Qh9TZ=t~C}Ju{l6Ex_Y*qwmm10=9Fvu?| z%`4%Kp`<>w6HiNoH53-ZWmpnVv=@FlTuK=her^fUZ{n|_6g_a!t~C`-XlZeE^OAYu zy6aCo5wg?YPLCA)3C`0Z>_=5-R2AjXf0P^o4A&5b&Iz*Rbltlq@=7z@0VDal$xD?halnCDUOlfQD zs$)2D7bh9pV-C$Vzd2$g#OD_$%`((AnPWc-l&yz!(D)_SkKCJR>n$EBo2koFsotRT z@&-9<0HparNfCI^dGD8dg<$E`XKAgLS&g?67kZx`7{X*A3xm@1dx ze%V>cSw)5Z}7xY}a>BY%jIqbv4-HA7vY@!S*~BIa8{2o_DHRC~@A8~PnoMuj zyVU@-cQg0V3tX+C;b)%hj?_v94+Y+fgKSXSZue?GF;{f<1~}W! zjRr(!Ngt3!!O^Q-_&$O_r#o;ZP+iCe2DZqHA4a!3IT%@+)-y%$SX7CCudf2xkKBzl zfFg<0mlwl>5>;x7`yDj zBc|TqghI<-EqrF|`fM6*SLGWycrP}0grA#gPyzbGzm@A`exA5=P2R&^wUpq=#-XoAYT0UuX#w&Diw@b;JxomN?%`YIp4N%M6$KN9d z!Ggt`uQ|uOS#W(Ul!s}$3+*HKZdP2#=}a)xczG~y2&l2uAUzaW=+()@(n)uY#s^{tfmdsS$A zDCZ8v#D-3BUjH^6;6013fR znyv^<#`Qs;g66us0_^>N2%co0dF9`J4gIJ46cHg25z2q6`unb^{V%{coA~TX3Awh+ zq0QqSpnl&|KS@ONAB5ch6I}mWFpMrQnSv?At47^r1zcbmpw``{9p3wTjU41(8yJUnAKHNz*DX5~ zL4+B}0?8zkNIv?B6x^&yru0(kO-Q8moL)W}G*^3D*s3*aTJC&)p{-&f4|JphkLIoN zuk`lP+VHR(YE)}0Ikm{i**9uJL=M((Gh8&|48pXI`sC?cMNg;(f|$+}_nR4y=FMlR zK5SGKCWU(rEWOVY!`XsHn=fx1Qd7jes_HNBc!F|~a}LL_ zv`$qO8b)X6H{*AMFp0$9iw63EK8L-E`YUZ5B`r;Q7T?)3gdinGa<9Kz7B5J?cZqE; z7!8YDfh(Z_O`FU-e7+h>y?`_@!_1m2} z=0GMpcKgv6$ril#sL?%@A~^SrO3KikmNu#==nGYb_f--B3RS?3>bDjXzhbW;n z(ZHfU$1>%%=^?k>jA!0aoHg?x!+T2C&2-?S64ACf<*`kY>9Kv;*Qz=`YD-by^U|BZ zV1;!pO}~0G&Qx(b{AtGn3{!1G1%LcZxHrg+Ap#l^+uM%gDrOBdxv~|yNS){M9$9RS z3ZHSLSPxdC^N!*J+3>YUbG*}}8_h7Fzdf(6Z&{B+BM&|cxWQYX&O3)41ZbA()Y zD3CO`Aw`GYY-$MG?9l>v@nyPphMh#lrJ*&KAB)Z}$_*X)z(`(X)Bti`+$VossCorA zel#E2FI$OASSv6JlFeewKT^yqmqhx-J?!`CRyFMDJ{*MVGg>0POZ ze9CELvyHHl|B~`vs0Q{0`ZUYLaVMUg#M!^|bF^~tO&WG=(J?vp^2JuYt;LX%JZnf& zRaq3S&&q3U*l-P zoGXMn=#|@?X@%Yc^BnDE5nZXza+mT?uuXKFTb-=`fVg(LyjOyhwAed@iianiZO=>% zCT{Z^LUevei4-w~bIJKNEfuD_#ED0SnQrW2nFajYPt-LoH(5 zj|dN?sK1JK5B)OZ5~vV7F5z#|G%w-id2gqvI|kY%;9t!R1Xog;h(|;`i3t8ng);tB zx(LEBj+B_Xx9B#gh)8RFQS`839O;*T@b;LrD7f%mj9qSwReV|k0$S&nVWAi>+;*Au z&?s;|=xE~bJE}#@lTq;A9}ZyQ_3m&DMvUBhD`KA_kj|*#QAGt)GxH1f`0nRIuhys- z2fRf3GtR(R(q#k_79VknilU9DXN|e0^_H%LGdsV?xouAf) z7%(6Z45rgQs7fQowc2a@+a=cMr1Wr=SGZ+dAQoxSF0lzMMYoviikMl>xU7-o(IHqP z|5Kmmcza{zy5Y^_P|4S3T!pOet7#8ma$K)cd@`1Hp|5gQ{NTrLP-gc)?X49OcY<|~ zfay67K~h6@Fy|YbfRU$}Bh5ZS+qt3z-e@xJARDS}!ikzR>WaAf}w$ZE0DiZVu)P+gh*c8w@nOQ!jycc%8j*&d#3H zRre}yHmz!c6e1Fl{PS}oy^OAeP>^K>1h|~FE>dk;kuMlf@ZCW$)l{>hu3veCtFCPi z3Y?@=aR7SJzT*q!=dC3+Lnm>D`>LjI`-ifw(-kQ-pQGV3Oq8B*WUiSmcC)UJqt{4S zZ>9itvuxZMiNcW23N|uxxF2rQvNSsG-N8tyOr6>-r_y$d3yez+lfHWQdG?4k5*_@* zj}S`p%d>7D(UI*|PpFD+2{$>!_VnHswoUbGa;XeBbnpbYDwn=Fzl8=>mTbSNTu(q@ zT*oh{@cT*PTy{VG~haeYsTlQ)hEMU4g*gf0USw5 z_nMNiPLq1mAN%ZLXK?|_-D8QNzNq;4*kw4|LePGy(gSecuMA87aR;YL;4qLeP96jT zanwagY?x1`QQe*09Bha?#{4ii2xL+kYz$s%_WOtvZnJ3*L>yl40Z)t?qVqZw3_a3Lh1EjfuNhMa!eAS@hS&yx~}AP0$zV{jv67b(=(9|?+CWY*t z#A?k75=A!RZM<)X9sh`l+3?+*m5`aHx$yVI{O#5K2vBX)T@mQsbn`a(+O!Hp9Jl}4 z)_r(wKVrT5^r1N)!LqP(rF6i4ymp}`c$7C|=9=F)-LI+dl{j8p5ZTqzB~;1H?Ux<* z`ujVBjc@7!pgFY_bYam7L#lx3*DfSlulDJ-vYuU^1{z3o=L0Og8p6YxmpxdK;+neZ z#XS7FQK}gj4D6dFkp-~h*lobNCX0PB6SC>@t!v#r_EJEy{_ONx6=_dr>-nvn)Y*{o zvZxPACG8u4PoVz{rnc@{)QthOZ!l}wbw9jib(j5znkLq!OE)8-0x0=g84X8z7jE2I zOmkc@03U)^%voJJC)KoYs2&yN80G5#?vqiRlRBROobHcZn5P=$k86Sr#*HDDnH>Hp z(m36S`{R|bfyb{;2X9Ob%m}Ez>O-j7FLH?S^9dWym$|aY1}QA5uBaCfzPOxY=G1Ut zKAa;iI*<)6YM-L;RoZd1;&OH1@Y3Kr&TQU=Rc7kXX7!g0#o-33ll#`6q$S{68}n`l zn3@faKRgqs8jQot9c6!!3Qa0$Se40IX zp>iwr&53QE%W9!K!Zez0ny)7rfDLPbDoa?+mf&QHTefif56&-ih)^#VU%{5W;h%ryEsR4 z*hM4|Q7tmgqoCq9N38Ei<>B3|WlkYWB1v9vS?SJoW4?M7fe2zU;6n3FGn#aChLmiz z%`VX=v19u>(y5a$Z9!H8txPx9&Krm~zgk>W`PwCue~d@Wp8gDb*D=cIAshmVe-rQq z(yJkYPlX^z-XnZJnr7iP9PwbJ<_6<>ZSDWQJNL`t8$ z9|iOM#y!3as4gpY)UFW5CC4PU&ti)^VDTOw+=oB3s^)h3vztMBWQoXqX>D*Pqi1S= z-!=|D@oT(Urw^If~;io#>c0^qRm3n zeEDuel3jZf=?6`W20=+S3t+oY!>L*gJl8*IVP70kyDA;uktp@L$TPQj3L^-ffc-0Gl&p}JKMN4?e9p|ElMX~K*+X3KUH8ajRuTp)D^lu8Fh%>ITB6 zr($N|^l9C3!~5g$ne$Rp@pkLGsXiwp z$ygmSxt z__P$f8@QhvrDRRvhr*F0%+HLeI9C&vZ_JBY7sv6=sq{}+{=YB;|804Jmof)>Vh<<~ zuk5#lhqDuT?T!-ac-8=DZb_NVTL%VOSn{S=xtu-v^ABVlmb0yaj{t2Zsi-^W<_Thv zPI2S#5#!}8MzkUOq=|-wgWLjn8HG(G|Ll(?DZBEoKh)yVW-Le<4X&Lpw5Ko!hH5r<(rN2%uOol`cwzY^MrG?pKD^<;k&V0C6Zn2 z=7wtzmG-9KL)LagvdjVdB5Re1x?jl~Bu|X80@ao+2@ivWf|w=bn;1cQl3P|xrNLeG z+f-xh4_DY3l{^KVFD6Qkg}*noW+Wct!(J%8@ftpRbF?zrZ8QS0Sn=OY%rbSkw;0g$ zRM^dAh8r9EHP}X*4wu$1m4d8DNx914@Lb%}jP}c|M}Q#|>vz>hyX?aK8wuXp;ea_| zH(x<;MY7{jnR>? z%9M6uX&kD|D;LDf{(d~^mfNL+gb$X*ivuU_sz*T6HIe2ox-6Qby}(_2(FqNU%=4hW zs^pFz)MzR$Gw#fdHEB=w+^rM^aB&le(+I_zgBmJ5wJY8KY|6geX{tY#g6r4z3t>iJ zT+Q@`TFH)&?v~?XV64P@gZpPDy_lp-P9}V_Z92raU zAdZ%Cs&B4-@+l8TK!V*EMTtjCOv$Q7R{Zm4^)ur_LkA553T#P8gxBYVLz$_^xuG%y z$$=o{ozr0KOF^C5pI=8-y>4!M{5nVG)U) zwx0_wdbS$(SB(A~oCGSQF?>44-2w)Fp$$bCP^j<=leZ;5xsg+AAzbzT-XTWX;c;vf z5izQi489j~ubB6WRTf-wALqO*p3IaJYsUmZn&cBxTN&$4jYHT zty6<|2>5$BLHU|Hi?C5wMj9k(TV67es6Br2-5spDAJ{f?K?Blb{2Ggh`u7z9w@Tsc#$ZQwTN^F;UdANJjS2?} z#vB0ZDL3Lyx9#9~ri@FYNmmzKdNggyRVNltN<6Ue{-u)bH#|22T4yZa-d@&GoBBb3 zNm1$Ht(A$t`Woy~)0&>6$x}GNTK=?B~?e zQMHPT&=BYyh4x`300&5VUvOUEy;}2sXg z>_^F3s!Lm8+i=!&OiOwre!1utXDm>whvD@jpwT~QZmX(DGXLwH-h+GbclME?ea1qY zkZq(|x82m_5lha_X{wOn6R=}msB_maDCu}`WUh{4qL~|3AW7#^7U(TF>zrhWl3lsD zdn}#6O<@Lh1Xp=AGv-4f;Qdm&XX(m*DxPBkQv5QKur0j)+dD>tf5*y*+Qf6!0Hjbt zxAr3-%03*{22+%A;~LseAgR6TB-a>q_AAZY6C9bM`Z%)rbdjbxCTt^T*y`xwORrQX zl~nfypYqAz`x9KFcuFh{xbS%_z!v2v3gr6EEM!baKBZ;LWb)wQ+xV z(@XiA+6Hn*@695Alnc#Ls?TwRI0Zn2PXb_9EQx%?B;U5&nM+;p+=BoNr4XKGM5~$? zOi(^O_~Q9(#V#qdY!iV?Q0%Yawy&|L(vC%g5*Bkl`VygQw$A~f!oca*!sGUzO!&Ta zim}4)|51nqS8;QJMBa4q-=@@M2aMa}>$!W}FI#3w$(OPReq!hy#>UwS1K~28hNIwtC^9a2L48#2Zu_|{tX8-lI%J+Ta8vdtH|3I- z*8-oP>IJEPZl@ec)|N7%ypAattT}c1Mltz@Xrk)n=rTvyW;nad8)rlzg6NQGJT~}G zRZVPAHqM-JBOqFHW>9M|Dk@(SG~lU|7DsH6wf$~FM?)Z{s=Ho$WFYFBb(No54U?X; zUoc~qJvFAGQGdAK_i;4>h?CB~cUhHCY8*+A)eV)-rC68L%H}k`E9#wdX^SidQ)hN1 ztmP!L)WVQsD6-0n**=4%_c!N<7x28|2L3fdD7Y`rFqjhey@V%q$e24#E(&yhaYCRGt8&s44cTWQfa+C6T5$o{1NH;LS#Z>mg)$Tq5)`kakn}C9j5C zSPuP@T|+6M!un$#XEWVm|2!jG=%-dwT+BASfn{&NGdKBuuROh#tMa;cl~HR-Os{Sh zS7q}vpz*X*H_5{gJwx_3|FqI$e(^j5ehMlyi_@BkWi+a7fqLQx0}oibny5$8s2SPh zN~&zNi!6($@Wo!tgRI9uMuX5rl`W?esgsingmNw%Wxop@+I=shi@On#4l6pEgP*xJ z>CX&$6crMV4BPPQ4sF%*efZXmmc#wEcD?Z+OxsX#I9p~{KfBUa@^1V65#w9n-VA!& z2d|~#O%FZdIfFR^am-F(VS53Wc@Z$WP`+flZ7DqkZUjZ=^X?zpK+hmO=E6Kz8WRWk<9s-4$Y zzKvuDE|!??33l|adhaBWsrK3z*H70}glFl&LO5&W8CHX2*ITX9D>5Qr+C=1JegDp! z3m4ZK?YSylI4ec%lLab%jX6P-WaO#AKM3$YbQitGd640Weo1l%&FpVd$DzM--=%5I znu%EVq;l!onW*%ve<#fUH9hvv$+LfI{Rj8{5t Date: Fri, 1 Dec 2023 15:19:54 +0300 Subject: [PATCH 4/4] updated artifacts --- site/ethereum-L2/index.html | 1346 ----------------- site/ethereum-L2/overview/index.html | 4 +- site/ethereum-L2/user-guide/index.html | 123 +- site/hacks-and-grants/user-guide/index.html | 2 +- ...ethereum_usage_withdraw_usdc_6_pending.jpg | Bin 0 -> 8930 bytes ...usage_withdraw_usdc_7_metamask_confirm.jpg | Bin 0 -> 43641 bytes ...ereum_usage_withdraw_usdc_8_no_pending.jpg | Bin 0 -> 8066 bytes ...ithdraw_usdc_9_accounts_after_withdraw.jpg | Bin 0 -> 10570 bytes site/integrations/contracts/index.html | 202 ++- site/integrations/l2/index.html | 286 ++-- site/search/search_index.json | 2 +- site/sitemap.xml.gz | Bin 127 -> 127 bytes site/static/checker.abi.json | 250 +++ 13 files changed, 613 insertions(+), 1602 deletions(-) delete mode 100644 site/ethereum-L2/index.html create mode 100644 site/images/ethereum_usage_withdraw_usdc_6_pending.jpg create mode 100644 site/images/ethereum_usage_withdraw_usdc_7_metamask_confirm.jpg create mode 100644 site/images/ethereum_usage_withdraw_usdc_8_no_pending.jpg create mode 100644 site/images/ethereum_usage_withdraw_usdc_9_accounts_after_withdraw.jpg create mode 100644 site/static/checker.abi.json diff --git a/site/ethereum-L2/index.html b/site/ethereum-L2/index.html deleted file mode 100644 index 7b01c6a..0000000 --- a/site/ethereum-L2/index.html +++ /dev/null @@ -1,1346 +0,0 @@ - - - - - - - - - - - - - - - - - - - GOSH Ethereum L2 - GOSH - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - - - - -
- - - - - - - -
- -
- - - - -
-
- - - -
-
-
- - - - - - - -
-
-
- - - - - - - -
-
- - - - -

GOSH Ethereum L2

-

Integration with GOSH L2

-

Introduction

-

Endpoint for use with Ever-SDK

-
network main: https://network.gosh.sh
-
-

The contract Profile (1) is deployed for each user when registering with GOSH.

-
    -
  1. The ABI can be obtained by link
  2. -
-

To get its address, you need to call the method:

-
getProfileAddr(string name) returns(address)
-
-

where:

-

name - user's name

-

from the contract VersionController, (1)

-
    -
  1. -

    is a contract version manager used when upgrading GOSH smart contracts

    -

    address (permanent) -

    0:5cbbbce41fc4290f3d4b085ab30912831b710fa2c681f6ea227d4a22f2b304f5
    -

    -

    The ABI can be obtained by link

    -
  2. -
-

The result is the address of the user's Profile contract.

-

Transfer tokens

-

from GOSH to GOSH

-

Before transferring to another TIP3-wallet, you need to check whether the recipient's TIP3-wallet is already deployed.

-

To do this, you need to call the method getWalletAddress in the RootTokenContract, the recipient's public key is specified.

-

If the recipient's TIP3-wallet is not deployed, you need to call the method transferToRecipient in the TIP3-wallet contract "TONTokenWallet" (1) (from which the transfer will be made).

-
    -
  1. ABI here
  2. -
-
void transferToRecipient(
-    address_opt answer_addr,
-    Tip3Creds   to,
-    uint128     tokens,
-    uint128     evers,
-    uint128     keep_evers,
-    bool        deploy,
-    uint128     return_ownership,
-    opt<cell>   notify_payload
-)
-
-

where:

-

answer_addr - Answer address, (should be null)
-to - Recipient credentials (pubkey + owner (should be null))
-tokens - Amount of tokens to transfer, (should be 0)
-evers - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value
-keep_evers - Evers to keep in destination wallet
-deploy - (should be true) then the contract will send acceptTransfer message with StateInit to also deploy new tip3 wallet (if it doesn't already exist) with the provided recipient public key and recipient internal owner
-return_ownership - Return ownership - to decrease lend ownership for the caller contract (additionally), (should be 0)
-notify_payload - (optional) < Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification, (should be 0)

- - -

As a result, an empty TIP3-wallet will be deployed to the recipient.

-
-

Warning

-

It is important to wait until the contract status changes to "Аctive".

-
-

Then, for transfer the TIP3-tokens to the user, you need to call the method transfer in the TONTokenWallet contract.

-
void transfer(
-    address_opt answer_addr,
-    address     to,
-    uint128     tokens,
-    uint128     evers,
-    uint128     return_ownership,
-    opt<cell>   notify_payload
-)
-
-

where:

-

answer_addr - (опциональный) Answer address (should be null)
-to - Destination TIP3-wallet address
-tokens - Amount of tokens to transfer
-evers - Native funds to process. For internal requests, this value is ignored and processing costs will be taken from attached value
-return_ownership - Return ownership - to decrease lend ownership provided for the caller contract (additionally) (should be 0)
-notify_payload - Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification (should be null)

- - -

from Ethereum to GOSH

-

For transfer ETH to GOSH, you need to call the method deposit in the ELOCK (1) contract, with attached value (the number of ETH, that will be transferred to GOSH).

-
    -
  1. -

    is a GOSH L2 smart contract on Ethereum Blockchain. - It receives deposits from users, manage withdrawals and locks user funds. ELOCK is also counting its total balance, total transaction count and stores root Merkle proofs, withdrawal smart contract code hash, etc. for L2 synchronization.

    -

    address in Ethereum: -

    0x135d03AF576633B0C99FB9F0A0c6Aa9cE8D3C67E
    -

    -

    ABI here

    -
  2. -
-
deposit(uint256 pubkey) public payable
-
-

where:

-

pubkey - the recipient's public key in GOSH

-

Then it is necessary to calculate the address of the user's TIP3-wallet in GOSH and wait the transfer of WETH tokens (wrapped ETH) to the received address.

-
-

example of calling the ELock contract in Ethereum

-
const elock = new data.web3.instance.eth.Contract(
-    ELockAbi.abi,
-    AppConfig.elockaddr,
-)
-
-const edata = elock.methods.deposit(data.summary.to.user.value.pubkey).encodeABI()
-
-const receipt = await data.web3.instance.eth.sendTransaction({
-    from: data.web3.address,
-    to: AppConfig.elockaddr,
-    value: data.web3.instance.utils.toWei(data.summary.from.amount, 'ether'),
-    data: edata,
-    gasLimit: 100000,
-    maxPriorityFeePerGas: 25000,
-})
-
-
-

from GOSH to Ethereum

-

For transfer "WETH" to Ethereum, you need to call the burnTokens method in the user contract TONTokenWallet

-
void burnTokens(uint128 tokens, uint256 to)
-
-

where:

-

tokens - amount WETH, which will be transferred to Ethereum
-to - the address of the recipient's wallet in Ethereum

-

Then wait for the transfer of ETH to the recipient's wallet in Ethereum.

-

Getting the TIP3-wallet address by user name

-

Knowing the address of the user's contract Profile (1) you call the method getAccess() in it.

-
    -
  1. The ABI can be obtained by link
  2. -
-
getAccess() returns(mapping(uint256 => uint8))
-
-

As a result, you get a list of all the user's public keys with their numbers.

-
-

Important

-

It is necessary to take the zeroth pubkey from the list

-
-

Then, using the received user's public key, it will be possible to determine the address of the user's TIP3-wallet

-

Getting the user's TIP3-wallet address using the user's public key

-

To do this, in the RootTokenContract (1)

-
    -
  1. -

    address

    -
    0:1792014440934b9c4024c97221b49c50bd2e2db1426b612ba4c6694b144f5e77
    -
    -

    ABI here

    -
  2. -
-

calling method:

-
address getWalletAddress(uint256 pubkey, address_opt owner)
-
-

where:

-

pubkey - user's public key
-owner - optional parameter, not used

-

Getting a list of incoming messages of the contract

- -
-

Info

-

Using pagination in the SDK

-
-

Get info about TIP3-wallet details

-

For get information about the TIP3-wallet in the contract TONTokenWallet, the getDetails method is called:

-
details_info getDetails()
-
-

and you get the data structure:

-
struct details_info {
-  string            name;              ///< Token name.
-  string            symbol;            ///< Token short symbol.
-  uint8             decimals;          ///< Decimals for ui purposes. ex: balance 100 with decimals 2 will be printed as 1.00.
-  uint128           balance;           ///< Token balance of the wallet.
-  uint128           locked;            ///< Locked token balance of the wallet.
-  uint256           root_pubkey;       ///< Public key of the related RootTokenContract.
-  address           root_address;      ///< Address of the related RootTokenContract.
-  uint256           wallet_pubkey;     ///< Public key of wallet owner (User id for FlexWallet).
-  address_opt       owner_address;     ///< Owner contract address for internal ownership, will be 0:0..0 otherwise.
-  opt<uint256>      lend_pubkey;       ///< Lend ownership pubkey.
-  lend_owners_array lend_owners;       ///< All lend ownership records of the contract.
-  uint128           lend_balance;      ///< Summarized lend balance to all targets.
-                                       ///< Actual active balance will be `balance - lend_balance`.
-  opt<bind_info>    binding;           ///< Flex binding info.
-  uint256           code_hash;         ///< TIP3 wallet code hash to verify other wallets.
-  uint16            code_depth;        ///< TIP3 wallet code depth to verify other wallets.
-  int8              workchain_id;      ///< Workchain id.
-}
-
- - - - - - -
-
- - -
- -
- - - -
-
-
-
- - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/site/ethereum-L2/overview/index.html b/site/ethereum-L2/overview/index.html index 268f36b..4691269 100644 --- a/site/ethereum-L2/overview/index.html +++ b/site/ethereum-L2/overview/index.html @@ -1345,7 +1345,7 @@

Contracts

  • RootTokenContract - is a smart contract on GOSH that manages user withdrawals. It receives TIP-3 transactions, verifies them and adds transactions to the counter index. -Also it deploys the contract TIP3 wallet contract (TONTokenWallet.cpp) and sends wrapped tokens there.

    +Also it deploys the contract TIP-3 wallet contract (TONTokenWallet.cpp) and sends wrapped tokens there.

  • TONTokenWallet - is a custom TIP-3 contract that runs in GOSH Masterchain and in addition to standard functions has burnTokens method. It is called when WETH needs to be transferred to Ethereum Blockchain. Burn is proven to ELOCK contract in order to allow for ETH native token withdrawals.

    @@ -1353,7 +1353,7 @@

    Contracts

    Commission

    for deposit to GOSH

    -

    When transferring assets to GOSH, checker.sol sends the transfer amount and coefficients a and b to the RootTokenContract.cpp and it calculates the commission amount. Then mints the wrapped tokens to the user TIP3-wallet minus the commission. And the commission is sent to the wallet by the commission in GOSH.

    +

    When transferring assets to GOSH, checker.sol sends the transfer amount and coefficients a and b to the RootTokenContract.cpp and it calculates the commission amount. Then mints the wrapped tokens to the user TIP-3 wallet minus the commission. And the commission is sent to the wallet by the commission in GOSH.

    calculated as:

    \(\frac{a * x}{10 000} + b\)

    where:

    diff --git a/site/ethereum-L2/user-guide/index.html b/site/ethereum-L2/user-guide/index.html index 1364602..9a44a94 100644 --- a/site/ethereum-L2/user-guide/index.html +++ b/site/ethereum-L2/user-guide/index.html @@ -790,6 +790,20 @@ Withdraw WETH to Ethereum +
  • + +
  • + + Deposit ERC20 to GOSH + + +
  • + +
  • + + Withdraw ERC20 to Ethereum + +
  • @@ -1061,6 +1075,20 @@ Withdraw WETH to Ethereum + + +
  • + + Deposit ERC20 to GOSH + + +
  • + +
  • + + Withdraw ERC20 to Ethereum + +
  • @@ -1095,7 +1123,7 @@

    Deposit ETH to GOSH

    the "Cross-chain transfer" page will open for you.

    In the Accounts section, click Connect to log into a software cryptocurrency wallet MetaMask

    -

    Choose the amount you want to send

    +

    Enter the amount you want to send

    Note

    The amount must be greater than or equal to 0.01

    @@ -1105,7 +1133,8 @@

    Deposit ETH to GOSH

    The contract has not been formally verified yet. Please do not send a lot!

    -

    Enter the wallet address or select the GOSH username for easy transfer

    +

    Enter the wallet address or GOSH username of the recipient for the transfer. +The Amount field will indicate the transferred amount (minus the commission) that will be credited to the recipient's wallet in GOSH.

    After depositing the GOSH contract on Ethereum, you will receive the corresponding amount of WITH tokens (Wrapper Ethereum tokens) in your GOSH network wallet.

    @@ -1124,7 +1153,7 @@

    Withdraw WETH to Ethereum

    In the From section, select the GOSH blockchain and enter the sender's wallet address or GOSH username along with the amount of WETH tokens you wish to withdraw:

    -

    In theTosection, make sure to choose the Ethereum blockchain network and verify the Receiver's wallet address for accuracy before proceeding. The ETH amount will be automatically calculated.

    +

    In the Tosection, make sure to choose the Ethereum blockchain network and verify the Receiver's wallet address for accuracy before proceeding. The ETH amount will be automatically calculated.

    Please click on the Next button to proceed.

    On the right, in the Summary section, you can see information about the amount of assets received and sent.

    @@ -1136,14 +1165,92 @@

    Withdraw WETH to Ethereum

    -

    Please wait until the process of sending WETH tokens and receiving ETH fully completed

    +

    Please wait until the process of sending WETH tokens and receiving ETH fully completed

    - +

    Deposit ERC20 to GOSH

    +

    To make a transfer ERC20 tokens, go to the Ethereum tab:

    +

    +

    or select this section by clicking on your profile in the right corner:

    +

    +

    Click on:

    +

    +

    the Cross-chain transfer page will open for you.

    +

    Let's look at the token transfer using the example of the USDC.

    +

    In the From section, select the token to transfer to GOSH

    +

    +

    To log into a software cryptocurrency wallet MetaMask, you can either click on Connect wallet or go to the Accounts section and click on Connect.

    +

    +

    Enter the amount you want to send

    +
    +

    Note

    +

    The amount must be greater than or equal to 0.011

    +
    +

    +

    Enter the wallet address or GOSH username of the recipient for the transfer.

    +

    The Amount field will indicate the transferred amount (minus the commission) that will be credited to the recipient's wallet in GOSH.

    +

    The Summary section will display detailed information about the transfer

    +

    +

    +

    And click Next button

    +

    The transfer process has three sub-steps.
    +The first one is to approve tokens, followed by deposit tokens, and finally, waiting for the transfer to be completed.

    +

    Once you click on the Approve button, you'll be authorizing the ELOCK contract to initiate the transfer of the specified amount.

    +

    +

    In the opened MetaMask window, confirm the necessary parameters for the transfer.

    +

    +

    +

    Click on the Deposit button and then check and confirm the transfer parameters in your MetaMask wallet.

    +

    +

    It's important to ensure that the transfer is being made to the ELOCK contract at this step.

    +
    +

    address of the ELOCK contract in Ethereum:

    +
    0x54a858bBD5968Eb755e54C45a3fe5B002bE3c254
    +
    +
    +

    +

    After that, you just need to wait for the transfer to be completed.

    +

    +

    After successful completion of the transfer, you will see a confirmation:

    +

    +

    If you want to view your asset balance, you can find it in the Accounts section. To do this select the relevant token in the "From" tab.

    +

    +

    +

    Withdraw ERC20 to Ethereum

    + + +

    To withdraw ERC20 tokens from GOSH to Ethereum, go to the Ethereum tab on the DAO page +and log into a software cryptocurrency wallet MetaMask

    +

    +

    In the From section, select the asset that you want to withdraw to Ethereum

    +

    +

    The available assets will be displayed in the Accounts section

    +

    +

    Enter the desired number of tokens to withdraw

    +

    +

    The Summary section will display detailed information about the withdraw

    +
    +

    Info

    +

    Tokens are withdrawn every 3 hours

    +
    +

    +

    In the To section, in the Recipient field, you must specify the recipient's Ethereum wallet address.
    +The number of tokens will be calculated automatically.

    +

    Please click on the Next button to proceed.

    +

    +

    The transfer of the ERC20 tokens from GOSH to Ethereum will take some time.

    + + +

    After the transfer process, you will be able to view the list of your assets that have been transferred from GOSH to Ethereum in the Your pending withdrawals section.
    +These assets are now located in Ethereum on the balance ELOCK contract, and you can withdraw them to your wallets by clicking on the Withdraw button.

    +

    +

    Confirm the withdrawal of tokens to your wallet

    +

    +

    Wait for the tokens to arrive on the balance of your Ethereum wallet

    + + +

    diff --git a/site/hacks-and-grants/user-guide/index.html b/site/hacks-and-grants/user-guide/index.html index 8b1a3f5..b3678ba 100644 --- a/site/hacks-and-grants/user-guide/index.html +++ b/site/hacks-and-grants/user-guide/index.html @@ -1239,7 +1239,7 @@

    for participants

    Then, in the form that opens, click Add application form DAO

    -

    and enter the name of your DAO and the names of the repository that you require.

    +

    and enter the name of your DAO and the name of the repository that you require.

    Important

    -

    depositERC20(address token, uint256 value, uint256 pubkey)

    -

    Allows a user to deposit ERC20 tokens into the Elock-contract for locking in it. The corresponding -amount of wrapped tokens in GOSH will be minted for the amount of the blocked funds.
    +

    +

    example of calling the ELock contract in Ethereum

    +
    const elock = new data.web3.instance.eth.Contract(
    +    ELockAbi.abi,
    +    AppConfig.elockaddr,
    +)
    +
    +const edata = elock.methods.deposit(data.summary.to.user.value.pubkey).encodeABI()
    +
    +const receipt = await data.web3.instance.eth.sendTransaction({
    +    from: data.web3.address,
    +    to: AppConfig.elockaddr,
    +    value: data.web3.instance.utils.toWei(data.summary.from.amount, 'ether'),
    +    data: edata,
    +    gasLimit: 100000,
    +    maxPriorityFeePerGas: 25000,
    +})
    +
    +
    +

    depositERC20(address token, uint256 value, uint256 pubkey)

    +

    Allows a user to deposit ERC20 tokens into the Elock-contract for locking in it. The corresponding +amount of wrapped tokens in GOSH will be minted for the amount of the blocked funds.
    Before calling deposit, the specified number of tokens must be available for transfer for the Elock address.

    PARAMETERS:

    -

    token (address) - address of the ERC20 token contract.
    -value (uint256) - deposited number of tokens.
    -pubkey (uint256) - the recipient's public key in GOSH. Used to derive the address of the -user's token wallet for minting wrapped tokens to it.

    -

    getERC20Approvement(address token, address recipient) returns (uint value, uint commission)

    -

    For the specified token and recipient, it returns the number of tokens available for withdrawal -(withdrawERC20) and the commission to be transferred for the withdrawal function.

    +
      +
    • token (address) - address of the ERC20 token contract.
    • +
    • value (uint256) - deposited number of tokens.
    • +
    • pubkey (uint256) - the recipient's public key in GOSH. Used to derive the address of the +user's token wallet for minting wrapped tokens to it.
    • +
    +

    withdrawERC20(address token)

    +

    Requests the withdrawal of the specified tokens for the caller (msg.sender).
    +Tokens must be approved for withdrawal. The commission must be attached to the function call.

    +

    PARAMETERS:

    +
      +
    • token (address) - address of the ERC20 token contract.
    • +
    +

    getERC20Approvement(address token, address recipient) returns (uint value, uint commission)

    +

    For the specified token and recipient, it returns the number of tokens available for withdrawal +(withdrawERC20) and the commission to be transferred for the withdrawal function.

    PARAMETERS:

    -

    token (address) - address of the ERC20 token contract.
    -recipient (address) - the address of the recipient of the withdrawed tokens

    +
      +
    • token (address) - address of the ERC20 token contract.
    • +
    • recipient (address) - the address of the recipient of the withdrawed tokens
    • +

    RETURNS:

    value (uint256) - the number of tokens approved for withdrawal.
    commission (uint256) - the amount of commission for withdrawal.

    -

    withdrawERC20(address token)

    -

    Requests the withdrawal of the specified tokens for the caller (msg.sender). Tokens must be -approved for withdrawal. The commission must be attached to the function call.

    -

    PARAMETERS:

    -

    token (address) - address of the ERC20 token contract.

    -

    getTokenRoots()

    -

    This function returns an array of addresses where each address represents a supported ERC 20 token in GOSH Ethereum L2.

    + + +

    getTokenRoots() returns (address[] memory roots)

    +

    The function returns an array of addresses where each address represents a supported ERC20 token in GOSH Ethereum L2.

    RETURNS:

    -

    roots (address[]) - list of addresses of ERС20 tokens

    - - +

    [ABI]

    +
    +

    Info

    +

    address in GOSH:

    +
    0:17eb654c5fca0027d47a4564139df71bec46b2277d71f6674ecd9dc55e52fb78
    +
    +
    +

    getRootAddr(RootData data) returns(address)

    + +

    The function returns TIP-3 root contract address

    +

    PARAMETERS

    +
      +
    • RootData.name (string) - ERC20 token name;
    • +
    • RootData.symbol (string) - ERC20 token symbol;
    • +
    • RootData.decimals (uint8) - ERC20 token decimals;
    • +
    • RootData.ethroot (uint256)- ERC20 token address;
    • +
    +

    RETURNS

    +

    address TIP-3 root for wrapped ERС20 token in GOSH

    + - +RETURN TYPE -->

    RootTokenContract

    is a smart contract on GOSH that manages user withdrawals. It receives TIP-3 transactions, verifies them and adds transactions to the counter index.
    @@ -1253,11 +1333,11 @@

    RootTokenContract

    Info

    address for TIP-3 token ETH:

    -
    0:d6182377a82e7f159f1b9995b2582ac933791599a4da9d72cc2c7812f056592d
    +
    0:d6182377a82e7f159f1b9995b2582ac933791599a4da9d72cc2c7812f056592d
     

    getWalletAddress(uint256 pubkey, address_opt owner)

    -

    The function for getting the user's TIP-3 wallet address

    +

    The function for getting the user's TIP-3 wallet address

    PARAMETERS:

    • pubkey - user's public key
    • @@ -1281,8 +1361,8 @@

      TONTokenWallet

      bool deploy,
      uint128 return_ownership,
      opt notify_payload
      -)

      -

      The function for deploying empty TIP-3 wallet to another user

      +)

      +

      The function for deploying empty TIP-3 wallet to another user

      PARAMETERS:

      • answer_addr - Answer address, (should be null)
      • @@ -1308,6 +1388,7 @@

        TONTokenWallet

        uint128 return_ownership,
        opt notify_payload
        )

        +

        The function transfers the TIP3-tokens between TIP-3 user wallets.

        PARAMETERS:

        • answer_addr - (optional) Answer address (should be null)
        • @@ -1317,17 +1398,18 @@

          TONTokenWallet

        • return_ownership - Return ownership - to decrease lend ownership provided for the caller contract (additionally) (should be 0)
        • notify_payload - Payload (arbitrary cell) - if specified, will be transmitted into dest owner's notification (should be null)
        -

        For transfer "WETH" to Ethereum, you need to call the burnTokens method in the user contract TONTokenWallet

        -
        void burnTokens(uint128 tokens, uint256 to)
        -
        -

        where:

        -

        tokens - amount WETH, which will be transferred to Ethereum
        -to - the address of the recipient's wallet in Ethereum

        -

        Then wait for the transfer of ETH to the recipient's wallet in Ethereum.

        -

        For get information about the TIP-3 wallet in the contract TONTokenWallet, the getDetails method is called:

        -
        details_info getDetails()
        -
        -

        and you get the data structure:

        +

        burnTokens(uint128 tokens, uint256 to)

        +

        The function burns tokens for transfer to Ethereum

        + +

        PARAMETERS:

        +
          +
        • tokens - amount WETH, which will be transferred to Ethereum
        • +
        • to - the address of the recipient's wallet in Ethereum
        • +
        +

        getDetails()

        +

        The function returns information about the TIP-3 wallet

        +

        RETURNS:

        +

        the data structure:

        struct details_info {
           string            name;           // Token name.
           string            symbol;         // Token short symbol.
        @@ -1348,6 +1430,8 @@ 

        TONTokenWallet

        int8 workchain_id; // Workchain id. }
        + + diff --git a/site/integrations/l2/index.html b/site/integrations/l2/index.html index 941b072..6744b45 100644 --- a/site/integrations/l2/index.html +++ b/site/integrations/l2/index.html @@ -904,11 +904,11 @@
      • - - Getting the user's TIP3-wallet address: + + Getting the user's TIP-3 wallet address: -