Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ members = [
"contracts/feature-tests/composability/forwarder-legacy/meta",
"contracts/feature-tests/composability/forwarder-blind",
"contracts/feature-tests/composability/forwarder-blind/meta",
"contracts/feature-tests/composability/forwarder-blind/dex-interactor",
"contracts/feature-tests/composability/forwarder-raw",
"contracts/feature-tests/composability/forwarder-raw/meta",
"contracts/feature-tests/composability/local-esdt-and-nft",
Expand Down
8 changes: 8 additions & 0 deletions contracts/core/wegld-swap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@
The EGLD-WEGLD swap contract mints and distributes the WEGLD token, in equal amount to the amount of EGLD locked in the contract.

There are such contracts deployed in each shard.

## Mainnet Deployments

| Shard | Address |
|-------|---------|
| Shard 0 | [erd1qqqqqqqqqqqqqpgqvc7gdl0p4s97guh498wgz75k8sav6sjfjlwqh679jy](https://explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqvc7gdl0p4s97guh498wgz75k8sav6sjfjlwqh679jy) |
| Shard 1 | [erd1qqqqqqqqqqqqqpgqhe8t5jewej70zupmh44jurgn29psua5l2jps3ntjj3](https://explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqhe8t5jewej70zupmh44jurgn29psua5l2jps3ntjj3) |
| Shard 2 | [erd1qqqqqqqqqqqqqpgqmuk0q2saj0mgutxm4teywre6dl8wqf58xamqdrukln](https://explorer.multiversx.com/accounts/erd1qqqqqqqqqqqqqpgqmuk0q2saj0mgutxm4teywre6dl8wqf58xamqdrukln) |
3 changes: 3 additions & 0 deletions contracts/core/wegld-swap/sc-config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[[proxy]]
path = "../../examples/multisig/interact/src/wegld_proxy.rs"

[[proxy]]
path = "../../feature-tests/composability/forwarder-blind/dex-interactor/src/proxies/wegld_proxy.rs"
12 changes: 12 additions & 0 deletions contracts/feature-tests/composability/forwarder-blind/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ Uses the async v2 mechanism (`register_promise`).

---

## Top-level endpoints

### `drain`
`#[only_owner]`
Drains the contract's full balance of a given token (identified by `token` and `token_nonce`) to the caller. Used to recover funds left in the contract after forwarding operations.

---

## Scenarios

Scenario tests are located in [`../scenarios/`](../scenarios) and cover:
Expand All @@ -98,6 +106,10 @@ Scenario tests are located in [`../scenarios/`](../scenarios) and cover:
| `forw_blind_sync_fallible_reject_egld` | Vault rejects payment; original EGLD returned to caller via sync fallible error path |
| `forw_blind_sync_fallible_retrieve_egld` | Retrieve EGLD from vault back to caller via sync fallible back-transfers |
| `forw_blind_sync_fallible_retrieve_esdt` | Retrieve ESDT from vault back to caller via sync fallible back-transfers |
| `forw_blind_transf_exec_accept_egld` | Send EGLD to vault via transfer-execute (fire-and-forget) |
| `forw_blind_deploy` | Deploy a new contract via `blind_deploy` |
| `forw_blind_upgrade` | Upgrade an existing contract via `blind_upgrade_from_source` |
| `forw_blind_drain` | Drain EGLD, ESDT, and NFT balances from the contract via `drain` |
| `forw_blind_transf_exec_accept_egld` | Send EGLD to vault via transfer-execute |
| `forw_blind_deploy` | Deploy a new contract |
| `forw_blind_upgrade` | Upgrade an existing contract |
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Pem files are used for interactions, but shouldn't be committed
*.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "forwarder-blind-dex-interactor"
version = "0.0.0"
authors = ["MultiversX <contact@multiversx.com>"]
edition = "2024"
publish = false

[[bin]]
name = "forwarder-blind-dex-interactor"
path = "src/interactor_main.rs"

[lib]
path = "src/interact.rs"

[dependencies.forwarder-blind]
path = ".."

[dependencies.multiversx-sc-snippets]
version = "0.65.0"
path = "../../../../../framework/snippets"

[dependencies.multiversx-sc]
version = "0.65.0"
path = "../../../../../framework/base"

[dependencies]
clap = { version = "4.4", features = ["derive"] }
serde = { version = "1.0", features = ["derive"] }
toml = "1.0"
tokio = { version = "1.24" }

[features]
chain-simulator-tests = []
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# forwarder-blind DEX interactor

CLI interactor for the `forwarder-blind` contract that demonstrates calling into a DEX pair
using every available call type.

## Running

```bash
cargo run -- <COMMAND> [OPTIONS]
```

---

## Commands

### `deploy`

Deploy a new instance of the forwarder-blind contract.

```bash
cargo run -- deploy
```

---

### `wrap`

Wrap EGLD into WEGLD via the WEGLD swap contract.

```bash
cargo run -- wrap -a <AMOUNT>
```

| Flag | Description |
|------|-------------|
| `-a`, `--amount` | Amount of EGLD to wrap, in denomination (1 EGLD = 10^18) |

---

### `swap1` — Swap WEGLD → USDC

```bash
cargo run -- swap1 <METHOD> [OPTIONS]
```

#### Methods

| Method | Description |
|--------|-------------|
| `direct` | Swap directly on the DEX pair |
| `sync` | Swap via forwarder-blind using `blind_sync` |
| `async1` | Swap via forwarder-blind using `blind_async_v1` |
| `async2` | Swap via forwarder-blind using `blind_async_v2` |
| `te` | Swap via forwarder-blind using `blind_transf_exec` |

#### Options (all methods)

| Flag | Description | Default |
|------|-------------|---------|
| `-a`, `--wegld-amount` | Amount of WEGLD to sell | *(required)* |
| `-m`, `--usdc-amount-min` | Minimum USDC to accept (slippage guard) | `1` |

#### Examples

```bash
# Direct swap
cargo run -- swap1 direct -a 1000000000000000000

# Via blind_sync
cargo run -- swap1 sync -a 1000000000000000000 -m 1000

# Via blind_async_v1
cargo run -- swap1 async1 -a 1000000000000000000

# Via blind_async_v2
cargo run -- swap1 async2 -a 1000000000000000000

# Via blind_transf_exec
cargo run -- swap1 te -a 1000000000000000000
```

---

### `swap2` — Swap USDC → WEGLD

```bash
cargo run -- swap2 <METHOD> [OPTIONS]
```

#### Methods

| Method | Description |
|--------|-------------|
| `direct` | Swap directly on the DEX pair |
| `sync` | Swap via forwarder-blind using `blind_sync` |
| `async1` | Swap via forwarder-blind using `blind_async_v1` |
| `async2` | Swap via forwarder-blind using `blind_async_v2` |
| `te` | Swap via forwarder-blind using `blind_transf_exec` |

#### Options (all methods)

| Flag | Description | Default |
|------|-------------|---------|
| `-a`, `--usdc-amount` | Amount of USDC to sell | *(required)* |
| `-m`, `--wegld-amount-min` | Minimum WEGLD to accept (slippage guard) | `1` |

#### Examples

```bash
# Direct swap
cargo run -- swap2 direct -a 40000

# Via blind_sync
cargo run -- swap2 sync -a 40000 -m 1

# Via blind_async_v1
cargo run -- swap2 async1 -a 40000

# Via blind_async_v2
cargo run -- swap2 async2 -a 40000

# Via blind_transf_exec
cargo run -- swap2 te -a 40000
```

---

### `get-rate`

Get the approximate WEGLD → USDC conversion rate.

```bash
cargo run -- get-rate [-a <WEGLD_AMOUNT>]
```

| Flag | Description | Default |
|------|-------------|---------|
| `-a`, `--wegld-amount` | Amount of WEGLD to price | `1000000000000000000` (1 EGLD) |

---

### `get-liquidity`

Show the liquidity reserves in the WEGLD/USDC pair.

```bash
cargo run -- get-liquidity
```

---

### `drain`

Drain all WEGLD and USDC balances held by the deployed forwarder-blind contract back to the owner.
Useful to recover tokens left in the contract after transfer-execute swaps (which have no callback).

```bash
cargo run -- drain
```

---

## Configuration

The interactor reads `config.toml` from the current directory. Example:

```toml
chain_type = 'real'
gateway_uri = 'https://gateway.battleofnodes.com'
wegld_address = 'erd1...' # WEGLD swap contract
pair_address = 'erd1...' # WEGLD/USDC DEX pair contract
wegld_token_id = 'WEGLD-bd4d79'
usdc_token_id = 'USDC-c76f1f'
```

| Field | Description |
|-------|-------------|
| `chain_type` | `real` for mainnet/testnet or `simulator` for the chain simulator |
| `gateway_uri` | Gateway endpoint URL |
| `wegld_address` | Address of the WEGLD swap contract |
| `pair_address` | Address of the WEGLD/USDC DEX pair contract |
| `wegld_token_id` | ESDT identifier for WEGLD |
| `usdc_token_id` | ESDT identifier for USDC |

The deployed contract address is persisted automatically in `state.toml` after a successful `deploy`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
chain_type = 'real'
gateway_uri = 'https://gateway.battleofnodes.com'
wegld_address = 'erd1qqqqqqqqqqqqqpgqmuk0q2saj0mgutxm4teywre6dl8wqf58xamqdrukln'
pair_address = 'erd1qqqqqqqqqqqqqpgqeel2kumf0r8ffyhth7pqdujjat9nx0862jpsg2pqaq'
wegld_token_id = 'WEGLD-bd4d79'
usdc_token_id = 'USDC-c76f1f'
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use multiversx_sc_snippets::imports::Bech32Address;
use serde::Deserialize;
use std::io::Read;

/// Config file
const CONFIG_FILE: &str = "config.toml";

#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ChainType {
Real,
Simulator,
}

/// Contract Interact configuration
#[derive(Debug, Deserialize)]
pub struct Config {
pub gateway_uri: String,
pub chain_type: ChainType,
pub wegld_address: Bech32Address,
pub pair_address: Bech32Address,
pub wegld_token_id: String,
pub usdc_token_id: String,
}

impl Config {
// Deserializes config from file
pub fn load_config() -> Self {
let mut file = std::fs::File::open(CONFIG_FILE).unwrap();
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
toml::from_str(&content).unwrap()
}

// Returns the gateway URI
pub fn gateway_uri(&self) -> &str {
&self.gateway_uri
}

// Returns if chain type is chain simulator
pub fn use_chain_simulator(&self) -> bool {
match self.chain_type {
ChainType::Real => false,
ChainType::Simulator => true,
}
}
}
Loading
Loading