Address
octGgEB5…Pz3F8f
octGgEB5fJUnxD6U77rFdWomUTxFSpBVhJeaTxT5oPz3F8f
State
OCT balance
0OCT
wallet balance
Type
Contract
smart contract on chain
Chain-level
View on Octrascan · devnet ↗
raw txs · nonce · pubkey
Pipoke (no profile)
this wallet has not registered a Pipoke profile
Contract
History
live · 20s · last 0Source · ABI · Bytecode✓ verifiedexpand →
Source · ABI · Bytecode
✓ verified✓ verified
interface stxOwnable {
fn owner(): address
fn transfer_ownership(new_owner: address): bool
}
interface stxMetadata {
fn name(): string
fn symbol(): string
fn collection_uri(): string
fn token_uri(token_id: int): string
}
interface stxTransferable {
fn transfer(to: address, token_id: int): bool
fn transfer_from(from: address, to: address, token_id: int): bool
}
interface stxApprovable {
fn approve(approved: address, token_id: int): bool
fn set_approval_for_all(operator: address, approved: int): bool
fn get_approved(token_id: int): address
fn is_approved_for_all(owner_addr: address, operator: address): int
}
interface stxRoyalty {
fn royalty_info(token_id: int, sale_price: int): (address, int)
}
interface stxEnumerable {
fn total_supply(): int
fn circulating_supply(): int
fn balance_of(addr: address): int
fn token_of_owner_by_index(owner_addr: address, index: int): int
fn exists(token_id: int): int
}
interface stxBurnable {
fn burn(token_id: int): bool
fn burned_supply(): int
}
interface stxSoulbound {
fn bind(token_id: int): bool
fn is_soulbound(token_id: int): int
}
interface stxPausable {
fn pause(): bool
fn unpause(): bool
fn is_paused(): int
}
interface stxMintable {
fn max_supply(): int
fn mint_price(): int
fn mints_remaining(addr: address): int
fn airdrop_remaining(): int
}
interface stxForgeable {
fn forge(a: int, b: int, c: int, private_trait_ct: bytes): int
}
interface stxPrivateTrait {
fn re_encrypt_trait(token_id: int, new_ct: bytes): bool
fn has_private_trait(token_id: int): int
fn private_trait_of(token_id: int): bytes
}
contract OHC721 implements
stxOwnable, stxMetadata, stxTransferable, stxApprovable,
stxRoyalty, stxEnumerable, stxBurnable, stxSoulbound,
stxPausable, stxMintable, stxForgeable, stxPrivateTrait {
const MAX_SUPPLY = 888
const MAX_PER_WALLET = 5
const AIRDROP_RESERVE = 18
const VAULT_THRESHOLD = 188
const VAULT_CONTRIBUTION = 10000000
const MAX_ROYALTY = 1000
const ZERO_ADDRESS: address = "oct1111111111111111111111111111111111111111111"
struct Token {
owner: address
minted_epoch: int
seed: int
layer_tier: int
enhancement: int
soulbound: int
private_trait: bytes
}
state {
contract_owner: address
royalty_recip: address
royalty_bps: int
name: string
symbol: string
base_uri: string
collection_uri: string
provenance_hash: string
provenance_locked: int
paused: int
mint_price: int
total_supply: int
burned_supply: int
airdrop_minted: int
forge_minted: int
tokens: map[int]Token
balances: map[address]int
owned_tokens: map[address]map[int]int
token_index: map[int]int
approvals: map[int]address
operator_approvals: map[address]map[address]int
mint_count: map[address]int
vault_addr: address
treasury_addr: address
}
event Minted(token_id: int, owner: address, layer_tier: int)
event Airdropped(token_id: int, to: address, layer_tier: int)
event Transferred(token_id: int, from: address, to: address)
event Approved(token_id: int, approved: address)
event ApprovalForAll(owner: address, operator: address, approved: int)
event Burned(token_id: int, owner: address)
event Forged(new_token_id: int, burned_a: int, burned_b: int, burned_c: int, owner: address)
event Bound(token_id: int, owner: address)
event VaultForwarded(vault: address, amount: int, mint_index: int)
event TraitReEncrypted(token_id: int, owner: address)
event OwnershipTransferred(previous: address, new_owner: address)
event Paused(by: address)
event Unpaused(by: address)
event MintPriceUpdated(old_price: int, new_price: int)
event RoyaltyUpdated(recipient: address, bps: int)
event ProvenanceLocked(hash: string)
event CollectionURISet(uri: string)
event BaseURISet(uri: string)
error NotOwner(403, "caller is not the contract owner")
error NotTokenOwner(403, "caller is not the token owner")
error NotAuthorized(403, "not authorized")
error ContractPaused(503, "contract is paused")
error MaxSupplyReached(400, "collection is fully minted")
error PublicSoldOut(400, "public supply is sold out")
error AirdropExhausted(400, "airdrop quota exhausted")
error TokenNotFound(404, "token does not exist")
error TokenBurned(410, "token has been burned")
error InvalidRoyalty(400, "royalty bps exceeds maximum")
error SelfOperator(400, "operator cannot be caller")
error InsufficientPayment(402, "insufficient payment")
error WalletLimitReached(400, "wallet mint limit reached")
error IsSoulbound(403, "token is soulbound")
error AlreadySoulbound(400, "already soulbound")
error DuplicateTokenIds(400, "forge requires three distinct token ids")
error NoFHEKey(403, "no fhe key registered for caller")
error ProvenanceAlreadyLocked(400, "provenance already locked")
error InvalidPrice(400, "price must be greater than vault contribution")
constructor(n: string, s: string, price: int) {
self.contract_owner = origin
self.royalty_recip = origin
self.royalty_bps = 500
self.name = n
self.symbol = s
self.base_uri = ""
self.collection_uri = ""
self.provenance_hash = ""
self.provenance_locked = 0
self.paused = 0
self.mint_price = price
self.total_supply = 0
self.burned_supply = 0
self.airdrop_minted = 0
self.forge_minted = 0
self.vault_addr = ZERO_ADDRESS
self.treasury_addr = ZERO_ADDRESS
}
private fn only_owner() {
require(caller == self.contract_owner, "not owner")
}
private fn not_paused() {
require(self.paused == 0, "contract paused")
}
private fn require_token(token_id: int) {
require(token_id >= 0, "token not found")
require(token_id < self.total_supply, "token not found")
require(self.tokens[token_id].owner != ZERO_ADDRESS, "token burned")
}
private fn map_layer_tier(raw: int): int {
if raw >= 884 { return 7 }
if raw >= 871 { return 6 }
if raw >= 835 { return 5 }
if raw >= 764 { return 4 }
if raw >= 649 { return 3 }
if raw >= 489 { return 2 }
if raw >= 267 { return 1 }
return 0
}
private fn map_enhancement(raw: int): int {
if raw >= 9 { return 3 }
if raw >= 8 { return 2 }
if raw >= 6 { return 1 }
return 0
}
private fn _add_token_enum(to: address, token_id: int) {
self.owned_tokens[to][self.balances[to]] = token_id
self.token_index[token_id] = self.balances[to]
}
private fn _remove_token_enum(from: address, token_id: int) {
let a = self.token_index[token_id]
let i = self.balances[from] - 1
if a != i {
let id = self.owned_tokens[from][i]
self.owned_tokens[from][a] = id
self.token_index[id] = a
}
self.owned_tokens[from][i] = 0
self.token_index[token_id] = 0
}
private fn _burn_internal(token_id: int, from: address) {
_remove_token_enum(from, token_id)
self.balances[from] -= 1
self.tokens[token_id].owner = ZERO_ADDRESS
self.approvals[token_id] = ZERO_ADDRESS
self.burned_supply += 1
emit Burned(token_id, from)
}
private fn _forge_validate(a: int, b: int, c: int) {
require(a != b, "duplicate token ids")
require(b != c, "duplicate token ids")
require(a != c, "duplicate token ids")
require_token(a)
require_token(b)
require_token(c)
require(self.tokens[a].owner == caller, "must own all three")
require(self.tokens[b].owner == caller, "must own all three")
require(self.tokens[c].owner == caller, "must own all three")
require(self.tokens[a].soulbound == 0, "soulbound token")
require(self.tokens[b].soulbound == 0, "soulbound token")
require(self.tokens[c].soulbound == 0, "soulbound token")
}
private fn _apply_traits(id: int, to: address, seed: int) {
let layer_raw = (((seed * 1664525 + epoch * 22695477 + 9125138007) % 888) + 888) % 888
let enh_raw = (((seed * 1664525 + epoch * 22695477 + 10139042230) % 10) + 10) % 10
let boosted = layer_raw
if id == 0 { boosted = 887 }
if id > 0 {
if id < VAULT_THRESHOLD {
boosted = min(layer_raw + 50, 883)
}
}
self.tokens[id].owner = to
self.tokens[id].minted_epoch = epoch
self.tokens[id].seed = seed
self.tokens[id].layer_tier = map_layer_tier(boosted)
self.tokens[id].enhancement = map_enhancement(enh_raw)
self.tokens[id].soulbound = 0
}
private fn _apply_forge_traits(id: int, seed: int) {
let layer_raw = (((seed * 1664525 + epoch * 22695477 + 9125138007) % 239) + 239) % 239 + 649
let enh_raw = (((seed * 1664525 + epoch * 22695477 + 10139042230) % 4) + 4) % 4 + 6
self.tokens[id].owner = caller
self.tokens[id].minted_epoch = epoch
self.tokens[id].seed = seed
self.tokens[id].layer_tier = map_layer_tier(layer_raw)
self.tokens[id].enhancement = map_enhancement(enh_raw)
self.tokens[id].soulbound = 0
}
fn transfer_ownership(addr: address): bool {
only_owner()
assert_address(addr)
require(addr != ZERO_ADDRESS, "cannot transfer to zero address")
let from = self.contract_owner
self.contract_owner = addr
emit OwnershipTransferred(from, addr)
return true
}
fn set_base_uri(uri: string): bool {
only_owner()
self.base_uri = uri
emit BaseURISet(uri)
return true
}
fn set_collection_uri(uri: string): bool {
only_owner()
self.collection_uri = uri
emit CollectionURISet(uri)
return true
}
fn set_mint_price(price: int): bool {
only_owner()
require(price > VAULT_CONTRIBUTION, "price must exceed vault contribution")
let old = self.mint_price
self.mint_price = price
emit MintPriceUpdated(old, price)
return true
}
fn set_royalty_bps(bps: int): bool {
only_owner()
require(bps >= 0, "negative royalty")
require(bps <= MAX_ROYALTY, "royalty exceeds maximum")
self.royalty_bps = bps
emit RoyaltyUpdated(self.royalty_recip, bps)
return true
}
fn set_royalty_recipient(addr: address): bool {
only_owner()
assert_address(addr)
self.royalty_recip = addr
emit RoyaltyUpdated(addr, self.royalty_bps)
return true
}
fn set_provenance(s: string): bool {
only_owner()
require(self.provenance_locked == 0, "provenance already locked")
self.provenance_hash = s
return true
}
fn lock_provenance(): bool {
only_owner()
require(self.provenance_locked == 0, "provenance already locked")
self.provenance_locked = 1
emit ProvenanceLocked(self.provenance_hash)
return true
}
fn pause(): bool {
only_owner()
self.paused = 1
emit Paused(caller)
return true
}
fn unpause(): bool {
only_owner()
self.paused = 0
emit Unpaused(caller)
return true
}
fn set_vault_contract(addr: address): bool {
only_owner()
assert_address(addr)
self.vault_addr = addr
return true
}
fn set_treasury_contract(addr: address): bool {
only_owner()
assert_address(addr)
self.treasury_addr = addr
return true
}
payable fn mint(qty: int, private_trait_ct: bytes): bool {
not_paused()
require(qty >= 1, "qty must be at least 1")
require(qty <= 5, "qty must be at most 5")
require(value >= self.mint_price * qty, "insufficient payment")
require(self.mint_count[caller] + qty <= MAX_PER_WALLET, "wallet mint limit reached")
require(self.total_supply - self.airdrop_minted - self.forge_minted + qty <= MAX_SUPPLY - AIRDROP_RESERVE, "public supply sold out")
require(self.treasury_addr != ZERO_ADDRESS, "treasury not configured")
let i = 0
while i < qty {
if self.vault_addr != ZERO_ADDRESS {
checkpoint()
let ok = transfer(self.vault_addr, VAULT_CONTRIBUTION)
if !ok { rollback() return false }
commit()
emit VaultForwarded(self.vault_addr, VAULT_CONTRIBUTION, self.total_supply)
checkpoint()
let b = transfer(self.treasury_addr, self.mint_price - VAULT_CONTRIBUTION)
if !b { rollback() return false }
commit()
} else {
checkpoint()
let ok = transfer(self.treasury_addr, self.mint_price)
if !ok { rollback() return false }
commit()
}
let id = self.total_supply
let seed = (((id * 1664525) + (epoch * 22695477)) % 888888887) + 1
_apply_traits(id, caller, seed)
self.tokens[id].private_trait = private_trait_ct
_add_token_enum(caller, id)
self.balances[caller] += 1
self.total_supply += 1
self.mint_count[caller] += 1
emit Minted(id, caller, self.tokens[id].layer_tier)
i = i + 1
}
if value > self.mint_price * qty {
checkpoint()
let a = transfer(caller, value - self.mint_price * qty)
if !a { rollback() return false }
commit()
}
return true
}
fn airdrop(to: address, private_trait_ct: bytes): int {
only_owner()
require(self.airdrop_minted < AIRDROP_RESERVE, "airdrop quota exhausted")
require(self.total_supply < MAX_SUPPLY, "max supply reached")
assert_address(to)
let id = self.total_supply
let seed = (((id * 1664525) + (epoch * 22695477)) % 888888887) + 1
_apply_traits(id, to, seed)
self.tokens[id].private_trait = private_trait_ct
_add_token_enum(to, id)
self.balances[to] += 1
self.total_supply += 1
self.airdrop_minted += 1
emit Airdropped(id, to, self.tokens[id].layer_tier)
return id
}
fn transfer(to: address, token_id: int): bool {
not_paused()
require_token(token_id)
let from = self.tokens[token_id].owner
require(caller == from, "not token owner")
require(self.tokens[token_id].soulbound == 0, "soulbound token")
assert_address(to)
require(to != ZERO_ADDRESS, "cannot transfer to zero address")
_remove_token_enum(from, token_id)
self.balances[from] -= 1
self.tokens[token_id].owner = to
_add_token_enum(to, token_id)
self.balances[to] += 1
self.approvals[token_id] = ZERO_ADDRESS
emit Transferred(token_id, from, to)
return true
}
fn transfer_from(from: address, to: address, token_id: int): bool {
not_paused()
require_token(token_id)
require(from == self.tokens[token_id].owner, "from is not token owner")
require(self.tokens[token_id].soulbound == 0, "soulbound token")
let approved = self.approvals[token_id]
let a = self.operator_approvals[from][caller]
require(caller == from || caller == approved || a == 1, "not authorized")
assert_address(to)
require(to != ZERO_ADDRESS, "cannot transfer to zero address")
_remove_token_enum(from, token_id)
self.balances[from] -= 1
self.tokens[token_id].owner = to
_add_token_enum(to, token_id)
self.balances[to] += 1
self.approvals[token_id] = ZERO_ADDRESS
emit Transferred(token_id, from, to)
return true
}
fn approve(approved: address, token_id: int): bool {
require_token(token_id)
require(caller == self.tokens[token_id].owner, "not token owner")
self.approvals[token_id] = approved
emit Approved(token_id, approved)
return true
}
fn set_approval_for_all(to: address, approved: int): bool {
require(to != caller, "self operator")
assert_address(to)
require(approved == 0 || approved == 1, "approved must be 0 or 1")
self.operator_approvals[caller][to] = approved
emit ApprovalForAll(caller, to, approved)
return true
}
fn burn(token_id: int): bool {
not_paused()
require_token(token_id)
let from = self.tokens[token_id].owner
require(caller == from, "not token owner")
require(self.tokens[token_id].soulbound == 0, "soulbound token")
_burn_internal(token_id, from)
return true
}
fn forge(a: int, b: int, c: int, private_trait_ct: bytes): int {
not_paused()
require(self.total_supply < MAX_SUPPLY, "max supply reached")
_forge_validate(a, b, c)
let seed = self.tokens[a].seed + self.tokens[b].seed * 3 + self.tokens[c].seed * 7
_burn_internal(a, caller)
_burn_internal(b, caller)
_burn_internal(c, caller)
let id = self.total_supply
_apply_forge_traits(id, seed)
self.tokens[id].private_trait = private_trait_ct
_add_token_enum(caller, id)
self.balances[caller] += 1
self.total_supply += 1
self.forge_minted += 1
emit Forged(id, a, b, c, caller)
return id
}
fn bind(token_id: int): bool {
not_paused()
require_token(token_id)
require(caller == self.tokens[token_id].owner, "not token owner")
require(self.tokens[token_id].soulbound == 0, "already soulbound")
self.tokens[token_id].soulbound = 1
emit Bound(token_id, caller)
return true
}
fn re_encrypt_trait(token_id: int, private_trait_ct: bytes): bool {
not_paused()
require_token(token_id)
require(caller == self.tokens[token_id].owner, "not authorized")
self.tokens[token_id].private_trait = private_trait_ct
emit TraitReEncrypted(token_id, caller)
return true
}
view fn owner(): address {
return self.contract_owner
}
view fn vault_contract(): address {
return self.vault_addr
}
view fn treasury_contract(): address {
return self.treasury_addr
}
view fn is_paused(): int {
return self.paused
}
view fn mint_price(): int {
return self.mint_price
}
view fn base_uri(): string {
return self.base_uri
}
view fn provenance(): string {
return self.provenance_hash
}
view fn name(): string {
return self.name
}
view fn symbol(): string {
return self.symbol
}
view fn collection_uri(): string {
return self.collection_uri
}
view fn token_uri(token_id: int): string {
require_token(token_id)
return concat(self.base_uri, to_string(token_id))
}
view fn royalty_info(token_id: int, price: int): (address, int) {
require_token(token_id)
return (self.royalty_recip, price * self.royalty_bps / 10000)
}
view fn total_supply(): int {
return self.total_supply
}
view fn burned_supply(): int {
return self.burned_supply
}
view fn circulating_supply(): int {
return self.total_supply - self.burned_supply
}
view fn balance_of(addr: address): int {
return self.balances[addr]
}
view fn token_of_owner_by_index(addr: address, i: int): int {
require(i >= 0, "index out of range")
require(i < self.balances[addr], "index out of range")
return self.owned_tokens[addr][i]
}
view fn exists(token_id: int): int {
if token_id < 0 { return 0 }
if token_id >= self.total_supply { return 0 }
return self.tokens[token_id].owner != ZERO_ADDRESS ? 1 : 0
}
view fn owner_of(token_id: int): address {
require_token(token_id)
return self.tokens[token_id].owner
}
view fn get_approved(token_id: int): address {
require_token(token_id)
return self.approvals[token_id]
}
view fn is_approved_for_all(addr: address, to: address): int {
return self.operator_approvals[addr][to]
}
view fn max_supply(): int {
return MAX_SUPPLY
}
view fn mints_remaining(addr: address): int {
return MAX_PER_WALLET - self.mint_count[addr]
}
view fn airdrop_remaining(): int {
return AIRDROP_RESERVE - self.airdrop_minted
}
view fn trait_hash(token_id: int): int {
require_token(token_id)
return self.tokens[token_id].seed * 1664525 + self.tokens[token_id].minted_epoch * 22695477
}
view fn layer_of(token_id: int): int {
require_token(token_id)
return self.tokens[token_id].layer_tier
}
view fn enhancement_of(token_id: int): int {
require_token(token_id)
require(caller == self.tokens[token_id].owner, "not authorized")
return self.tokens[token_id].enhancement
}
view fn is_soulbound(token_id: int): int {
require_token(token_id)
return self.tokens[token_id].soulbound
}
view fn seed_of(token_id: int): int {
require_token(token_id)
return self.tokens[token_id].seed
}
view fn has_private_trait(token_id: int): int {
require_token(token_id)
return len(to_string(self.tokens[token_id].private_trait)) > 0 ? 1 : 0
}
view fn private_trait_of(token_id: int): bytes {
require_token(token_id)
require(caller == self.tokens[token_id].owner, "not authorized")
return self.tokens[token_id].private_trait
}
}