메인 콘텐츠로 건너뛰기

스마트 컨트랙트

Savitri Network는 내장 토큰 표준, 거버넌스, 오라클 지원을 갖춘 네이티브 스마트 컨트랙트 런타임을 제공합니다.

컨트랙트 런타임

컨트랙트는 다음을 갖춘 격리된 환경(샌드박스)에서 실행됩니다:

  • 가스 계량: 각 연산은 무한 루프 방지를 위해 가스를 소비합니다
  • 스토리지 슬롯: Keccak256 해시 슬롯 주소를 통한 키-값 저장소
  • 이벤트 시스템: 컨트랙트가 외부 소비자를 위한 이벤트를 방출합니다
  • 메모리 모니터링: 런타임 메모리 제한으로 DoS 공격을 방지합니다
  • 업그레이드 지원: 거버넌스를 통해 컨트랙트를 업그레이드할 수 있습니다

토큰 표준

표준유형동등설명
SAVITRI-20대체 가능ERC-20토큰 전송, 승인, 허용량
SAVITRI-721대체 불가능 (NFT)ERC-721고유 토큰 소유권, 전송, 메타데이터
SAVITRI-1155멀티 에셋ERC-1155배치 작업, 혼합 대체/비대체 가능

내장 컨트랙트

거버넌스

온체인 제안 및 투표 시스템:

  • 제목, 설명, 투표 기간으로 제안 생성
  • 찬성/반대 투표
  • 승인된 제안 실행
  • FL (Federated Learning) 제안 특수화

자세한 내용은 거버넌스를 참조하세요.

오라클

외부 데이터 피드 시스템:

  • 오라클 제공자 등록
  • 데이터 요청 및 제출
  • 증명 검증
  • 스키마 검증

자세한 내용은 오라클 시스템을 참조하세요.

SDK를 통한 컨트랙트 상호작용

ContractClient 사용

use savitri_sdk::{ContractClient, Wallet, RpcClient};

let wallet = Wallet::from_private_key_hex("your_key")?;
let contract = ContractClient::from_url_and_wallet("http://localhost:8545", wallet)?;

// 컨트랙트 함수 호출
let tx_hash = contract.call_contract(
&"contract_address".to_string(),
b"transfer",
&encoded_args,
Some(0),
).await?;

TransactionBuilder 사용

use savitri_sdk::TransactionBuilder;

let tx = TransactionBuilder::new()
.to("contract_address")
.data(call_data) // function selector + encoded args
.value(0)
.nonce(nonce)
.fee(5_000_000_000_000_000) // 0.005 SAVT contract fee
.build_and_sign(&wallet)?;

스토리지 모델

컨트랙트는 Ethereum과 유사한 슬롯 기반 스토리지 모델을 사용합니다:

  • 슬롯 0-99: BaseContract용 예약 (소유자, 메타데이터)
  • 슬롯 100+: 컨트랙트 특정 스토리지

충돌을 방지하기 위해 Keccak256 해시를 통해 슬롯 주소가 파생됩니다:

balance_slot = keccak256(address || SLOT_BALANCES_BASE)
allowance_slot = keccak256(spender || keccak256(owner || SLOT_ALLOWANCES_BASE))

모든 값은 32바이트 배열로 저장됩니다 (숫자 유형은 little-endian).

가스 비용

연산가스 비용수수료 (SAVT)
컨트랙트 배포가변기본 0.005
컨트랙트 호출가변기본 0.005
스토리지 쓰기 (SSTORE)20,000기본 포함
스토리지 읽기 (SLOAD)200기본 포함
토큰 전송~50,0000.005
NFT 민트~80,0000.005
거버넌스 투표~30,0000.005

컨트랙트 배포

컨트랙트는 to = None이고 data 필드에 컨트랙트 바이트코드가 있는 특수 트랜잭션을 통해 배포됩니다:

let deploy_tx = TransactionBuilder::new()
// 없는 .to() -- 컨트랙트 배포를 나타냄
.data(contract_bytecode)
.value(0)
.nonce(nonce)
.fee(5_000_000_000_000_000)
.build_and_sign(&wallet)?;