Skip to content

Commit

Permalink
Add support for OUSD and OETH contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
shahthepro committed Dec 25, 2023
1 parent 1d7bff3 commit d2e7c87
Show file tree
Hide file tree
Showing 1,020 changed files with 3,808 additions and 420 deletions.
Binary file added .DS_Store
Binary file not shown.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
# limitations under the License.
# ****************************************************************************

# EDIT THIS: Application name
APPNAME = "PluginBoilerplate"
# Application name
APPNAME = "Origin"

# Application version
APPVERSION_M = 1
Expand Down
55 changes: 39 additions & 16 deletions PLUGIN_SPECIFICATION.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,47 @@
# Technical Specification

> **Warning**
This documentation is a template and shall be updated.

## About

This documentation describes the smart contracts and functions supported by the boilerplate plugin.
This documentation describes the smart contracts and functions supported by the Origin plugin for Ledger Live.

## Smart Contracts

Smart contracts covered by the plugin shall be described here:

| Network | Version | Smart Contract | Address |
| ---- | --- | ---- | --- |
| NetworkName | VX | ContractName | `0x0000000000000000000000000000000000000000` |

## Functions

For the smart contracts implemented, the functions covered by the plugin shall be described here:

|Contract | Function | Selector | Displayed Parameters |
| --- | --- | --- | --- |
|ContractName | FunctionName | `0x00000000`| <table><tbody> <tr><td><code>type ParameterName</code></td></tr> </tbody></table> |
| Contract | Address |
| -------------------- | -------------------------------------------- |
| OETH Zapper | `0x9858e47bcbbe6fbac040519b02d7cd4b2c470c66` |
| OETH Vault | `0x39254033945aa2e4809cc2977e7087bee48bd7ab` |
| ETH/OETH Curve Pool | `0x94b17476a93b3262d87b9a326965d1e91f9c13e7` |
| Curve Router | `0x99a58482bd75cbab83b27ec03ca68ff489b5788f` |
| OUSD Vault | `0xe75d77b1865ae93c7eaa3040b038d7aa7bc02f70` |
| OUSD Flipper | `0xcecad69d7d4ed6d52efcfa028af8732f27e08f70` |
| UniswapV3 Router | `0xe592427a0aece92de3edee1f18e0157c05861564` |
| OUSD/3CRV Curve Pool | `0x87650d7bbfc3a9f10587d7778206671719d9910d` |
| ETH/OETH Curve Pool | `0x94b17476a93b3262d87b9a326965d1e91f9c13e7` |
| Curve Router | `0x99a58482bd75cbab83b27ec03ca68ff489b5788f` |
| OUSD Vault | `0xe75d77b1865ae93c7eaa3040b038d7aa7bc02f70` |
| OUSD Flipper | `0xcecad69d7d4ed6d52efcfa028af8732f27e08f70` |
| WOETH | `0xdcee70654261af21c44c093c300ed3bb97b78192` |
| WOUSD | `0xd2af830e8cbdfed6cc11bab697bb25496ed6fa62` |

## Functions implemented:

| Function | Selector | Displayed Parameters |
| ------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| deposit | 0xd0e30db0 | <table> <tbody> </tbody> </table> |
| depositSFRXETH | 0xd443e97d | <table> <tbody> <tr> <td><code>uint256 amount</code></td></tr> <tr><td><code>uint256 minOETH</code></td></tr> </tbody> </table> |
| mint | 0x156e29f6 | <table> <tbody> <tr><td><code>address \_asset</code></td></tr> <tr><td><code>,uint256 \_amount</code></td></tr> <tr><td><code>uint256 \_minimumOusdAmount</code></td></tr> </tbody> </table> |
| redeem | 0x7cbc2373 | <table> <tbody> <tr><td><code>uint256 \_amount</code></td></tr> <tr><td><code>uint256 \_minimumUnitAmount</code></td></tr> </tbody> </table> |
| exchange | 0x3df02124 | <table> <tbody> <tr><td><code>int128 i</code></td></tr> <tr><td><code>int128 j</code></td></tr> <tr><td><code>uint256 \_dx</code></td></tr> <tr><td><code>uint256 \_min_dy</code></td></tr> </tbody> </table> |
| exchange_underlying | 0xa6417ed6 | <table> <tbody> <tr><td><code>int128 i</code></td></tr> <tr><td><code>int128 j</code></td></tr> <tr><td><code>uint256 \_dx</code></td></tr> <tr><td><code>uint256 \_min_dy</code></td></tr> </tbody> </table> |
| exchange_multiple | 0x353ca424 | <table> <tbody> <tr><td><code>address[9] \_route</code></td></tr> <tr><td><code>uint256 \_amount</code></td></tr> <tr><td><code>uint256 \_expected</code></td></tr> </tbody> </table> |
| exactInput | 0xc04b8d59 | <table> <tbody> <tr><td><code>bytes path</code></td></tr> <tr><td><code>address recipient</code></td></tr> <tr><td><code>uint256 amountIn</code></td></tr> <tr><td><code>uint256 amountOutMinimum</code></td></tr> </tbody> </table> |
| exactInputSingle | 0x414bf389 | <table> <tbody> <tr><td><code>address tokenIn</code></td></tr> <tr><td><code>address tokenOut</code></td></tr> <tr><td><code>address recipient</code></td></tr> <tr><td><code>uint256 amountIn</code></td></tr> <tr><td><code>uint256 amountOutMinimum</code></td></tr> </tbody> </table> |
| buyOusdWithUsdt | 0x35aa0b96 | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| sellOusdForUsdt | 0xcb939053 | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| buyOusdWithDai | 0x5981c746 | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| sellOusdForDai | 0x8a095a0f | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| buyOusdWithUsdc | 0xbfc11ffd | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| sellOusdForUsdc | 0xc6b68169 | <table> <tbody> <tr><td><code>uint256 amount</code></td></tr> </tbody> </table> |
| redeem | 0xba087652 | <table> <tbody> <tr><td><code>uint256 assets</code></td></tr> <tr><td><code>address receiver</code></td></tr> </tbody> </table> |
| redeem | 0xba087652 | <table> <tbody> <tr><td><code>uint256 shares</code></td></tr> <tr><td><code>address receiver</code></td></tr> </tbody> </table> |
31 changes: 14 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,16 @@
[![Compilation & tests](https://github.com/LedgerHQ/app-plugin-boilerplate/actions/workflows/build_and_functional_tests.yml/badge.svg?branch=develop)](https://github.com/LedgerHQ/app-plugin-boilerplate/actions/workflows/build_and_functional_tests.yml)


# app-plugin-boilerplate
# app-plugin-origin

This repo is meant to be a forkable example of a plugin.

Plugins are lightweight applications that go hand-in-hand with the Ethereum
Application on a Nano (S, S plus, X) and Stax devices.

They allow users to safely interact with smart contracts by parsing the
transaction data and displaying its content in a human-readable way. This is
done on a "per contract" basis, meaning a plugin is required for every DApp.

The code has been commented, and special "EDIT THIS" comments indicate where
developers are expected to adapt the code to their own needs.

It is STRONGLY recommended to follow the
[plugin guide](https://developers.ledger.com/docs/dapp/embedded-plugin/code-overview/)
in order to better understand the flow and the context for plugins.
Ledger's recommended [plugin guide](https://developers.ledger.com/docs/dapp/embedded-plugin/code-overview/) is out-dated and doesn't work since they introduced a lot of new changes. Here's a simple way to get started with this repo:
1. Clone this repo (along with git submodules)
2. Install [Xquartz](https://www.xquartz.org/) and make sure you have enabled "Allow connections from network clients" enabled under "Security" settings.
3. Install and start Docker (Note: If Docker is already running, quit and start it after starting Xquartz, otherwise docker cannot connect to Xquartz).
4. Install the [Ledger Dev Tools VS Code plugin](https://marketplace.visualstudio.com/items?itemName=LedgerHQ.ledger-dev-tools#:~:text=ledger%2Dvscode%2Dextension,Plus%2C%20Nano%20X%2C%20Stax) and makes sure it's enabled
5. Once you have installed the plugin and open the repo, the plugin should by default try to create and start the containers. If it doesn't, you can simply click "Update Container" under "Ledger Dev Tools" in the Activity Side Bar on VS Code.
6. On the "Ledger Dev Tools" side bar, Select a target and then click on Build.
7. Once build is complete, click on "Run tests" to run the tests

## Ethereum SDK

Expand All @@ -33,8 +26,12 @@ the code is compiled and tested on the latest version of the SDK.

## Documentation

The documentation about the plugin shall be added in [PLUGIN_SPECIFICATON.md](https://github.com/LedgerHQ/app-plugin-boilerplate/blob/develop/PLUGIN_SPECIFICATION.md). It shall includes at least the smart contracts and functions supported by the plugin.
The documentation about the plugin is in [PLUGIN_SPECIFICATON.md](https://github.com/LedgerHQ/app-plugin-boilerplate/blob/develop/PLUGIN_SPECIFICATION.md). It includes the smart contracts and functions supported by the plugin.

## Formatting

The C source code is expected to be formatted with `clang-format` 11.0.0 or higher.

```
clang-format -style=Google -i src/*
```
Binary file added glyphs/stax_origin_64px.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added glyphs/stax_origin_64px_bitmap.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed glyphs/stax_pluginboilerplate_64px.gif
Binary file not shown.
Binary file added icons/nanos_app_origin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/nanos_app_origin.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed icons/nanos_app_pluginboilerplate.gif
Binary file not shown.
Binary file added icons/nanox_app_origin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/nanox_app_origin.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed icons/nanox_app_pluginboilerplate.gif
Binary file not shown.
Binary file added icons/stax_app_origin.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added icons/stax_app_origin.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed icons/stax_app_pluginboilerplate.gif
Binary file not shown.
55 changes: 42 additions & 13 deletions src/handle_finalize.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,50 @@
#include "plugin.h"

void handle_finalize(ethPluginFinalize_t *msg) {
context_t *context = (context_t *) msg->pluginContext;
context_t *context = (context_t *)msg->pluginContext;

msg->uiType = ETH_UI_TYPE_GENERIC;
msg->uiType = ETH_UI_TYPE_GENERIC;

// EDIT THIS: Set the total number of screen you will need.
msg->numScreens = 2;
// EDIT THIS: Handle this case like you wish to (i.e. maybe no additional screen needed?).
// If the beneficiary is NOT the sender, we will need an additional screen to display it.
if (memcmp(msg->address, context->beneficiary, ADDRESS_LENGTH) != 0) {
msg->numScreens += 1;
}
// Number of screens needed
msg->numScreens = 2;

bool sender_is_beneficiary =
memcmp(msg->address, context->beneficiary, ADDRESS_LENGTH) == 0;

// EDIT THIS: set `tokenLookup1` (and maybe `tokenLookup2`) to point to
// token addresses you will info for (such as decimals, ticker...).
msg->tokenLookup1 = context->token_received;
if (sender_is_beneficiary) {
// No need to show beneficary screen when signer is same as `beneficiary`
bool wrap_tx =
(context->selectorIndex == WRAP || context->selectorIndex == UNWRAP);
bool uniswap_tx =
(context->selectorIndex == UNISWAP_V3_ROUTER_EXACT_INPUT ||
context->selectorIndex == UNISWAP_ROUTER_EXACT_INPUT_SINGLE);

if (wrap_tx) {
msg->numScreens -= 1;
} else if (uniswap_tx) {
msg->numScreens += 1;
}
}
if (!ADDRESS_IS_NETWORK_TOKEN(context->contract_address_sent)) {
// Address is not network token (0xeee...) so we will need to look up the
// token in the CAL.
printf_hex_array("Setting address sent to: ", ADDRESS_LENGTH,
context->contract_address_sent);
msg->tokenLookup1 = context->contract_address_sent;
} else {
sent_network_token(context);
msg->tokenLookup1 = NULL;
}
if (!ADDRESS_IS_NETWORK_TOKEN(context->contract_address_received)) {
// Address is not network token (0xeee...) so we will need to look up the
// token in the CAL.
printf_hex_array("Setting address received to: ", ADDRESS_LENGTH,
context->contract_address_received);
msg->tokenLookup2 = context->contract_address_received;
} else {
received_network_token(context);
msg->tokenLookup2 = NULL;
}

msg->result = ETH_PLUGIN_RESULT_OK;
msg->result = ETH_PLUGIN_RESULT_OK;
}
127 changes: 79 additions & 48 deletions src/handle_init_contract.c
Original file line number Diff line number Diff line change
@@ -1,59 +1,90 @@
#include "plugin_utils.h"
#include "plugin.h"
#include "plugin_utils.h"

// Called once to init.
void handle_init_contract(ethPluginInitContract_t *msg) {
// Make sure we are running a compatible version.
if (msg->interfaceVersion != ETH_PLUGIN_INTERFACE_VERSION_LATEST) {
// If not the case, return the `UNAVAILABLE` status.
msg->result = ETH_PLUGIN_RESULT_UNAVAILABLE;
return;
}
// Make sure we are running a compatible version.
if (msg->interfaceVersion != ETH_PLUGIN_INTERFACE_VERSION_LATEST) {
// If not the case, return the `UNAVAILABLE` status.
msg->result = ETH_PLUGIN_RESULT_UNAVAILABLE;
return;
}

// Double check that the `context_t` struct is not bigger than the maximum size (defined by
// `msg->pluginContextLength`).
if (msg->pluginContextLength < sizeof(context_t)) {
PRINTF("Plugin parameters structure is bigger than allowed size\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}
// Double check that the `context_t` struct is not bigger than the maximum
// size (defined by `msg->pluginContextLength`).
if (msg->pluginContextLength < sizeof(context_t)) {
PRINTF("Plugin parameters structure is bigger than allowed size\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}

context_t *context = (context_t *) msg->pluginContext;
context_t *context = (context_t *)msg->pluginContext;

// Initialize the context (to 0).
memset(context, 0, sizeof(*context));
// Initialize the context (to 0).
memset(context, 0, sizeof(*context));

size_t index;
if (!find_selector(U4BE(msg->selector, 0), SELECTORS, SELECTOR_COUNT, &index)) {
PRINTF("Error: selector not found!\n");
msg->result = ETH_PLUGIN_RESULT_UNAVAILABLE;
return;
}
context->selectorIndex = index;
// check for overflow
if ((size_t) context->selectorIndex != index) {
PRINTF("Error: overflow detected on selector index!\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}
size_t index;
if (!find_selector(U4BE(msg->selector, 0), SELECTORS, SELECTOR_COUNT,
&index)) {
PRINTF("Error: selector not found!\n");
msg->result = ETH_PLUGIN_RESULT_UNAVAILABLE;
return;
}
context->selectorIndex = index;
// check for overflow
if ((size_t)context->selectorIndex != index) {
PRINTF("Error: overflow detected on selector index!\n");
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}

// Set `next_param` to be the first field we expect to parse.
// EDIT THIS: Adapt the `cases`, and set the `next_param` to be the first parameter you expect
// to parse.
switch (context->selectorIndex) {
case SWAP_EXACT_ETH_FOR_TOKENS:
context->next_param = MIN_AMOUNT_RECEIVED;
break;
case BOILERPLATE_DUMMY_2:
context->next_param = TOKEN_RECEIVED;
break;
// Keep this
default:
PRINTF("Missing selectorIndex: %d\n", context->selectorIndex);
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}
// Set `next_param` to be the first field we expect to parse.
switch (context->selectorIndex) {
case ZAPPER_DEPOSIT_ETH:
context->next_param = NONE;
break;
case CURVE_POOL_EXCHANGE:
case CURVE_POOL_EXCHANGE_UNDERLYING:
if (memcmp(CURVE_OETH_POOL_ADDRESS,
msg->pluginSharedRO->txContent->destination,
ADDRESS_LENGTH) == 0 ||
memcmp(CURVE_OUSD_POOL_ADDRESS,
msg->pluginSharedRO->txContent->destination,
ADDRESS_LENGTH) == 0) {
context->next_param = TOKEN_SENT;
break;
}
PRINTF("Missing selectorIndex: %d\n", context->selectorIndex);
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
case UNISWAP_V3_ROUTER_EXACT_INPUT:
context->skip += 2;
context->next_param = BENEFICIARY;
case UNISWAP_ROUTER_EXACT_INPUT_SINGLE:
break;
case CURVE_ROUTER_EXCHANGE_MULTIPLE:
case VAULT_MINT:
context->next_param = TOKEN_SENT;
break;
case FLIPPER_BUY_OUSD_WITH_USDT:
case FLIPPER_SELL_OUSD_FOR_USDT:
case FLIPPER_BUY_OUSD_WITH_DAI:
case FLIPPER_SELL_OUSD_FOR_DAI:
case FLIPPER_BUY_OUSD_WITH_USDC:
case FLIPPER_SELL_OUSD_FOR_USDC:
case ZAPPER_DEPOSIT_SFRXETH:
case VAULT_REDEEM:
case WRAP:
case UNWRAP:
context->next_param = AMOUNT_SENT;
break;
// Keep this
default:
PRINTF("Missing selectorIndex: %d\n", context->selectorIndex);
msg->result = ETH_PLUGIN_RESULT_ERROR;
return;
}

// Return valid status.
msg->result = ETH_PLUGIN_RESULT_OK;
// Return valid status.
msg->result = ETH_PLUGIN_RESULT_OK;
}
Loading

0 comments on commit d2e7c87

Please sign in to comment.