Skip to content

Commit

Permalink
Merge pull request #3 from Wire-Network/edits-1
Browse files Browse the repository at this point in the history
Added a few articles
  • Loading branch information
bearcubsvet authored Nov 18, 2024
2 parents a4e7d4c + ea67e15 commit feb9462
Show file tree
Hide file tree
Showing 12 changed files with 934 additions and 4 deletions.
2 changes: 1 addition & 1 deletion docs/api-reference/system-contracts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Not all system accounts contain a system contract, but each system account has i
|sysio.wrap|Yes|It contains the `sysio.wrap` contract.|Simplifies block producer superuser actions by making them more readable and easier to audit.|
|sysio.token|No|It contains the `sysio.token` contract.|Defines the structures and actions allowing users to create, issue, and manage tokens on Wire based blockchains.|
|sysio.names|No|No|The account which is holding funds from namespace auctions.|
<!-- |sysio.bpay|No|No|The account that pays the block producers for producing blocks. It assigns 0.25% of the inflation based on the amount of blocks a block producer created in the last 24 hours.| -->
|sysio.bpay|No|No|The account that pays the block producers for producing blocks. It assigns 0.25% of the inflation based on the amount of blocks a block producer created in the last 24 hours.|
|sysio.prods|No|No|The account representing the union of all current active block producers permissions.|
|sysio.ram|No|No|The account that keeps track of the SYS balances based on users actions of buying or selling RAM.|
|sysio.ramfee|No|No|The account that keeps track of the fees collected from users RAM trading actions: 0.5% from the value of each trade goes into this account.|
Expand Down
59 changes: 59 additions & 0 deletions docs/introduction/deposits.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Deposits

Before users can transact with tokens on the Wire network, their tokens must be ‘shadowed’ from the origin chain. Shadowing, also known as token wrapping, is creating a digital representation of a token from one blockchain on another. For example, Ethereum (ETH) on the Wire Network is represented as Wrapped Ethereum (WETH) to enable its use within that specific ecosystem.
The deposit process involves *transferring the ownership of the tokens to a special escrow contract*, where they are held until the eventual recipient decides to claim them. This contract serves as the foundational mechanism for managing the *deposit root*, which is essential for tracking and verifying the deposits within the network.

## Deposit Root

The deposit root is a dynamic cryptographic hash used as a cumulative verification point within the escrow account on the external chain.

- **Initialization and Update**: The deposit root is initialized with a deterministic value. Each transaction updates this root by hashing the transaction details with the existing deposit root value and incorporating a sequential identifier to ensure traceability.
- **Proof Construction**: This updating mechanism facilitates the creation of a verifiable proof that includes the initial deposit root value, detailed transaction information, and all subsequent transaction hashes.
Below is a detailed diagram of the deposit flow of operations:

```mermaid
sequenceDiagram
autonumber
participant User
participant External Chain
participant Validator
participant Wire Network
User->>Wire Network: Intent to deposit
rect rgb(255, 210, 128)
User -> Wire Network: amount/kind of token to be deposited <br/> the current deposit root on the origin chain <br/> the user's account on the origin chain <br/> the next sequential nonce for that user's account (if applicable)
end
%% alt Proposed deposit is valid
Validator->>External Chain: Verifies
Validator->>Validator: wait for acceptance
Validator->>Wire Network: Acceptance
User->>External Chain: Perform deposit
External Chain->>External Chain: on_received()
External Chain->>External Chain: Hash transaction details
Note over External Chain,External Chain: - The sender (depositor)<br/>- contract address for the token<br/>- Token ID (for ERC 721 & 1155)<br/>- Amount (for ERC 20 & 1155)
External Chain->>External Chain: Hash with existing deposit root
External Chain->>External Chain: Take 32 LSB from existing root<br/>Increment and update new deposit root
External Chain->>External Chain: Write new deposit root to contract state
External Chain-->>User: event with new deposit root
User->>Wire Network: Perform 'report' transaction
rect rgb(191, 223, 255)
User -> Wire Network: Signed Transaction, deposit root, and chained roots
end
Wire Network->>Validator: Send report transaction
Validator->>External Chain: Verify deposit
External Chain-->>Validator: Is deposit valid?
alt Deposit is valid
Validator->>Wire Network: Emit ratification
else Deposit not performed
alt Nonce used
Validator->>Wire Network: Write denial with transaction data
else Nonce not used
Validator->>External Chain: Perform signed transaction on external chain
Validator->>Wire Network: Emit ratification
External Chain-->>Validator: Transaction executed
Validator->>Wire Network: Write denial showing chain <br/> from proposal deposit root not including deposit
end
end
```
12 changes: 12 additions & 0 deletions docs/introduction/wns-trx-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
id: wns-trx-flow
slug: /introduction/wns-trx-flow
---
# WNS Transaction Flow

Below is an example of a diagram that visualizes deposit, swap and withdrawal for two hypothetical users - Bob and Alice.
Bob possesses $100 of ETH on Ethereum and Alice has $100 of SOL on Solana, both stored in their respective UPAP-enabled wallets. Upon successful deposits, Bob and Alice have respectively their wrapped tokens WETH and WSOL.
If they wish to swap these assets, the WNS system can perform an atomic swap on the Wire blockchain via the swap contract.
Either party can initiate this transaction using their UPAP-enabled wallet. For instance, Bob proposes a transaction to exchange his $100 in ETH for Alice's $100 in SOL. Alice then finalizes the transaction in her UPAP-enabled wallet, resulting in the updated ownership being confirmed and reflected in the WNS system.
Bob and Alice then decide to withdraw their assets - Bob would now have $100 of SOL in his Solana wallet, and Alice - $100 of ETH in her ETH.
![wns-trx-flow](../../static/img/wns-2.png)
81 changes: 81 additions & 0 deletions docs/smart-contract-development/accounts-permissions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Accounts & Permissions

A Wire account is a digital entity on the blockchain that identifies a participant, which can be an individual or a group. An account also represents the smart contract actors that send and receive actions to and from other accounts on the blockchain. Actions, which are the fundamental units of execution, are always encapsulated within transactions, allowing for one or more atomic actions to be grouped together.

## Public & Private Keys

Every Wire account is ultimately controlled by a key pair (public and corresponding private key). While the public key is used to identify the account on the blockchain and can be publicly known, the private key which is used to sign each transaction must be kept secret at all times.

If you lose your private key, you will lose access to your account and all of its assets, smart contracts, and any other data associated with it.

## Permissions

Each account has a set of hierarchical permissions that control what that account can do and how actions are authorized. By default, each account comes with two base permissions - `owner` and `active`. These two permissions are mandatory and they cannot be removed. A permission can only modify its own controls (keys or accounts) or those of its children, but **never those of its parent.**

### Owner Permission

The `owner` permission is the highest in an account’s hierarchy, usually reserved for recovery scenarios when lower permissions are compromised. It can perform any action that lower permissions can, but keys for this permission are generally stored offline in cold storage to avoid misuse.

### Active Permission

The `active` permission is the default for all actions, sitting just below the `owner` permission. It handles typical account activities, but cannot alter owner keys. Custom permissions usually are created under the `active` and linked to specific contracts or actions.

![account-hierarchy](../../static/img/account-hierarchy.png).

A permission is linked to and controlled by either a **public key** or another **account**. This allows for the creation of complex account control structures, where multiple parties may control a single account while still having full autonomy over their own account's security.

See the diagram below as an example, where the account `jack@active` is controlled by both `nick@active` and `daniel@active`, and on the other hand, `daniel@active` is also controlled by `katey@active`.

![account-complex-structure](../../static/img/accounts-complex-structure.png)

### Permission Mapping

It is possible to create custom permissions scoped to specific actions within a designated contract, also known as *permission mapping*. That permission will then only ever be able to interact with the contract action you specified. Such setup allows for very granular access permissions across accounts and hierarchical structures tailored to your needs.

![account-custom-permissions](../../static/img/accounts-custom-permissions.png)

### Permission Evaluation

When determining whether an action is authorized to be executed, the wire-sysio software:

- first checks whether the signatures provided in the transaction are valid.
- then it proceeds to check the authorization of all the actions included in the transaction. This is where permissions are evaluated. If any action fails to be authorized, the transaction fails.

#### Authority Table

Each account's permission can be linked to an `authority` table used to determine whether a given action authorization can be satisfied. The authority table contains the target permission name and threshold, the factors and their weights, all of which are used in the evaluation to determine whether the authorization can be satisfied. The permission threshold is the target numerical value that must be reached to satisfy the action authorization (see `authority` schema below).

#### `authority` schema

Name | Type | Description
-|-|-
`threshold` | `uint32_t` | threshold value to satisfy authorization
`keys` | array of `key_weight` | list of public keys and weights
`accounts` | array of `permission_level_weight` | list of `account@permission` levels and weights
`waits` | array of `wait_weight` | list of time waits and weights

The `key_weight` type contains the actor's public key and associated weight. The `permission_level_weight` type consists of the actor's `account@permission` level and associated weight. The `wait_weight` contains the time wait and associated weight (used to satisfy action authorizations in delayed user transactions. All of these types allow to define lists of authority factors that are used for satisfaction of action authorizations.

#### Authority Factors

Every authority table linked to a given permission lists potential factors explicitly used in the evaluation of the action authorization. A factor type can be one of the following:

- Actor's account name and permission level
- Actor's public key
- Time wait

The potential actors who may execute the action are specified by either **public key** or **account name** in the `authority` table. Time waits are special factors which are satisfied by publishing a transaction with a delay in excess of the defined time. These carry weights as well that may contribute to satisfy the threshold.

#### Authority Threshold

Authorization over a given action is determined by satisfying all explicit authorizations specified in the action instance. Those are in turn individually satisfied by evaluating each *factor* (account, public key, wait) for satisfaction and summing the weights of those that are satisfied. If the sum equals or exceeds the weight threshold, the action is authorized.

**Example:**

The authority table for `jack`'s `release-code` named permission is shown in the diagram below. In order to authorize an action under that permission, a threshold of 2 must be reached.

Since both `katey@active` and `kyle@active` factors have a weight of 2, *either one can satisfy the action authorization*. This means that either `katey` or `kyle` with a permission level of `active` or higher can independently execute any action under `jack`'s `release-code` permission.

Alternatively, it would require two acounts each with weight of 1 to satisfy the action authorization - in this case account with public key `SYS7Hnv4iBfcw2...` and `nick@active`.

![account-weights-example](../../static/img/weights-example.png)
160 changes: 160 additions & 0 deletions docs/smart-contract-development/actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# Actions

An action is a specific function or operation that can be executed on a smart contract. Smart contracts are self-executing programs with predefined rules and conditions, and actions are the entry points that allow accounts or other contracts to interact with them.

## Defining an Action in Wire Smart Contracts

- **Action with specified return type**

If you want the action to have a return type, you must use the `[[sysio::action]]` syntax followed by the desired return type.

```cpp
[[sysio::action]] std::string myaction() {
// ...
return "Hello";
}
```

:::warning
Return values are only usable **outside the blockchain** and cannot currently be used within Wire for smart contract composability.
:::

- **Simple Action**: A shorthand method that always returns `void`

If you don’t need to specify the return type, you can use the `ACTION` macro, which is a shorthand for `[[sysio::action]] void`.

```cpp
ACTION myaction() {
//...
}
```

## Inline Actions

Inline actions allow a contract to call an action of another contract from within its own code. This is useful for building functionality on top of existing contracts.

Let’s demonstrate this with two simple contracts: `seller` and `buyer`. In this example we will define an inline action `notifysale` on `seller` contract which would be called within `buyitem` action on the `buyer` contract.

```cpp
#include <sysio/sysio.hpp>
using namespace sysio;

#include <sysio/sysio.hpp>
#include <sysio/asset.hpp>
using namespace sysio;

CONTRACT seller : public contract {
public:
using contract::contract;

ACTION notifysale(name buyer_name, uint64_t item_id, asset price) {
require_auth(get_self()); // Only the seller contract can call this action

// ...business logic to process the sale

print("Item ", item_id, " sold to ", buyer_name, " for ", price);
}
};
```

```cpp
#include <sysio/sysio.hpp>
#include <sysio/asset.hpp>
using namespace sysio;

CONTRACT buyer : public contract {
public:
using contract::contract;

ACTION buyitem(name buyer_account, name seller_account, uint64_t item_id, asset price) {
require_auth(buyer_account);

// ...business logic

// highlight-start
// Notify seller of the purchase
action(
permission_level{get_self(), "active"_n},
seller_account, // Seller's contract account
"notifysale"_n, // Action on the seller contract
std::make_tuple(buyer_account, item_id)
).send();
// highlight-end
print("Buyer: Purchased item ", item_id, " from ", seller_account);
}
};
```

### Inline Action Constructor

The action constructor takes four arguments:

```txt
action(
<permission_level>,
<contract>,
<action>,
<data>
).send();
```

#### Parameters of the `action` constructor

| Parameter | Type | Description |
|--------------------|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `permission_level` | `permission_level` | Specifies who is authorizing the action and at what permission level. Constructed using `{actor, permission}`. |
| `contract` | `name` | The account name where the target action is deployed. This is the contract you are calling. |
| `action_name` | `name` | The name of the action you want to invoke on the target contract. |
| `data` | `std::tuple` | The data to be passed to the action, packaged as a tuple containing the arguments required by the target action. Use `std::make_tuple` to create it. |

:::success[TIP]

- To convert a string into a `name` type for parameters like `contract` and `action_name`, use the `name()` function.

- Use `std::make_tuple()` to package multiple arguments together into the `data` parameter that matches the target action’s expected structure.

- `std::make_tuple(arg1, arg2, arg3, ...);`

:::

##### Setting Up the Permission Level

The `permission_level` argument specifies the permission level under which the action will be executed. It consists of two components:

```cpp
permission_level(
account,
permission
)
```

- `account` (name type): The account authorizing the action.
- `permission` (name type): The permission level of the account (e.g., "active"_n).

:::danger[IMPORTANT]
When you call an inline action, **the contract initiating the call becomes the new sender**. For security reasons, the original authorization is **not** passed to the called contract. This prevents the called contract from performing actions on behalf of the original sender, such as transferring tokens without explicit permission.
:::

###### Setting Up Special Permission (`eosio.code`)

To allow your contract to call inline actions on other contracts,**you need to grant it the special `eosio.code` permission**. Without this permission, your contract cannot execute actions on other contracts.

This permission is on the `active` permission level so that it allows other contracts using the `require_auth()` to verify that your contract has the authority to perform the action.

###### How to Add the `eosio.code` Permission

Add the `eosio.code` permission to the contract account `active` permission to enable calling inline actions by the contract account's `active` permission.

```sh
clio set account permission yourcontract active --add-code -p yourcontract@active
```

Example of post-update permission's hierarchy:

```txt
owner
• YOUR_PUBLIC_KEY
↳ active
• YOUR_PUBLIC_KEY
• <[email protected]>
```
Loading

0 comments on commit feb9462

Please sign in to comment.