Skip to content

kilnfi/app-plugin-kiln-v2

 
 

Repository files navigation

Badges

Code style check Compilation & tests

app-plugin-kiln

Kiln Logo

This plug-in is compatible with Nano S / X / SP devices, it enables to interact in a secure way with the Kiln On-Chain v1, v2, EigenLayer Liquid Restaking contracts, and DeFi vault contracts.

Documentation

Plugin codebase

This plugin follows the structure of a Ledger Ethereum app plugin described here.

It receives data from the Ethereum app, processes it and displays (ie "clearsign") on the device screen.

All the plugin code is in the src folder.

The plugin codebase follows the 6 steps of the plugin flow:

  1. initialize (in src/handle_init_contract.c): plugin receives the selector to manage, and init the correct parser initial state for the function (context->next_param).
  2. provide parameter (in src/provide_parameter/handle_provide_parameter.c): selected parser receives parameters 32 bytes by 32 bytes, and parse them to the correct state. See files like src/provide_parameter/eigenlayer.c for the different parsers.
  3. finalize (in src/handle_finalize.c): plugin returns the number of screens to display
  4. provide_token not used here
  5. query_contract_id (in src/handle_query_contract_id.c): plugin returns the contract name as the first displayed screen on the device
  6. query_contract_ui (in src/query_contract_ui/handle_query_contract_ui.c): plugin returns the screens to display on the device, each product has its own file like src/query_contract_ui/eigenlayer.c.

Other important files:

  • src/contracts.c holds all the constant representing contract functions, parameters or known contracts mappings.
  • src/kiln_plugin.h is where we define all the parser states and the plugin context structure.

Plugin context

The plugin context is defined in src/kiln_plugin.h and holds the state of the plugin. It is passed to all the plugin functions.

It is defined using a union of all the possible parser parameters of the plugin, and a next_param field to know which parser state to use next.

The plugin context is memset to 0 everytime init_contract is called (beginning of a clearsigning flow), so we make sure that the plugin context union is in a clean state before using it in the parsers.

Provide parameter parsers

The provide parameter parsers are defined in src/provide_parameter/ and are called by the handle_provide_parameter function.

Each parser is a state machine that receives 32 bytes of data at a time (abi format), and updates the plugin context state accordingly.

Build

$ git clone --recurse-submodules https://github.com/kilnfi/app-plugin-kiln-v2.git
$ cd app-plugin-kiln-v2/
$ docker run --rm -it \
    -v "$(realpath .):/app" \
    --user $(id -u $USER):$(id -g $USER) \
    ghcr.io/ledgerhq/ledger-app-builder/ledger-app-dev-tools:latest \
    make

Tests

The tests are in the tests/tests folder. They are written in python and use the ragger framework developed by Ledger.

The output of the tests is a series of screenshots stored in the tests/snapshots-tmp folder that are compared to the expected screenshots in the tests/snapshots folder. The latter are stored in the git repository to make sure we expect the correct outputs.

The recommended way to test the plugin is to use the Ledger vscode extension to build and run the tests.

Fuzzing

The plugin is fuzzed using the fuzzing folder following ledger boilerplate.

Continuous Integration

The flow processed in GitHub Actions is the following:

Supported Smart Contracts

Smart contracts covered by this plugin are:

Network Name Address
Mainnet Kiln On-Chain v1 0x1e68238ce926dec62b3fbc99ab06eb1d85ce0270
Mainnet Kiln On-Chain v2 Native20 0x5db5235b5c7e247488784986e58019fffd98fda4
Mainnet Kiln On-Chain v2 ExitQueue 0x8d6fd650500f82c7d978a440348e5a9b886943bf
Mainnet EigenLayer Strategy Manager 0x858646372cc42e1a627fce94aa7a7033e7cf075a
Mainnet EigenLayer Delegation Manager 0x39053d51b77dc0d36036fc1fcc8cb819df8ef37a
Mainnet Cool Wallet AAVEv3 USDT 0x03441c89e7B751bb570f9Dc8C92702b127c52C51
Mainnet BITNOVO AAVE v3 USDC 0x6f15CDA2D68B00311614294A2b9b17400636133C
Mainnet Cool Wallet AAVEv3 USDT 0x4d1806C26A728f2e1b82b4549b9E074DBE5940B9

Clearsigning

KILN ON-CHAIN v1 - Deposit

Function: deposit() Clearsigned:

  • tx.value

KILN ON-CHAIN v1 - Withdraw

Function withdraw(bytes validatorPubkey) Clearsigned:

  • none as BLS key is not digest to display on device and only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Withdraw EL

Function withdrawEL(bytes validatorPubkey) Clearsigned:

  • none as BLS key is not digest to display on device and only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Withdraw CL

Function withdrawCL(bytes validatorPubkey) Clearsigned:

  • none as BLS key is not digest to display on device and only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Batch Withdraw

Function batchWithdraw(bytes validatorPubkeys)

  • none as validatorPubkeys can represent many BLS keys that we can't store on the device. Also only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Batch Withdraw EL

Function batchWithdrawEL(bytes validatorPubkeys) Clearsigned:

  • none as validatorPubkeys can represent many BLS keys that we can't store on the device. Also only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Batch WithdrawCL

Function batchWithdrawCL(bytes validatorPubkeys) Clearsigned:

  • none as validatorPubkeys can represent many BLS keys that we can't store on the device. Also only owner of the validator can withdraw on its behalf so no attack vector possible.

KILN ON-CHAIN v1 - Request Exits

Function requestValidatorsExit(bytes validatorPubkeys) Clearsigned:

  • none as validatorPubkeys can represent many BLS keys that we can't store on the device. Also only owner of the validator can request exit on its behalf so no attack vector possible.

KILN ON-CHAIN v2 - Stake

Function: stake() Clearsigned:

  • tx.value

KILN ON-CHAIN v2 - RequestExit

Function: requestExit(uint256 shares) Clearsigned:

  • none as shares is not 1:1 with ETH value, it would confuse users

KILN ON-CHAIN v2 - MultiClaim

Function: multiClaim(address[] exitQueues, uint256[][] ticketIds, uint32[][] casksIds) Clearsigned:

  • none

KILN ON-CHAIN v2 - Claim

Function: claim(uint256[] ticketIds, uint32[] caskIds, uint16 maxClaimDepth) Clearsigned:

  • none

EigenLayer Strategy Manager - LR Deposit Into Strategy

Function: depositIntoStrategy(address strategy, address erc20, uint256 amount) Clearsigned:

  • strategy: using mapping in contracts.c, it is either recognized or displayed as "UNKOWN"
  • erc20: using mapping in contracts.c, it is either recognized or displayed as "UNKOWN"
  • amount

EigenLayer Delegation Manager - Delegate To

Function:

struct SignatureWithExpiry {
    bytes signature;
    uint256 expiry;
}

function delegateTo(
    address operator,
    SignatureWithExpiry memory approverSignatureAndExpiry,
    bytes32 approverSalt
)

Clearsigned:

  • operator: using mapping in contracts.c, it is either recognized or displayed as address

Shares are confusing for users and would be hard to store properly on the device for display.

EigenLayer Delegation Manager - Undelegate

Function: undelegate(address staker) Clearsigned:

  • none as there is a staker == msg.sender requirement in the contract

EigenLayer Strategy Manager - Queue Withdrawals

Function:

struct QueuedWithdrawalParams {
    address[] strategies;
    uint256[] shares;
    address withdrawer;


function queueWithdrawals(
    QueuedWithdrawalParams[] queuedWithdrawalParams
)

Clearsigned:

  • strategies: using mapping in contracts.c, they are either recognized or displayed as "UNKOWN"
  • withdrawer

Shares are confusing for users and would be hard to store properly on the device for display.

EigenLayer Strategy Manager - LR Complete Queued Withdrawals

Function:

struct Withdrawal {
    address staker;
    address delegatedTo;
    address withdrawer;
    uint256 nonce;
    uint32 startBlock;
    address[] strategies;
    uint256[] shares;
}

function completeQueuedWithdrawals(
    Withdrawal[] withdrawals,
    address[][] tokens,
    uint256[] middlewareTimesIndexes,
    bool[] receiveAsTokens
)

Clearsigned:

  • strategies: using mapping in contracts.c, they are either recognized or displayed as "UNKOWN"
  • if each withdrawal corresponding receiveAsTokens is true, then the corresponding token is displayed as "Withdraw" else as "Redelegation

Shares are confusing for users and would be hard to store properly on the device for display.

DeFi - Deposit

Function: deposit(uint256 assets, address receiver) Clearsigned:

  • assets: amount of assets to deposit
  • receiver: address that will receive the shares

DeFi - Mint

Function: mint(uint256 shares, address receiver) Clearsigned:

  • shares: amount of shares to mint
  • receiver: address that will receive the shares

DeFi - Withdraw

Function: withdraw(uint256 assets, address receiver, address owner) Clearsigned:

  • assets: amount of assets to withdraw
  • receiver: address that will receive the assets
  • owner: address that owns the shares

DeFi - Redeem

Function: redeem(uint256 shares, address receiver, address owner) Clearsigned:

  • shares: amount of shares to redeem
  • receiver: address that will receive the assets
  • owner: address that owns the shares

DeFi - Approve

Function: approve(address spender, uint256 amount) Clearsigned:

  • spender: address to allow spending tokens
  • amount: amount of tokens that can be spent

DeFi - Transfer

Function: transfer(address to, uint256 amount) Clearsigned:

  • to: address to receive tokens
  • amount: amount of tokens to transfer

DeFi - TransferFrom

Function: transferFrom(address from, address to, uint256 amount) Clearsigned:

  • from: address to transfer tokens from
  • to: address to receive tokens
  • amount: amount of tokens to transfer

About

Ethereum Ledger App for Kiln

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 84.7%
  • Python 13.0%
  • CMake 1.6%
  • Other 0.7%