Address
octFc9yn…18pr9z
octFc9ynSen79FarWJqsLExjJTHbp27iQAfy3CG9218pr9z
State
OCT balance
1OCT
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
collection: string
metadata_uri: string
royalty_bps: int
minted_epoch: int
}
event Minted(token_id: int, owner: address, collection: string)
event Transferred(token_id: int, from: address, to: address)
event Approved(token_id: int, approved: address)
event ApprovalForAll(owner: address, operator: address, approved: int)
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 = origin
self.name = n
self.symbol = s
self.total_supply = 0
}
fn mint(
to: address,
collection: string,
metadata_uri: string,
royalty_bps: int
): int {
require(caller == self.owner, "not authorized")
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 = caller
self.tokens[id].collection = collection
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, collection)
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")
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] = to
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")
let current_owner = self.tokens[token_id].owner
require(from == current_owner, "from is not 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] = to
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(caller == self.tokens[token_id].owner, "not owner")
self.approvals[token_id] = approved
emit Approved(token_id, approved)
return true
}
fn set_operator(operator: address, approved: int): bool {
require(operator != caller, "self operator")
self.operator_approvals[caller][operator] = approved
emit ApprovalForAll(caller, operator, approved)
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.tokens[token_id].collection
}
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 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.tokens[token_id].collection)
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))
return s
}
view fn is_approved_or_owner(token_id: int, addr: address): int {
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_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
}
}