Address
octCFgFC…rKX7kZ
octCFgFCTd5AgUySuY4ouMQ1rYmXXpZNTkaxt38mvrKX7kZ
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
contract SpectrumNFT {
struct NFT {
owner: address
creator: address
metadata_uri: string
royalty_bps: int
minted_epoch: int
}
event Minted(token_id: int, owner: address, creator: address)
event Transferred(token_id: int, from: address, to: address)
event Approved(token_id: int, approved: address)
event ApprovalRevoked(token_id: int)
event ApprovalForAll(owner: address, operator: address, approved: int)
event OwnershipTransferred(old_owner: address, new_owner: address)
const MAX_ROYALTY: int = 1000
state {
owner: address
name: string
symbol: string
total_supply: int
tokens: map[int]NFT
balances: map[address]int
approvals: map[int]address
operator_approvals: map[address]map[address]int
}
constructor(n: string, s: string) {
self.owner = caller
self.name = n
self.symbol = s
self.total_supply = 0
}
fn mint(
to: address,
creator: address,
metadata_uri: string,
royalty_bps: int
): int {
require(caller == self.owner, "not authorized")
require(is_address(to), "invalid to address")
require(to != 0, "cannot mint to zero address")
require(is_address(creator), "invalid creator address")
require(creator != 0, "invalid creator")
require(royalty_bps >= 0, "negative royalty")
require(royalty_bps <= MAX_ROYALTY, "max royalty 10%")
let id = self.total_supply
self.tokens[id].owner = to
self.tokens[id].creator = creator
self.tokens[id].metadata_uri = metadata_uri
self.tokens[id].royalty_bps = royalty_bps
self.tokens[id].minted_epoch = epoch
self.balances[to] += 1
self.total_supply += 1
emit Minted(id, to, creator)
emit Transferred(id, 0, to)
return id
}
fn transfer(to: address, token_id: int): bool {
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
require(is_address(to), "invalid address")
require(to != 0, "cannot transfer to zero address")
let current_owner = self.tokens[token_id].owner
require(caller == current_owner, "not owner")
require(to != current_owner, "already owner")
self.tokens[token_id].owner = to
self.balances[current_owner] -= 1
self.balances[to] += 1
self.approvals[token_id] = 0
emit Transferred(token_id, current_owner, to)
return true
}
fn transfer_from(from: address, to: address, token_id: int): bool {
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
require(is_address(to), "invalid address")
require(to != 0, "cannot transfer to zero address")
let current_owner = self.tokens[token_id].owner
require(from == current_owner, "from is not owner")
require(to != current_owner, "already owner")
let approved = self.approvals[token_id]
let is_operator = self.operator_approvals[from][caller]
require(
caller == current_owner ||
caller == approved ||
is_operator == 1,
"not authorized"
)
self.tokens[token_id].owner = to
self.balances[from] -= 1
self.balances[to] += 1
self.approvals[token_id] = 0
emit Transferred(token_id, from, to)
return true
}
fn approve(approved: address, token_id: int): bool {
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
require(is_address(approved), "invalid address")
require(approved != 0, "use revoke_approval to clear")
let current_owner = self.tokens[token_id].owner
let is_operator = self.operator_approvals[current_owner][caller]
require(
caller == current_owner ||
is_operator == 1,
"not authorized"
)
self.approvals[token_id] = approved
emit Approved(token_id, approved)
return true
}
fn revoke_approval(token_id: int): bool {
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
let current_owner = self.tokens[token_id].owner
let is_operator = self.operator_approvals[current_owner][caller]
require(
caller == current_owner ||
is_operator == 1,
"not authorized"
)
self.approvals[token_id] = 0
emit ApprovalRevoked(token_id)
return true
}
fn set_operator(operator: address, approved: int): bool {
require(operator != caller, "self operator")
require(is_address(operator), "invalid address")
require(operator != 0, "invalid operator")
require(approved == 0 || approved == 1, "invalid value")
self.operator_approvals[caller][operator] = approved
emit ApprovalForAll(caller, operator, approved)
return true
}
fn transfer_ownership(new_owner: address): bool {
require(caller == self.owner, "not owner")
require(is_address(new_owner), "invalid address")
require(new_owner != 0, "invalid address")
let old_owner = self.owner
self.owner = new_owner
emit OwnershipTransferred(old_owner, new_owner)
return true
}
view fn owner_of(token_id: int): address {
return self.tokens[token_id].owner
}
view fn creator_of(token_id: int): address {
return self.tokens[token_id].creator
}
view fn royalty_of(token_id: int): int {
return self.tokens[token_id].royalty_bps
}
view fn token_uri(token_id: int): string {
return self.tokens[token_id].metadata_uri
}
view fn collection_of(token_id: int): string {
return self.name
}
view fn balance_of(addr: address): int {
return self.balances[addr]
}
view fn get_approved(token_id: int): address {
return self.approvals[token_id]
}
view fn total_supply(): int {
return self.total_supply
}
view fn collection_name(): string {
return self.name
}
view fn symbol(): string {
return self.symbol
}
view fn is_approved_or_owner(token_id: int, addr: address): int {
require(addr != 0, "cannot query zero address")
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
let current_owner = self.tokens[token_id].owner
if addr == current_owner {
return 1
}
if self.approvals[token_id] == addr {
return 1
}
if self.operator_approvals[current_owner][addr] == 1 {
return 1
}
return 0
}
view fn get_token_info(token_id: int): string {
require(token_id >= 0, "invalid id")
require(token_id < self.total_supply, "token not found")
let s = to_string(token_id)
s = concat(s, "|")
s = concat(s, to_string(self.tokens[token_id].owner))
s = concat(s, "|")
s = concat(s, to_string(self.tokens[token_id].creator))
s = concat(s, "|")
s = concat(s, self.name)
s = concat(s, "|")
s = concat(s, to_string(self.tokens[token_id].royalty_bps))
s = concat(s, "|")
s = concat(s, to_string(self.tokens[token_id].minted_epoch))
s = concat(s, "|")
s = concat(s, self.tokens[token_id].metadata_uri)
return s
}
view fn get_contract_info(): string {
let s = self.name
s = concat(s, "|")
s = concat(s, self.symbol)
s = concat(s, "|")
s = concat(s, to_string(self.total_supply))
s = concat(s, "|")
s = concat(s, to_string(self.owner))
return s
}
}