KyberSwap Docs
  • Introduction to KyberSwap
  • Getting Started
    • Quickstart
      • FAQ
    • Supported Exchanges And Networks
    • Foundational Topics
      • Decentralized Finance
        • Tokens
        • Stablecoins
        • DEX/DeFi Aggregator
        • Slippage
        • Price Impact
        • Zap
        • Maximal Extractable Value (MEV)
      • Decentralized Technologies
        • Wallets
        • Dapps
        • RPC
        • Oracles
        • On-Chain vs Off-Chain Data
      • Other Valuable Resources
  • KyberSwap Solutions
    • KyberSwap Interface
      • User Guides
        • Connect Your Wallet
        • Switching Networks
        • Instantly Swap At Superior Rates
        • Swap At Your Preferred Rates
        • Cross-chain Swap
        • Add Your Favourite Tokens
        • Get Crypto With Fiat
        • Bridge Your Assets Across Multiple Chains
      • Profiles
        • Profile Creation
        • Profile Customization
        • Sync Profile Across Devices
      • Notifications
        • Notification Center
    • KyberSwap Aggregator
      • Concepts
        • Dynamic Trade Routing
      • User Guides
        • Instantly Swap At Superior Rates
      • Developer Guides
        • Execute A Swap With The Aggregator API
        • Upgrading To APIv1
      • Aggregator API Specification
        • EVM Swaps
        • Permit
      • Contracts
        • Aggregator Contract Addresses
      • DEX IDs
      • Subgraphs
      • FAQ
    • KyberSwap Zap as a Service
      • KyberSwap Zap as a Service (ZaaS) API
        • ZaaS HTTP API
        • ZaaS GRPC API
      • KyberSwap Zap Liquidity Widget
      • Zap Fee Model
      • Zap's Supported Chains/Dexes
      • Zap's Deployed Contract Addresses
      • Zap's DEX IDs
    • KyberSwap Widget
      • Developer Guides
        • Integrating The KyberSwap Widget
        • Customizing The KyberSwap Widget
      • iFrame Alternative
      • Widget/iFrame Fee
    • KyberSwap Liquidity Widget
      • Integrating The KyberSwap Liquidity Widget
    • Limit Order
      • Concepts
        • Off-Chain Relay, On-Chain Settlement
        • Gasless Cancellation
      • User Guides
        • Swap At Your Preferred Rates
        • Update Limit Orders
        • Cancel Limit Orders
      • Developer Guides
        • Create Limit Order
        • Gasless Cancel
        • Hard Cancel
        • Fill Limit Order
      • Contracts
        • Limit Order Contract Addresses
      • Limit Order API Specification
        • General APIs
        • Maker APIs
        • Taker APIs
      • FAQ
    • KyberSwap OnChain Price Service
    • Fee Schedule
  • Governance
    • KyberDAO
      • User Guides
        • Participating in KyberDAO
        • Staking
        • Voting
        • Stake KNC And Enjoy Gas Savings
      • Fees to KyberDAO
      • KyberDAO Operator MultiSig
      • Contracts
        • KyberDAO Contract Repo
        • KyberDAO Contract Addresses
      • FAQ - Others
    • KNC Token
      • KNC Tokenomics & Utility
      • Gas Refund Program
      • KNC Contract Addresses
  • Security
    • Audits
  • Reference
    • Legacy
      • KyberSwap Classic
        • Concepts
          • Programmable Pricing Curves
          • Dynamic Auto-Adjusting Fees
          • Virtual Balances
          • Protocol Fees
        • Contracts
          • Classic Contract Repo
          • Classic Contract Addresses
          • Classic Contract Farming Addresses
      • KyberSwap Elastic
        • Concepts
          • Concentrated Liquidity
          • Reinvestment Curve
          • Tick-Range Mechanism
          • Pool Process Flows
          • Anti-Sniping Mechanism
          • Tick-Based Farming
          • Elastic Zap
          • TWAP Oracle
          • Elastic APR Calculations
        • Contracts
          • Elastic Contract Repo
          • Elastic Contract Addresses
          • Elastic Farming Contract Addresses
          • Elastic Zap Contract Addresses
          • Elastic Core Contracts
          • Elastic Core Libraries
          • Elastic Periphery Core Contracts
          • Elastic Peripheral Library Contracts
          • Elastic Peripheral Base Contracts
        • Subgraphs
      • Whitepapers
      • Audits
      • KyberAI
        • KyberScore
        • Concepts
        • On-Chain Indicators
          • Number Of Trades
          • Trading Volume
          • Netflow To Whale Wallets
          • Netflow To CEX
          • Number Of Transfers
          • Volume Of Transfers
          • Number Of Holders
          • Top Holders
        • Technical Indicators
          • Live Charts
          • Support & Resistance Levels
          • Live Trades
          • Funding Rate On CEX
          • Liquidations On CEX
        • Liquidity Analysis
      • Elastic Legacy
        • Elastic Legacy Contract Repo
        • Elastic Legacy Contract Addresses
        • Elastic Legacy Farming Contract Addresses
        • Remove Elastic Legacy Liquidity
      • Protocol
        • Overview
        • Smart Contract Architecture
        • Trust and Security Model
      • Integrations
        • Getting Started
        • Use Cases
        • Integration Types
        • Smart Contracts
        • Ethers JS
        • RESTful API
        • Slippage Rate Protection
        • Price Feed Security
        • Contract Events
        • Platform Fees
      • Reserves
        • Getting Started
          • Overview
          • Why Develop On Kyber
          • Create New Reserve
          • Existing Reserves
          • Customising Existing Reserves
        • Development Guides
          • Fed Price Reserve
          • Automated Price Reserve
          • Reserves with Ganache
          • Orderbook Reserve
        • Operations
          • Listing Policies
          • Reserve IDs
          • Reserve Rebates
          • Sanity Rates
      • Addresses
        • Introduction
        • Mainnet
        • Kovan
        • Rinkeby
        • Ropsten
      • API/ABI
        • Introduction
        • RESTful API
          • RESTful API Overview
          • RESTful API
        • Core Smart Contracts
          • IKyberNetworkProxy
          • KyberNetworkProxy
          • IKyberNetwork
          • ISimpleKyberProxy
          • IKyberMatchingEngine
          • KyberMatchingEngine
          • IKyberHint
          • KyberHintHandler
          • IKyberHintHandler
          • IKyberFeeHandler
          • IKyberStaking
          • KyberStaking
          • IKyberDao
          • KyberDao
          • IKyberStorage
          • KyberStorage
          • IKyberHistory
          • KyberHistory
          • IKyberReserve
          • KyberReserve
          • ConversionRates
          • LiquidityConversionRates
          • EpochUtils
          • IEpochUtils
          • KyberFeeHandler
        • Contract ABIs
          • ABIs
        • Code Snippets
          • Token Quantity Conversion
        • Misc Contracts
          • KyberNetwork
          • ConversionRatesInterface
          • PermissionGroups
          • SanityRates
          • Withdrawable
          • OrderbookReserveInterface
          • OrderbookReserveLister
    • KyberSwap Operator MultiSig
    • Permitable Tokens
    • Third-Party Integrations
    • KyberSwap Analytics
    • KyberSwap App
    • GitHub
    • KyberSwap Analytics
    • KyberSwap Blog
    • Kyber Network Press Kit
  • Socials
    • X
    • Discord
    • Telegram
    • LinkedIn
    • Reddit
    • Instagram
    • Tik Tok
  • Support
    • KyberSwap Help Center
    • Complaints Handling Process
Powered by GitBook
On this page
  • Introduction​
  • Things To Note​
  • Trading Tokens​
  • Reserve Routing​

Was this helpful?

  1. Reference
  2. Legacy
  3. Integrations

Smart Contracts

PreviousIntegration TypesNextEthers JS

Last updated 2 years ago

Was this helpful?

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:

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

  2. - 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 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();

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

pragma solidity 0.6.6;

import "./IERC20.sol";
import "./IKyberNetworkProxy.sol";

The network proxy contract can be instantiated as such:

IKyberNetworkProxy kyberProxy;

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

hint

bytes

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.

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

// 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.

uint256 expectedRate = kyberNetworkProxyContract.getExpectedRateAfterFee(
    0x2260fac5e5542a773aa44fbcfedf7c193bc2c599, // WBTC token address
    0xdd974d5c2e2928dea5f71b9825b8b646686bd200, // KNC token address
    100000000, // 1 WBTC
    25, // 0.25%
    '' // empty hint
    );

// expectedRate = 7980824281140923034320
// 7980824281140923034320 / 1e18 = 7980.824 => 1 WBTC = 7980.824 KNC

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.

-->

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

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

// 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.

// Note: msg.value should be the srcQty if src == ETH, 0 otherwise
uint256 actualDestAmount = kyberNetworkProxyContract.tradeWithHintAndFee{value: msg.value}(
    0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, // ETH address
    1000000000000000000, // 1 ETH
    0xdd974d5c2e2928dea5f71b9825b8b646686bd200, // KNC address
    0xbeE6fFAFDE4A9cB252a5eA357a53f558dc8A6876, // destAddress
    9999999999999999999999999999999, // maxDestAmount: arbitarily large to swap full amount
    expectedRate, // minConversionRate: value from getExpectedRate call
    0xbeE6fFAFDE4A9cB252a5eA357a53f558dc8A6876, // platform wallet
    25, // 0.25%
    '' // empty hint
    );

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

// 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.

pragma solidity 0.6.6;

import "./IERC20.sol";
import "./IKyberNetworkProxy.sol";

contract MyContract {
    IERC20 internal constant ETH_TOKEN_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
    IKyberNetworkProxy kyberProxy;
    address payable public platformWallet;
    uint256 public platformFeeBps;

    // constructor
    // _platformWallet: To receive platform fees
    // _platformFeeBps: Platform fee amount in basis points
    constructor(
        IKyberNetworkProxy _kyberProxy,
        address payable _platformWallet,
        uint256 _platformFeeBps
        ) public
    {
        kyberProxy = _kyberProxy;
        platformWallet = _platformWallet;
        platformFeeBps = _platformFeeBps;
    }

    /// @dev Get the conversion rate for exchanging srcQty of srcToken to destToken
    function getConversionRates(
        IERC20 srcToken,
        IERC20 destToken,
        uint256 srcQty
    ) public
      view
      returns (uint256)
    {
      return kyberProxy.getExpectedRateAfterFee(srcToken, destToken, srcQty, platformFeeBps, '');
    }

    /// @dev Swap from srcToken to destToken (including ether)
    function executeSwap(
        IERC20 srcToken,
        uint256 srcQty,
        IERC20 destToken,
        address payable destAddress,
        uint256 maxDestAmount
    ) external payable {
        if (srcToken != ETH_TOKEN_ADDRESS) {
            // check that the token transferFrom has succeeded
            // we recommend using OpenZeppelin's SafeERC20 contract instead
            // NOTE: msg.sender must have called srcToken.approve(thisContractAddress, srcQty)
            require(srcToken.transferFrom(msg.sender, address(this), srcQty), "transferFrom failed");

            // mitigate ERC20 Approve front-running attack, by initially setting
            // allowance to 0
            require(srcToken.approve(address(kyberProxy), 0), "approval to 0 failed");

            // set the spender's token allowance to tokenQty
            require(srcToken.approve(address(kyberProxy), srcQty), "approval to srcQty failed");
        }

        // Get the minimum conversion rate
        uint256 minConversionRate = kyberProxy.getExpectedRateAfterFee(
            srcToken,
            destToken,
            srcQty,
            platformFeeBps,
            '' // empty hint
        );

        // Execute the trade and send to destAddress
        kyberProxy.tradeWithHintAndFee{value: msg.value}(
            srcToken,
            srcQty,
            destToken,
            destAddress,
            maxDestAmount,
            minConversionRate,
            platformWallet,
            platformFeeBps,
            '' // empty hint
        );
    }
}

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.

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

pragma solidity 0.6.6;

import "./IKyberHint.sol";
import "./IKyberStorage.sol";

The kyberStorage and kyberHintHandler contracts can be instantiated as such:

IKyberHint kyberHintHandler;
IKyberStorage kyberStorage;

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.

Get reserve IDs for WBTC -> ETH

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(WBTC_ADDRESS);

Get reserve IDs for ETH -> KNC

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenDest(KNC_ADDRESS);
  • 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

  • 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.

Note that the splits parameter must be empty.

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

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(WBTC_ADDRESS);
bytes32[] memory includedReserveIds = new bytes32[](1);
includedReserveIds[0] = reserveIds[0];
uint256[] memory emptySplits;

bytes memory hint = kyberHintHandler.buildTokenToEthHint(
    WBTC_ADDRESS,
    IKyberHint.TradeType.MaskIn,
    includedReserveIds,
    emptySplits
);

Note that the splits parameter must be empty.

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

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(WBTC_ADDRESS);
bytes32[] memory excludedReserveIds = new bytes32[](1);
excludedReserveIds[0] = reserveIds[0];
uint256[] memory emptySplits;

bytes memory hint = kyberHintHandler.buildTokenToEthHint(
    WBTC_ADDRESS,
    IKyberHint.TradeType.MaskIn,
    excludedReserveIds,
    emptySplits
);

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

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

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenDest(KNC_ADDRESS);
bytes32[] memory splitReserveIds = new bytes32[](2);
splitReserveIds[0] = reserveIds[0];
splitReserveIds[1] = reserveIds[1];
uint256[] memory splits = new uint256[](2);
splits[0] = 5000;
splits[1] = 5000;

bytes memory hint = kyberHintHandler.buildEthToTokenHint(
    KNC_ADDRESS,
    IKyberHint.TradeType.Split,
    splitReserveIds,
    splits
);
  • 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.

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

// 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.

bytes32[] memory reserveIds = kyberStorage.getReserveIdsPerTokenSrc(WBTC_ADDRESS);
bytes32[] memory includedReserveIds = new bytes32[](1);
includedReserveIds[0] = reserveIds[0];
bytes32[] memory emptyReserveIds;
uint256[] memory emptySplits;

bytes memory hint = kyberHintHandler.buildTokenToTokenHint(
    WBTC_ADDRESS,
    IKyberHint.TradeType.MaskIn,
    includedReserveIds,
    emptySplits,
    KNC_ADDRESS,
    IKyberHint.TradeType.BestOfAll,
    emptyReserveIds,
    emptySplits
);

Trading Tokens

File Import

: Token approvals and transfers. We recommend the usage of for these purposes.

: Fetch rates and execute trades

Proxy Contract Declaration

Fetching Rates

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

hint for reserve routing. hint for reserve routing. Refer to

Example

Trade Execution

<!-- Read more about platform fees

<!-- Read more about platform fees

<!-- Refer to

Example

Code Example

Reserve Routing

Overview

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 or the . Nevertheless, this guide explains how you may do the building of hints on-chain.

File Import

: Fetching reserve IDs. For more information about reserve IDs, refer to .

: Building and parsing of hints

: The IERC20 input parameter of building / parsing hints

Contract Variable Declarations

Fetching Reserve IDs

Examples

Building Hints

Notes

MaskIn TradeType

Example

MaskOut TradeType

Example

Split TradeType

Example

BestOfAll TradeType

Example

Classic
Elastic
Limit Order
Aggregator
​
Trading Tokens
Reserve Routing
​
is the wrapper contract address
​
​
IERC20.sol
OpenZeppelin's SafeERC20 contract
IKyberNetworkProxy.sol
​
​
​
​
​
​
​
​
​
ethers
/hint RESTful API
​
IKyberStorage.sol
this section
IKyberHint.sol
IERC20.sol
​
​
​
​
​
​
​
​
​
​
​
​
​
here
this section
here
here
this section