Smart Contracts
You are referring to the Legacy
version of KyberSwap docs.
For the most updated information, please refer to:
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:
Trading Tokens - The section covers what contract interfaces to import, and functions to call to fetch rates and perform a simple trade.
Reserve Routing - This section covers the reserve routing feature to include / exclude reserves, or to split trades amongst multiple reserves.
Things To Note
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.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 thetransferFrom
function.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
.
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:
IERC20.sol
: Token approvals and transfers. We recommend the usage of OpenZeppelin's SafeERC20 contract for these purposes.IKyberNetworkProxy.sol
: Fetch rates and execute trades
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.
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
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.
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.
platformFeeBps
uint256
platform fee to be charged, in basis points.
hint
bytes
hint for reserve routing.
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:
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.MaskIn
(Whitelist) - Specify a list of reserves to be included and perform theBestOfAll
routing on themMaskOut
(Blacklist) - Specify a list of reserves to be excluded and perform theBestOfAll
routing on the remaining reservesSplit
- Specify a list of reserves and their respective percentages of the totalsrcQty
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:
IKyberStorage.sol
: Fetching reserve IDs. For more information about reserve IDs, refer to this section.IKyberHint.sol
: Building and parsing of hintsIERC20.sol
: TheIERC20
input parameter of building / parsing hints
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
functionFor ether -> token trades, call the
buildTokenToEthHint
functionFor token -> token trades, call the
buildTokenToTokenHint
function
Their input parameters are explained below:
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 beSplit
.
MaskIn
TradeType
MaskIn
TradeTypeNote that the splits parameter must be empty.
Example
Select the first reserve for a WBTC -> ETH trade.
MaskOut
TradeType
MaskOut
TradeTypeNote that the splits parameter must be empty.
Example
Exclude the first reserve from a WBTC -> ETH trade.
Split
TradeType
Split
TradeTypeNote that the splits values must add up to 10000
(100%).
Example
Split evenly among 2 reserves for a ETH -> KNC trade.
BestOfAll
TradeType
BestOfAll
TradeTypeThe
BestOfAll
TradeType is primarily for specifying theBestOfAll
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