Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

시스템 모듈 사용

Stable은 고정된 주소의 사전 컴파일된 컨트랙트를 통해 프로토콜 수준 로직을 노출합니다. 애플리케이션 컨트랙트에서 Stable SDK 동작을 다시 구현하는 대신 Solidity 또는 ethers.js에서 이러한 사전 컴파일을 호출할 수 있습니다.

노출되는 기능

모듈사전 컴파일 주소용도
Bank0x0000000000000000000000000000000000001003STABLE 토큰 전송 및 잔액 작업
Distribution0x0000000000000000000000000000000000000801스테이킹 보상 청구, 보상 조회, 수수료 관리
Staking0x0000000000000000000000000000000000000800위임, 위임 해제, 재위임, 검증자 조회
Gov0x0000000000000000000000000000000000000805제안, 집계 결과 및 온체인 투표 기록
Slashing0x0000000000000000000000000000000000000806검증자 서명 정보 및 가동 시간
StableSystem0x0000000000000000000000000000000000009999시스템 트랜잭션에 대한 보장된 블록 공간 레인 쿼리 및 EVM 이벤트 방출

읽기 메서드는 모든 EVM 컨트랙트 또는 오프체인 클라이언트에서 호출할 수 있습니다. 일부 상태 변경 메서드는 호출자 권한을 강제하며, notifySystemTxLogs()는 프로토콜에서 생성된 시스템 트랜잭션만 허용합니다. 주소는 메인넷과 테스트넷에서 동일합니다.

사전 컴파일 호출 시점 vs 일반 컨트랙트 호출 시점

  • 사전 컴파일 사용: 작업이 Stable SDK 모듈(스테이킹, 보상 분배, STABLE 토큰 작업)에 매핑될 때 사용합니다. 사전 컴파일을 호출하는 것이 더 저렴하며 프로토콜 수준 동작을 트리거하는 유일한 방법입니다.
  • 일반 컨트랙트 사용: 작업이 애플리케이션 로직(에스크로, 가격 책정, 접근 제어)일 때 사용합니다. 사용자 지정 권한 부여 또는 유효성 검사가 필요한 경우 사전 컴파일 호출을 자체 컨트랙트에 래핑하십시오.

사전 컴파일은 애플리케이션 컨트랙트를 대체하지 않습니다. 이는 기본 프로토콜에 대한 안정적인 인터페이스입니다.

Solidity에서 호출

필요한 메서드에 대한 인터페이스를 선언한 다음, 배포된 컨트랙트인 것처럼 사전 컴파일을 호출합니다.

검증자의 EVM 주소를 스테이킹 메서드에 전달합니다. 사전 컴파일은 Bech32 검증자-운영자 문자열을 허용하지 않습니다.

// SAFE: the precompile address is fixed on Stable.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
 
struct Coin {
    string denom;
    uint256 amount;
}
 
interface IStaking {
    function delegate(
        address delegatorAddress,
        address validatorAddress,
        uint256 amount
    ) external returns (bool success);
 
    function delegation(
        address delegatorAddress,
        address validatorAddress
    ) external view returns (uint256 shares, Coin memory balance);
}
 
contract StakingHelper {
    address constant STAKING_PRECOMPILE =
        0x0000000000000000000000000000000000000800;
 
    /// @notice Delegate STABLE tokens to a validator from this contract.
    function delegateToValidator(
        address validatorAddress,
        uint256 amount
    ) external returns (bool) {
        return IStaking(STAKING_PRECOMPILE).delegate(
            address(this),
            validatorAddress,
            amount
        );
    }
 
    /// @notice Read the current delegation of this contract to a validator.
    function myDelegation(address validatorAddress)
        external
        view
        returns (uint256 shares, Coin memory balance)
    {
        return IStaking(STAKING_PRECOMPILE).delegation(
            address(this),
            validatorAddress
        );
    }
}

Foundry 또는 Hardhat으로 컴파일하고 배포합니다. 사전 컴파일 주소는 상수 슬롯에 컨트랙트에 고정되어 있으므로 배포 후 연결할 필요가 없습니다.

ethers.js에서 호출

오프체인 클라이언트의 경우, 동일한 인터페이스를 최소 ABI로 선언하고 사전 컴파일 주소를 가리키는 컨트랙트를 인스턴스화합니다.

// queryDelegation.ts
import { ethers } from "ethers";
import "dotenv/config";
 
const provider = new ethers.JsonRpcProvider("https://rpc.testnet.stable.xyz");
 
const STAKING_PRECOMPILE = "0x0000000000000000000000000000000000000800";
 
const staking = new ethers.Contract(
  STAKING_PRECOMPILE,
  [
    "function delegation(address delegator, address validator) view returns (uint256 shares, (string denom, uint256 amount) balance)",
  ],
  provider
);
 
const delegator = "0x1111111111111111111111111111111111111111";
const validator = "0x2222222222222222222222222222222222222222";
 
const [shares, balance] = await staking.delegation(delegator, validator);
console.log("Delegation shares: ", shares.toString());
console.log("Delegation denomination:", balance.denom);
console.log("Delegation amount:", balance.amount.toString());
npx tsx queryDelegation.ts
Delegation shares:  <share amount>
Delegation denomination: <staking denomination>
Delegation amount: <base-unit amount>

시스템 트랜잭션 이벤트 구독

일부 Stable SDK 작업(예: 언본딩 완료)은 자연스럽게 EVM 이벤트를 발생시키지 않습니다. Stable은 시스템 트랜잭션을 통해 이 격차를 해소합니다. 이는 다음 블록 동안 표준 EVM 이벤트를 발생시키기 위해 StableSystem 사전 컴파일을 호출하는 검증자 생성 트랜잭션입니다.

UnbondingCompleted를 보려면 ERC-20 Transfer 리스너와 마찬가지로 사전 컴파일 주소에서 구독하십시오.

// watchUnbonding.ts
import { ethers } from "ethers";
 
const provider = new ethers.JsonRpcProvider("https://rpc.testnet.stable.xyz");
 
const STABLE_SYSTEM = "0x0000000000000000000000000000000000009999";
 
const stableSystem = new ethers.Contract(
  STABLE_SYSTEM,
  [
    "event UnbondingCompleted(address indexed delegator, address indexed validator, uint64 indexed originBlockHeight, uint256 amount)",
  ],
  provider
);
 
stableSystem.on("UnbondingCompleted", (delegator, validator, originBlockHeight, amount, event) => {
  console.log("Unbonding completed for:", delegator);
  console.log("Origin block:", originBlockHeight.toString());
  console.log("Amount:", ethers.formatEther(amount), "STABLE");
  console.log("Tx:", event.log.transactionHash);
});
 
console.log("Listening for UnbondingCompleted events...");
npx tsx watchUnbonding.ts
Listening for UnbondingCompleted events...
Unbonding completed for: 0xabcd...
Origin block: 36975999
Amount: 100.0 STABLE
Tx: 0x12ab...

전체 시스템 트랜잭션 메커니즘 및 사용자별 필터 / 기록 쿼리 패턴에 대한 자세한 내용은 언본딩 완료 추적을 참조하십시오.

모듈별 참조

각 사전 컴파일의 전체 메서드 목록, 이벤트 및 권한 부여 규칙은 참조 페이지에 있습니다.

다음 단계

  • 언본딩 완료 추적: StableSystem 사전 컴파일을 통해 발생되는 UnbondingCompleted 이벤트를 구독합니다.
  • 시스템 모듈 참조: 모듈별 ABI, 메서드 서명 및 이벤트 스키마로 이동합니다.
  • 시스템 모듈 개념: Stable이 사전 컴파일을 통해 SDK 모듈을 노출하는 이유를 이해합니다.