Skip to content
KIMP

Interfaces

Solidity interface stubs for the seven KIMP core contracts, with NatSpec, structs, events and errors.

This page lists the external interfaces of the KIMP core contracts. They are reference stubs for integrators. Deployed contracts will implement them exactly; verified source will be published on the GIWA explorer at deployment. Conventions are described in Contracts overview: index values in signed basis points, USD amounts with 18 decimals, assets as bytes32 tickers.

IKimpIndex#

The index stores one finalized value per asset per 60-second epoch. latest returns the most recent finalized value. twap averages finalized samples over a window and is used for settlement. setSource is the governance switch used to make the Upbit Oracle the primary source for the Upbit KRW price.

Solidity
// SPDX-License-Identifier: MITpragma solidity ^0.8.24;interface IKimpIndex {    /// @notice Source used for the Upbit KRW price of an asset.    enum Source { Reporters, UpbitOracle }    /// @notice One finalized epoch value.    struct Epoch {        int256 bps;         // signed kimp in basis points        uint64 timestamp;   // finalization time        uint16 reports;     // valid reports in the median        bool stale;         // true if quorum was missed and the previous value was carried    }    event EpochFinalized(bytes32 indexed asset, uint64 indexed epoch, int256 bps, uint16 reports, bool stale);    event EpochHeld(bytes32 indexed asset, uint64 indexed epoch, int256 proposedBps, int256 previousBps);    event AssetFrozen(bytes32 indexed asset, bool frozen);    event SourceSet(bytes32 indexed asset, Source source, address oracle);    error UnknownAsset(bytes32 asset);    error InvalidWindow(uint64 from, uint64 to);    error NotEnoughSamples(uint256 available, uint256 required);    /// @notice Latest finalized value. Entry and mark price for Kimp Contracts.    function latest(bytes32 asset) external view returns (int256 bps, uint64 timestamp);    /// @notice Time-weighted average of finalized samples in [from, to).    function twap(bytes32 asset, uint64 from, uint64 to) external view returns (int256 bps, uint256 samples);    /// @notice Finalized value for a given epoch.    function epochOf(bytes32 asset, uint64 epoch) external view returns (Epoch memory);    /// @notice True if no finalized update for 5 minutes, or the asset is frozen.    function isStale(bytes32 asset) external view returns (bool);    /// @notice Finalizes an epoch once its submission window closes. Permissionless.    function finalize(bytes32 asset, uint64 epoch) external;    /// @notice Switches the Upbit KRW price source. onlyTimelock.    function setSource(bytes32 asset, Source source, address oracle) external;}

IKimpReporterRegistry#

The registry holds reporter bonds, accepts signed reports, flags deviations and runs disputes. Bonds unbond over 14 days. The dispute window is 30 minutes after finalization.

Solidity
interface IKimpReporterRegistry {    struct Report {        bytes32 asset;        uint64 epoch;        uint256 upbitKrw;    // KRW-<ASSET> last trade, 18 decimals        uint256 globalUsd;   // median of global venues, 18 decimals        uint256 usdKrw;      // FX mid, 18 decimals        int256 bps;          // computed kimp in basis points    }    struct Dispute {        address challenger;        address reporter;        bytes32 asset;        uint64 epoch;        bytes32 evidenceHash;        uint256 bond;        uint8 status;        // 0 open, 1 upheld, 2 rejected, 3 escalated    }    event Bonded(address indexed reporter, uint256 amount);    event UnbondRequested(address indexed reporter, uint256 amount, uint64 availableAt);    event Flagged(address indexed reporter, bytes32 indexed asset, uint64 epoch, int256 deviationBps);    event Slashed(address indexed reporter, uint256 amount, uint256 burned, uint256 toChallenger);    event Suspended(address indexed reporter);    event DisputeOpened(uint256 indexed id, address indexed challenger, address indexed reporter);    event DisputeResolved(uint256 indexed id, bool upheld);    error NotActiveReporter(address reporter);    error BadSignature(address reporter);    error DisputeWindowClosed(uint64 epoch);    error UnbondingNotElapsed(uint64 availableAt);    /// @notice Bond $KIMP to join or top up. Minimum bond set by governance.    function bond(uint256 amount) external;    /// @notice Start the 14-day unbonding period.    function requestUnbond(uint256 amount) external;    /// @notice Withdraw unbonded $KIMP after 14 days.    function withdrawBond() external;    /// @notice Submit signed reports for the current epoch. Forwarded to KimpIndex.    function submit(Report[] calldata reports, bytes[] calldata signatures) external;    /// @notice Open a dispute within 30 minutes of finalization. Requires the dispute bond.    function openDispute(address reporter, bytes32 asset, uint64 epoch, bytes32 evidenceHash) external returns (uint256 id);    /// @notice Resolve a dispute. Dispute Committee only, executed through the timelock.    function resolveDispute(uint256 id, bool upheld, uint256 slashAmount) external;    function activeReporters() external view returns (address[] memory);    function bondOf(address reporter) external view returns (uint256);}

IKimpMarket#

The market holds positions and enforces margin, limits and fees. Entry and mark use KimpIndex.latest. settle records the one-hour TWAP for an expired series. Positions of a settled series are paid out with redeem.

Solidity
interface IKimpMarket {    enum Side { Long, Short }    enum Lane { Open, Verified }    enum State { Active, ReduceOnly, Paused }    struct Position {        address owner;        bytes32 asset;        uint64 seriesExpiry;   // Friday 08:00 UTC        Side side;        Lane lane;        uint256 notionalUsd;        uint256 marginUsd;        int256 entryBps;    }    struct OpenParams {        bytes32 asset;        Side side;        Lane lane;        uint256 notionalUsd;        address collateral;    // ETH (address(0)) or USDC        uint256 collateralAmount;        int256 worstEntryBps;  // slippage bound on the index    }    event Opened(uint256 indexed id, address indexed owner, bytes32 indexed asset, Side side, Lane lane, uint256 notionalUsd, int256 entryBps);    event Increased(uint256 indexed id, uint256 notionalUsd, uint256 marginUsd);    event Closed(uint256 indexed id, uint256 notionalUsd, int256 exitBps, int256 pnlUsd, uint256 feeUsd);    event SeriesSettled(bytes32 indexed asset, uint64 indexed expiry, int256 twapBps);    event Liquidated(uint256 indexed id, address indexed keeper, uint256 penaltyUsd, uint256 keeperRewardUsd);    event StateChanged(bytes32 indexed asset, State state);    error MarketNotActive(bytes32 asset, State state);    error LeverageTooHigh(uint256 leverageX100, uint256 maxX100);    error PositionLimit(uint256 notionalUsd, uint256 limitUsd);    error CapExceeded(bytes32 asset);    error SlippageExceeded(int256 entryBps, int256 worstEntryBps);    error NotLiquidatable(uint256 id);    error SeriesNotExpired(uint64 expiry);    /// @notice Open a position at the latest finalized index value.    function open(OpenParams calldata p) external payable returns (uint256 id);    /// @notice Increase notional. Verified Lane positions re-check the gate.    function increase(uint256 id, uint256 notionalUsd, uint256 collateralAmount) external payable;    /// @notice Close all or part of a position. Always allowed, including in reduce-only and paused states.    function close(uint256 id, uint256 notionalUsd, int256 worstExitBps) external returns (int256 pnlUsd);    /// @notice Record the settlement TWAP for an expired series. Permissionless.    function settle(bytes32 asset, uint64 expiry) external returns (int256 twapBps);    /// @notice Pay out a position of a settled series.    function redeem(uint256 id) external returns (uint256 amountUsd);    /// @notice Liquidate a position whose equity is at or below maintenance margin. Permissionless.    function liquidate(uint256 id) external returns (uint256 keeperRewardUsd);    function positions(uint256 id) external view returns (Position memory);    function equity(uint256 id) external view returns (int256 equityUsd);    function state(bytes32 asset) external view returns (State);    /// @notice onlyGuardian.    function pause(bytes32 asset) external;    function unpause(bytes32 asset) external;}

IKimpPool#

The pool is the counterparty vault. kLP is minted and burned at nav() / totalSupply(). Withdrawals are instant while utilization after the withdrawal stays at or below 80%, and queued otherwise.

Solidity
interface IKimpPool {    event Deposited(address indexed account, address indexed asset, uint256 amount, uint256 klpOut);    event Withdrawn(address indexed account, address indexed asset, uint256 klpIn, uint256 amountOut);    event WithdrawRequested(uint256 indexed requestId, address indexed account, uint256 klpIn, address assetOut);    event WithdrawCancelled(uint256 indexed requestId);    event QueueProcessed(uint64 indexed expiry, uint256 requests, uint256 klpBurned);    error UtilizationTooHigh(uint256 utilizationBps, uint256 maxBps);    error UnsupportedAsset(address asset);    error SlippageExceeded(uint256 out, uint256 minOut);    /// @notice Deposit ETH (address(0)) or USDC and mint kLP. No fee.    function deposit(address asset, uint256 amount, uint256 minKlpOut) external payable returns (uint256 klpOut);    /// @notice Instant withdrawal. Reverts if utilization after withdrawal exceeds 80%.    function withdraw(uint256 klpIn, address assetOut, uint256 minAmountOut) external returns (uint256 amountOut);    /// @notice Queue a withdrawal for the next weekly settlement. Locks kLP.    function requestWithdraw(uint256 klpIn, address assetOut) external returns (uint256 requestId);    function cancelWithdraw(uint256 requestId) external;    /// @notice Net asset value in USD, net of unrealized trader P&L.    function nav() external view returns (uint256 navUsd);    function klpPrice() external view returns (uint256 usdPerKlp);    function utilization() external view returns (uint256 bps);}

IKimpVerifiedGate#

The gate wraps DojangScroll. The attester ID and scroll address are immutable. The exact modifier is shown in Contract interface.

Solidity
type DojangAttesterId is bytes32;interface IDojangScroll {    function isVerified(address addr, DojangAttesterId attesterId) external view returns (bool);}interface IKimpVerifiedGate {    event LeaderboardOptInSet(address indexed account, bool optedIn);    error NotVerified(address account);    function dojangScroll() external view returns (IDojangScroll);    function upbitKorea() external view returns (DojangAttesterId);    /// @notice True if the account holds a valid Verified Address attestation from Upbit Korea.    function isVerified(address account) external view returns (bool);    /// @notice Opt in or out of the Verified Lane leaderboard. Stores a boolean only.    function setLeaderboardOptIn(bool optedIn) external;    function leaderboardOptIn(address account) external view returns (bool);}

IKimpStaking#

Stakers receive 30% of base fees, from which reporters are paid. Unstaking has a 7-day cooldown with no rewards.

Solidity
interface IKimpStaking {    event Staked(address indexed account, uint256 amount);    event UnstakeRequested(address indexed account, uint256 amount, uint64 availableAt);    event Unstaked(address indexed account, uint256 amount);    event Claimed(address indexed account, uint256 ethAmount, uint256 usdcAmount);    error CooldownNotElapsed(uint64 availableAt);    error NothingToClaim();    function stake(uint256 amount) external;    /// @notice Start the 7-day cooldown. Stake stops earning and voting immediately.    function requestUnstake(uint256 amount) external;    function completeUnstake() external returns (uint256 amount);    /// @notice Claim accrued fee share in ETH and USDC.    function claim() external returns (uint256 ethAmount, uint256 usdcAmount);    function stakeOf(address account) external view returns (uint256);    function getVotes(address account) external view returns (uint256);}

IKimpBuyback#

Receives 20% of base fees. execute is permissionless, runs at most once per 24 hours, and reverts if the swap deviates more than 1% from the DEX TWAP.

Solidity
interface IKimpBuyback {    event Executed(uint256 ethIn, uint256 usdcIn, uint256 kimpBought, uint256 twapPrice);    event Burned(uint256 amount);    error TooSoon(uint64 nextAt);    error PriceGuard(uint256 received, uint256 minOut);    /// @notice Swap accumulated fees for $KIMP and burn it. Permissionless.    function execute() external returns (uint256 kimpBurned);    function lastExecution() external view returns (uint64);    function nextExecutionAt() external view returns (uint64);}