Smart Contracts

Introduction

This guide will walk you through on how you can interact with our protocol implementation at a smart contract level. The most common group of users that can benefit from this guide are Dapps.

We break the guide into 2 sections:

  1. Trading Tokens - The section covers what contract interfaces to import, and functions to call to fetch rates and perform a simple trade.

  2. Reserve Routing - This section covers the reserve routing feature to include / exclude reserves, or to split trades amongst multiple reserves.

Things To Note

  1. If possible, minimise the use of msg.sender within your smart contract. If you were to call a function within the wrapper contract, msg.sender is the wrapper contract address instead of your wallet address.

  2. If the source token is not ETH (ie. an ERC20 token), the user is required to first call the ERC20 approve function to give an allowance to the smart contract executing the transferFrom function.

  3. To prevent front running, the contract limits the gas price trade transactions can have. The transaction will be reverted if the limit is exceeded. To query for the maximum gas limit, check the public variable maxGasPrice.

// DISCLAIMER: Code snippets in this guide are just examples and you
// should always do your own testing. If you have questions, visit our
// https://t.me/KyberDeveloper.

let maxGasPrice = await KyberNetworkProxyContract.maxGasPrice();

Trading Tokens

File Import

We will use Solidity compiler version 0.6.6 for deploying our sample contract. The following interfaces are imported for these functionalities:

Proxy Contract Declaration

The network proxy contract can be instantiated as such:

Fetching Rates

Call the getExpectedRateAfterFee function of the network proxy contract. The input parameters are explained below.

Parameter
Type
Description

src

IERC20

source ERC20 token contract address

dest

IERC20

destination ERC20 token contract address

srcQty

uint256

src token wei amount

platformFeeBps

uint256

platform fee to be charged, in basis points. Read more about platform fees here

hint

bytes

hint for reserve routing. hint for reserve routing. Refer to this section

Returns\ Expected rate for a trade after deducting network and platform fees. To get a 'readable' rate, divide it by 10**18. Refer to the example below.

Example

Get the conversion rate of 1 WBTC -> KNC, with a platform fee of 0.25%.

Trade Execution

Call the tradeWithHintAndFee function of the network proxy contract. The input parameters are explained below.

Parameter
Type
Description

src

IERC20

source ERC20 token contract address

srcAmount

uint256

src token wei amount

dest

IERC20

destination ERC20 token contract address

destAddress

address

recipient address of dest tokens

maxDestAmount

uint256

limit on maximum dest token wei receivable

minConversionRate

uint256

minimal conversion rate. If actual rate is lower, trade reverts

platformWallet

address

wallet address for receiving platform fees.

<!-- Read more about platform fees here

-->

platformFeeBps

uint256

platform fee to be charged, in basis points.

<!-- Read more about platform fees here

-->

hint

bytes

hint for reserve routing.

<!-- Refer to this section

-->

Returns\ Actual dest token wei amount sent to destAddress

Example

Convert 1 ETH to KNC, specifying 0.25% platform fee.

Code Example

Note: The following code is not audited and should not be used in production. If so, it is done at your own risk.

Reserve Routing

Overview

In previous network versions, the hint parameter was used to filter permissionless reserves. With Katalyst, we utilise this parameter for routing trades to specific reserves.

There are 4 optional routing rules:

  1. BestOfAll - This is the default routing rule when no hint is provided, and is the classic reserve matching algorithm used by the Kyber smart contracts since the beginning.

  2. MaskIn (Whitelist) - Specify a list of reserves to be included and perform the BestOfAll routing on them

  3. MaskOut (Blacklist) - Specify a list of reserves to be excluded and perform the BestOfAll routing on the remaining reserves

  4. Split - Specify a list of reserves and their respective percentages of the total srcQty that will be routed to each reserve.

For token -> token trades, you can specify a routing rule for each half. For example, a MaskIn route can be used for the token -> ether side, while a Split route can be used for the ether -> token side.

Recommendation

We strongly recommend for the building of hints to be performed off-chain to save gas costs, and we have not discovered a use case for it to be done on-chain yet. You can do so using ethers or the /hint RESTful API. Nevertheless, this guide explains how you may do the building of hints on-chain.

File Import

We will use Solidity compiler version 0.6.6 for deploying our sample contract. The following interfaces are imported for these functionalities:

Contract Variable Declarations

The kyberStorage and kyberHintHandler contracts can be instantiated as such:

Fetching Reserve IDs

For the token -> ether side of the trade, call getReserveIdsPerTokenSrc of the kyberStorage contract. For the ether -> token side of the trade, call getReserveIdsPerTokenDest of the kyberStorage contract.

Examples

Get reserve IDs for WBTC -> ETH

Get reserve IDs for ETH -> KNC

Building Hints

  • For token -> ether trades, call the buildTokenToEthHint function

  • For ether -> token trades, call the buildTokenToEthHint function

  • For token -> token trades, call the buildTokenToTokenHint function

Their input parameters are explained below:

Parameter
Type
Description

tokenSrc

IERC20

source ERC20 token contract address

tokenToEthType

TradeType

BestOfAll, MaskIn, MaskOut or Split

tokenToEthReserveIds

bytes32[]

list of reserve IDs for token -> ether trade

tokenToEthSplits

uint256[]

percentages (in basis points) for Split trade

tokenDest

IERC20

source ERC20 token contract address

ethToTokenType

TradeType

BestOfAll, MaskIn, MaskOut or Split

ethToTokenReserveIds

bytes32[]

list of reserve IDs for token -> ether trade

ethToTokenSplits

uint256[]

percentages (in basis points) for Split trade

Notes

  • The correct builder hint function must be used for the correct trade type. Otherwise, the hint will not be built correctly, and will result in transaction failure.

  • For token -> token trades, a combination of TradeTypes are allowed. For example, the token -> eth trade can be BestOfAll, while the eth -> token trade can be Split.

MaskIn TradeType

Note that the splits parameter must be empty.

Example

Select the first reserve for a WBTC -> ETH trade.

MaskOut TradeType

Note that the splits parameter must be empty.

Example

Exclude the first reserve from a WBTC -> ETH trade.

Split TradeType

Note that the splits values must add up to 10000 (100%).

Example

Split evenly among 2 reserves for a ETH -> KNC trade.

BestOfAll TradeType

  • The BestOfAll TradeType is primarily for specifying the BestOfAll behaviour for one side of token -> token trades. It is not needed for token -> ether and ether -> token trades.

  • The reserveIds and splits parameters must be empty.

Example

For a WBTC -> KNC trade, do a MaskIn route for WBTC -> ETH, and BestOfAll route for ETH -> KNC.

Last updated

Was this helpful?