{
address: "0x73f7dafa086d58aedd8146f40dd8a86fcf778b8f",
balance: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
"transactions": [],
code: "/*
Name: Hot Potatoe
Version: 0.0.3
*/
class HotPotatoe {
name = 'HOT Potatoe';
symbol = 'POTATOE';
decimals = 0;
totalSupply = number('0');
initPrice = number('1' + '000000000000000000'); // 1 ether
admin = '';
PotatoeType = {
idx: number(0),
minter: '',
owner: '',
debtor: '',
price: number(0),
parentIdx: number(-1),
initDate: number(0),
transfers: number(0),
cumulativePrice: number(0),
};
potatoes = []; // array of Potatoe
participants = {}; // mapping (address participant => mapping(uint256 potatoeIdx => string role))
Initialize(minterAddress) {} // event
Mint(potatoeIdx, minter) {} // event
Transfer(potatoeIdx, sender, to) {} // event
Steal(potatoeIdx, stealer) {} // event
Withdrawal(amount) {} // event
constructor() {
this.admin = msg.sender;
}
initialize() {
//require(msg.sender == this.admin, "ONLY_ADMIN");
require(this.potatoes.length == 0, "ONLY_ONCE");
this._mint(msg.sender, -1);
emit('Initialize', [msg.sender]);
}
potatoesCount() {
return [this.potatoes.length];
}
_mint(minter, parentIdx) {
minter = minter.toLowerCase();
const potatoeIdx = this.potatoes.length;
const potatoe = {
idx: potatoeIdx,
minter,
owner: address(this).address,
debtor: minter,
price: this.initPrice,
parentIdx,
initDate: number(block.timestamp),
transfers: number(0),
cumulativePrice: number(0),
};
this.potatoes.push(potatoe);
this._setHolding(minter, potatoeIdx, 'minter+debtor');
this.totalSupply = this.totalSupply.add(1);
emit('Mint', [potatoeIdx, minter]);
}
_nextPrice(currentPrice) {
const rewardPercent = number(150); // 150%
const price = currentPrice.mul(rewardPercent).div(100);
return [price];
}
price(potatoeIdx) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const price = potatoe.price;
return [price];
}
nextPrice(potatoeIdx) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const price = this._nextPrice(potatoe.price)[0];
return [price];
}
owner(potatoeIdx) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const owner = potatoe.owner;
return [owner];
}
debtor(potatoeIdx) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const debtor = potatoe.debtor;
return [debtor];
}
transfer(potatoeIdx, to) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const sender = msg.sender.toLowerCase();
require(potatoe.debtor == sender, "ONLY_DEBTOR");
require(address(this) != to, "INVALID_TARGET");
require(address(0) != to, "INVALID_TARGET");
to = to.toLowerCase();
require(potatoe.owner != to, "NO_BACKTRACK_TO_OWNER");
require(potatoe.minter != to, "NO_BACKTRACK_TO_MINTER");
const price = potatoe.price;
require(price.eq(msg.value), "INVALID_POTATOE_PRICE");
const treasureFees = msg.value.mul(1).div(1000); // 0.1% fees for the treasure
const minterFees = msg.value.mul(9).div(1000); // 0.9% fees for the minter
address(potatoe.minter).transfer(minterFees);
address(potatoe.owner).transfer(msg.value.sub(treasureFees).sub(minterFees)); // repay (+bonus-fees) the previous owner
if (potatoe.owner == potatoe.minter) {
this._setHolding(potatoe.owner, potatoeIdx, 'minter+retired');
} else if (potatoe.owner != address(this).address) {
this._setHolding(potatoe.owner, potatoeIdx, 'retired');
}
if (sender == potatoe.minter) {
this._setHolding(sender, potatoeIdx, 'minter+owner');
} else {
this._setHolding(sender, potatoeIdx, 'owner');
}
if (to == potatoe.minter) {
this._setHolding(to, potatoeIdx, 'minter+debtor');
} else {
this._setHolding(to, potatoeIdx, 'debtor');
}
potatoe.owner = sender; // new owner (old debtor)
potatoe.debtor = to; // new debtor
potatoe.transfers = potatoe.transfers.add(1);
if (sender != to) {
potatoe.cumulativePrice = potatoe.cumulativePrice.add(msg.value);
}
const newPrice = this._nextPrice(price)[0];
potatoe.price = newPrice; // new price
emit('Transfer', [potatoeIdx, sender, to]);
this._mint(msg.sender, potatoe.idx);
}
holdings(participantAddress) {
participantAddress = participantAddress.toLowerCase();
require(participantAddress in this.participants, "INVALID_PARTICIPANT");
const result = Object.entries(this.participants[participantAddress]).map((entry => {
const [potatoeIdx, role] = entry;
return potatoeIdx + ':' + role;
})).join(' ');
return [result];
}
_setHolding(participantAddress, potatoeIdx, role) {
participantAddress = participantAddress.toLowerCase();
if (! (participantAddress in this.participants)) {
this.participants[participantAddress] = {};
}
this.participants[participantAddress][potatoeIdx] = role;
}
steal(potatoeIdx) {
require(potatoeIdx in this.potatoes, "INVALID_POTATOE_ID");
const potatoe = this.potatoes[potatoeIdx];
const stealer = msg.sender.toLowerCase();
require(potatoe.owner != stealer, "INVALID_STEALER_OWNER");
require(potatoe.debtor != stealer, "INVALID_STEALER_DEBTOR");
const _stealPrice = this.nextPrice(potatoeIdx)[0];
require(_stealPrice.eq(msg.value), "INVALID_POTATOE_STEAL_PRICE");
potatoe.owner = stealer; // stealer is now the owner => he will not pay the transfer (transfer to himself)
potatoe.debtor = stealer;
potatoe.price = _stealPrice;
potatoe.cumulativePrice = potatoe.cumulativePrice.add(msg.value);
this._setHolding(stealer, potatoeIdx, 'stealer');
emit('Steal', [potatoeIdx, stealer]);
}
withdraw(amount) {
require(msg.sender == this.admin, "ONLY_ADMIN");
address(this.admin).transfer(amount);
emit('Withdrawal', [amount]);
}
}
// Events
HotPotatoe.prototype.Initialize.event = true;
HotPotatoe.prototype.Initialize.inputs = ['address indexed'];
HotPotatoe.prototype.Mint.event = true;
HotPotatoe.prototype.Mint.inputs = ['uint256 indexed', 'address indexed'];
HotPotatoe.prototype.Transfer.event = true;
HotPotatoe.prototype.Transfer.inputs = ['uint256 indexed', 'address indexed', 'address indexed'];
HotPotatoe.prototype.Steal.event = true;
HotPotatoe.prototype.Steal.inputs = ['uint256 indexed', 'address indexed'];
HotPotatoe.prototype.Withdrawal.event = true;
HotPotatoe.prototype.Withdrawal.inputs = ['uint256'];
// Methods
HotPotatoe.prototype._mint.internal = true;
HotPotatoe.prototype._nextPrice.internal = true;
HotPotatoe.prototype.transfer.payable = true;
HotPotatoe.prototype.transfer.inputs = ['uint256', 'address'];
HotPotatoe.prototype.price.view = true;
HotPotatoe.prototype.price.inputs = ['uint256'];
HotPotatoe.prototype.price.outputs = ['uint256'];
HotPotatoe.prototype.potatoesCount.view = true;
HotPotatoe.prototype.potatoesCount.outputs = ['uint256'];
HotPotatoe.prototype.nextPrice.view = true;
HotPotatoe.prototype.nextPrice.inputs = ['uint256'];
HotPotatoe.prototype.nextPrice.outputs = ['uint256'];
HotPotatoe.prototype.owner.view = true;
HotPotatoe.prototype.owner.inputs = ['uint256'];
HotPotatoe.prototype.owner.outputs = ['address'];
HotPotatoe.prototype.debtor.view = true;
HotPotatoe.prototype.debtor.inputs = ['uint256'];
HotPotatoe.prototype.debtor.outputs = ['address'];
HotPotatoe.prototype.holdings.view = true;
HotPotatoe.prototype.holdings.inputs = ['address'];
HotPotatoe.prototype.holdings.outputs = ['string'];
HotPotatoe.prototype._setHolding.internal = true;
HotPotatoe.prototype.steal.payable = true;
HotPotatoe.prototype.steal.inputs = ['uint256'];
HotPotatoe.prototype.withdraw.inputs = ['uint256'];
return HotPotatoe;
",
codeHash: "0x38bfd1abf92e59c02ef1cf580e5f0310eb66202c827d72430dda08a6f357d703",
codeAbi: {
0x06fdde03: {
constant: true,
"inputs": [],
name: "name",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x95d89b41: {
constant: true,
"inputs": [],
name: "symbol",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x313ce567: {
constant: true,
"inputs": [],
name: "decimals",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x18160ddd: {
constant: true,
"inputs": [],
name: "totalSupply",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0xb6add0f4: {
constant: true,
"inputs": [],
name: "initPrice",
outputs: [
{
name: "",
type: "uint256"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0xf851a440: {
constant: true,
"inputs": [],
name: "admin",
outputs: [
{
name: "",
type: "address"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0xaa7b0928: {
constant: true,
"inputs": [],
name: "PotatoeType",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x1b5b0f01: {
constant: true,
"inputs": [],
name: "potatoes",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x6c4470fb: {
constant: true,
"inputs": [],
name: "participants",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0xa8ac9b50: {
constant: true,
"inputs": [],
name: "prototype",
outputs: [
{
name: "",
type: "string"
}
],
payable: false,
stateMutability: "view",
type: "function"
},
0x36b14535: {
inputs: [
{
name: "minterAddress",
type: "address",
indexed: true
}
],
name: "Initialize",
"outputs": [],
stateMutability: "nonpayable",
type: "event"
},
0xf3cea549: {
inputs: [
{
name: "potatoeIdx",
type: "uint256",
indexed: true
},
{
name: "minter",
type: "address",
indexed: true
}
],
name: "Mint",
"outputs": [],
stateMutability: "nonpayable",
type: "event"
},
0x0a429aba: {
inputs: [
{
name: "potatoeIdx",
type: "uint256",
indexed: true
},
{
name: "sender",
type: "address",
indexed: true
},
{
name: "to",
type: "address",
indexed: true
}
],
name: "Transfer",
"outputs": [],
stateMutability: "nonpayable",
type: "event"
},
0xab64b03a: {
inputs: [
{
name: "potatoeIdx",
type: "uint256",
indexed: true
},
{
name: "stealer",
type: "address",
indexed: true
}
],
name: "Steal",
"outputs": [],
stateMutability: "nonpayable",
type: "event"
},
0x4e70a604: {
inputs: [
{
name: "amount",
type: "uint256",
indexed: false
}
],
name: "Withdrawal",
"outputs": [],
stateMutability: "nonpayable",
type: "event"
},
0x8129fc1c: {
"inputs": [],
name: "initialize",
"outputs": [],
stateMutability: "nonpayable",
type: "function"
},
0xf469c89c: {
"inputs": [],
name: "potatoesCount",
outputs: [
{
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
0x26a49e37: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
}
],
name: "price",
outputs: [
{
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
0x2821ca71: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
}
],
name: "nextPrice",
outputs: [
{
name: "",
type: "uint256"
}
],
stateMutability: "view",
type: "function"
},
0xa123c33e: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
}
],
name: "owner",
outputs: [
{
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
0x10361897: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
}
],
name: "debtor",
outputs: [
{
name: "",
type: "address"
}
],
stateMutability: "view",
type: "function"
},
0xb7760c8f: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
},
{
name: "to",
type: "address"
}
],
name: "transfer",
"outputs": [],
stateMutability: "payable",
type: "function"
},
0xdd3ced63: {
inputs: [
{
name: "participantAddress",
type: "address"
}
],
name: "holdings",
outputs: [
{
name: "",
type: "string"
}
],
stateMutability: "view",
type: "function"
},
0x9bcf5f0c: {
inputs: [
{
name: "potatoeIdx",
type: "uint256"
}
],
name: "steal",
"outputs": [],
stateMutability: "payable",
type: "function"
},
0x2e1a7d4d: {
inputs: [
{
name: "amount",
type: "uint256"
}
],
name: "withdraw",
"outputs": [],
stateMutability: "nonpayable",
type: "function"
}
},
contractName: "HotPotatoe",
storage: {
prototype: {
address: "0x73f7dafa086d58aedd8146f40dd8a86fcf778b8f"
},
name: "HOT Potatoe",
symbol: "POTATOE",
decimals: 0,
totalSupply: {
type: "BigNumber",
hex: "0x01"
string: "1"
ether: "0.000000000000000001"
},
initPrice: {
type: "BigNumber",
hex: "0x0de0b6b3a7640000"
string: "1000000000000000000"
ether: "1.0"
},
admin: "0x131a190fa22cb867abf58193bf9e7640e9fce682",
PotatoeType: {
idx: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
minter: "",
owner: "",
debtor: "",
price: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
parentIdx: {
type: "BigNumber",
hex: "-0x01"
},
initDate: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
transfers: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
cumulativePrice: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
}
},
potatoes: [
{
idx: 0,
minter: "0xccf8ba457dcad7ee6a0361c96846a0f79744b113",
owner: "0x73f7dafa086d58aedd8146f40dd8a86fcf778b8f",
debtor: "0xccf8ba457dcad7ee6a0361c96846a0f79744b113",
price: {
type: "BigNumber",
hex: "0x0de0b6b3a7640000"
string: "1000000000000000000"
ether: "1.0"
},
parentIdx: -1,
initDate: {
type: "BigNumber",
hex: "0x018089715388"
string: "1651573347208"
ether: "0.000001651573347208"
},
transfers: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
},
cumulativePrice: {
type: "BigNumber",
hex: "0x00"
string: "0"
ether: "0.0"
}
}
],
participants: {
0xccf8ba457dcad7ee6a0361c96846a0f79744b113: {
0: "minter+debtor"
}
}
},
storageHash: "0xb5193f92ac3d5c5c6b4f34b77b9d11cc38fc5d8508236e345904b6556ba232b6",
savedOnBlockNumber: {
type: "BigNumber",
hex: "0x0d"
string: "13"
ether: "0.000000000000000013"
}
}