Injective | Documentation
InjectiveGithub
Injective | Documentation
Injective | Documentation
  • About Injective
  • Getting Started
    • Wallet
      • Create a wallet
      • Accounts
      • Staking
      • Governance
      • Auction
    • Token Standards
      • INJ coin
      • Token Factory
      • CW20 Standard
    • Transactions
      • Gas and Fees
  • Guides
    • Create a Wallet
    • Bridge
      • From Ethereum
      • Using Wormhole
      • Using IBC
      • From Solana
    • Launch a Token
    • Launch a Market
    • Denom Metadata
    • Get INJ
  • Toolkits
    • injectived
      • Install injectived
      • Using injectived
      • Commands
    • Injective TS SDK
    • Injective Go SDK
    • Injective Python SDK
    • Injective CW SDK
    • Injective Rust
    • The Graph
  • References
  • Glossary
  • Developers
    • Getting Started
      • Guides
        • Testnet Proposals
        • Convert addresses
        • Calculations
          • Min Price Tick Size
          • Min Quantity Tick Size
        • Testnet Faucet Integration
    • Exchange Developers
      • Build a DEX
      • Provider Oracle
    • EVM Developers
      • Your First Smart Contract
      • Guides
        • Testnet Deployment
      • Technical Information
        • Network Information
        • EVM Equivalence
        • MultiVM Token Standard
        • Precompiles
          • Bank Precompile
          • Exchange Precompile
        • ERC20 Module
        • Infrastructure & Tooling
      • EVM Testnet Faucet
      • EVM Testnet Explorer
    • Cosmwasm Developers
      • Your First Smart Contract
      • Guides
        • Local Development
        • Mainnet Deployment
        • Whitelisting deployment address
        • Create your Swap Contract
        • Creating UIs
      • Using Injective Queries and Messages
      • CW20 Adapter
      • Injective Test Tube
    • Modules
      • Injective
        • Auction
          • State
          • Messages
          • EndBlock
          • Events
          • Params
          • Errors
        • Exchange
          • Derivative Markets Concepts
          • Spot Markets Concepts
          • Binary Option Markets Concepts
          • Other Concepts
          • State
          • State Transitions
          • Messages
          • Proposals
          • BeginBlock
          • EndBlock
          • Events
          • Params
          • MsgPrivilegedExecuteContract
          • Errors
        • Insurance
          • State
          • State Transitions
          • Messages
          • EndBlock
          • Events
          • Params
          • Improvements
          • Errors
        • OCR
          • Concepts
          • State
          • Messages
          • Proposals
          • BeginBlock
          • Hooks
          • Events
          • Params
          • Errors
        • Oracle
          • State
          • Keeper
          • Messages
          • Proposals
          • Events
          • Improvements
          • Errors
        • Peggy
          • Definitions
          • Workflow
          • State
          • Messages
          • Slashing
          • EndBlock
          • Events
          • Params
          • Relay Semantics
          • Improvements
          • Errors
        • Permissions
          • Concepts
          • State
          • State Transition
          • Errors
        • TokenFactory
          • Concepts
          • State
          • Messages
          • Events
          • Params
          • Errors
        • WasmX
          • Concepts
          • Data
          • Proposals
          • Messages
          • Params
          • Errors
        • Lanes
        • TxFees
      • Core
        • Auth
        • AuthZ
        • Bank
        • Consensus
        • Crisis
        • Distribution
        • Evidence
        • Feegrant
        • Gov
        • Group
        • Mint
        • NFT
        • Params
        • Slashing
        • Staking
        • Upgrade
        • Circuit
        • Genutils
    • dApps Documentation
  • Nodes
    • Getting Started
      • Interact with a node
      • Running a node
        • Setting up the keyring
        • Join a network
        • Cosmovisor
        • Upgrade your node
    • Validators
      • Mainnet
        • Peggo
        • Canonical Chain Upgrades
          • Upgrade to 10002-rc1
          • Upgrade to 10002-rc2
          • Upgrade to 10003-rc1
          • Upgrade to 10004-rc1
          • Upgrade to 10004-rc1-patch
          • Upgrade to 10005-rc1
          • Upgrade to 10006-rc1
          • Upgrade to 10007-rc1
          • Upgrade to 10008 - Camelot
          • Upgrade to 10009
          • Upgrade to v1.10
          • Upgrade to v1.11
          • Upgrade to v1.12.0 - Volan
          • Upgrade to v1.12.1
          • Upgrade to v1.13.0 - Altaris
          • Upgrade to v1.13.2
          • Upgrade to v1.13.3
          • Upgrade to v1.14.0
          • Upgrade to v1.14.1
          • Upgrade to v1.15.0
      • Testnet
        • Testnet Peggo
    • Public Endpoints
    • Premium Endpoints
    • Injective Indexer Setup
  • Traders
    • Getting Started
    • Documentation
    • API Reference
  • Useful Links
    • Injective 101
    • Injective Hub
    • Injective Explorer
    • Chain API Reference
    • Indexer API Reference
    • Testnet Faucet
Powered by GitBook
On this page
Edit on GitHub
Export as PDF
  1. Developers
  2. EVM Developers
  3. Technical Information
  4. Precompiles

Exchange Precompile

The Exchange Precompile is a system smart contract residing at the fixed address 0x0000000000000000000000000000000000000065. It offers Solidity developers a gas-efficient and native pathway to interact directly with the Injective chain's exchange module. By leveraging this precompile, your smart contracts can seamlessly perform a variety of exchange-related actions, including:

  • Depositing and withdrawing funds to/from subaccounts.

  • Placing or cancelling spot and derivative orders.

  • Querying subaccount balances and open positions.

  • Managing authorization grants for other accounts or contracts.

Calling the Precompile: Direct vs. Proxy Access

Interacting with the Exchange Precompile can be approached in two primary ways:

1. Direct Access (Self-Calling Contracts)

In this mode, your smart contract interacts with the precompile on its own behalf. The contract itself is the actor performing operations on the exchange module, using its own funds and managing its own positions.

Example:

exchange.deposit(address(this), subaccountID, denom, amount);  

This method is straightforward and requires no explicit authorization grant, as the contract is inherently permissioned to manage its own resources.

2. Proxy Access (Calling on Behalf of Another User)

Smart contracts can also be designed to act as intermediaries, performing exchange operations on behalf of external user accounts. In this scenario, the contract calls the precompile, specifying a third-party's address as the sender or the account to be acted upon.

Example:

exchange.deposit(userAddress, subaccountID, denom, amount);  

For this to succeed, the smart contract (grantee) must be explicitly authorized by the user (userAddress, the granter) to perform the specified action. This authorization is managed using the approve and revoke methods provided by the precompile. It's crucial to handle these authorizations with care to ensure user funds are secure.

To authorize a contract to perform specific actions on your behalf:

exchange.approve(grantee, msgTypes, spendLimit, duration);  
  • grantee: The address of the contract being authorized.

  • msgTypes: An array of message types (e.g., MsgCreateDerivativeLimitOrder, MsgDeposit) the grantee is authorized to execute. Refer to ExchangeTypes.sol or the Injective Protocol protobuf definitions for a complete list.

  • spendLimit: An array of Cosmos.Coin structs defining the maximum amount of specified tokens the grantee can utilize per message type or overall for the grant.

  • duration: The time period, in seconds, for which the authorization remains valid.

To revoke a previously granted authorization:

exchange.revoke(grantee, msgTypes);  

To check if an authorization currently exists:

exchange.allowance(grantee, granter, msgType);  

Example: Direct Method

The ExchangeDemo contract below illustrates how a smart contract can use the direct access method. It performs basic exchange actions like depositing funds, withdrawing funds, creating a derivative limit order, and querying subaccount positions, all using its own subaccount and funds.

The Exchange.sol and ExchangeTypes.sol files contain the necessary interface definitions and data structures for interacting with the precompile. These are typically available in the official Injective Solidity contracts repository or can be included as dependencies in your project.

// SPDX-License-Identifier: MIT  
pragma solidity ^0.8.4;  
  
import "../src/Exchange.sol"; // Contains IExchangeModule interface  
import "../src/ExchangeTypes.sol"; // Contains necessary structs like DerivativeOrder  
  
contract ExchangeDemo {  
    address constant exchangeContract = 0x0000000000000000000000000000000000000065;  
    IExchangeModule exchange = IExchangeModule(exchangeContract);  
  
    /***************************************************************************  
     * Calling the precompile directly (contract acts on its own behalf)  
    ****************************************************************************/  
  
    /**  
     * @notice Deposits funds from the contract's balance into one of its exchange subaccounts.  
     * @param subaccountID The target subaccount ID (derived from the contract's address).  
     * @param denom The denomination of the asset to deposit (e.g., "inj").  
     * @param amount The quantity of the asset to deposit.  
     * @return success Boolean indicating if the deposit was successful.  
     */  
    function deposit(  
        string calldata subaccountID,  
        string calldata denom,  
        uint256 amount  
    ) external returns (bool) {  
        try exchange.deposit(address(this), subaccountID, denom, amount) returns (bool success) {  
            return success;  
        } catch Error(string memory reason) {  
            revert(string(abi.encodePacked("Deposit error: ", reason)));  
        } catch {  
            revert("Unknown error during deposit");  
        }  
    }  
  
    /**  
     * @notice Withdraws funds from one of the contract's exchange subaccounts to its main balance.  
     * @param subaccountID The source subaccount ID.  
     * @param denom The denomination of the asset to withdraw.  
     * @param amount The quantity of the asset to withdraw.  
     * @return success Boolean indicating if the withdrawal was successful.  
     */  
    function withdraw(  
        string calldata subaccountID,  
        string calldata denom,  
        uint256 amount  
    ) external returns (bool) {  
        try exchange.withdraw(address(this), subaccountID, denom, amount) returns (bool success) {  
            return success;  
        } catch Error(string memory reason) {  
            revert(string(abi.encodePacked("Withdraw error: ", reason)));  
        } catch {  
            revert("Unknown error during withdraw");  
        }  
    }  
  
    /**  
     * @notice Queries the derivative positions for a given subaccount of this contract.  
     * @param subaccountID The subaccount ID to query.  
     * @return positions An array of DerivativePosition structs.  
     */  
    function subaccountPositions(  
        string calldata subaccountID  
    ) external view returns (IExchangeModule.DerivativePosition[] memory positions) {  
        // Note: View functions calling precompiles might behave differently based on node configuration  
        // For on-chain state, this is fine. For off-chain queries, direct gRPC/API queries are often preferred.  
        return exchange.subaccountPositions(subaccountID);  
    }  
  
    /**  
     * @notice Creates a new derivative limit order from the contract's subaccount.  
     * @param order The DerivativeOrder struct containing order details.  
     * @return response The response struct containing details like order hash.  
     */  
    function createDerivativeLimitOrder(  
        IExchangeModule.DerivativeOrder calldata order  
    ) external returns (IExchangeModule.CreateDerivativeLimitOrderResponse memory response) {  
        try exchange.createDerivativeLimitOrder(address(this), order) returns (IExchangeModule.CreateDerivativeLimitOrderResponse memory resp) {  
            return resp;  
        } catch Error(string memory reason) {  
            revert(string(abi.encodePacked("CreateDerivativeLimitOrder error: ", reason)));  
        } catch {  
            revert("Unknown error during createDerivativeLimitOrder");  
        }  
    }  
}  

Start building

Conclusion

The Exchange Precompile is a powerful tool, enabling sophisticated, protocol-integrated trading logic to be embedded directly within your smart contracts on Injective. Whether your contract is managing its own portfolio or acting as a versatile trading interface for other users (via the proxy pattern with approve and revoke), this precompile offers a clean, secure, and efficient method to interact with the core exchange module using Solidity.

Remember to prioritize direct calls for self-contained contract logic and to carefully implement the proxy pattern with robust authorization when building reusable contract interfaces for the broader Injective ecosystem.

\

PreviousBank PrecompileNextERC20 Module

Last updated 15 hours ago

For detailed instructions on how to build, deploy, and interact with this ExchangeDemo smart contract, including setting up subaccounts and funding, please refer to the comprehensive demo available in our repository.

solidity-contracts