Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 58 additions & 17 deletions interface.rsh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
// -----------------------------------------------
// Name: ALGO/ETH/CFX NFT Jam Reverse Auction
// Author: Nicholas Shellabarger
// Version: 1.0.2 - use Struct/Object instead of Tuple
// Version: 1.1.2 - add missing curator fee return
// Requires Reach v0.1.11-rc7 (27cb9643) or later
// -----------------------------------------------
// TODO calculate price change per second with more precision

// IMPORTS

Expand All @@ -18,9 +19,10 @@ const SERIAL_VER = 0; // serial version of reach app reserved to release identic

const DIST_LENGTH = 9; // number of slots to distribute proceeds after sale

const FEE_MIN_ACCEPT = 6000;
const FEE_MIN_CONSTRUCT = 5000;
const FEE_MIN_RELAY = 17000;
const FEE_MIN_ACCEPT = 6_000; // 0.006
const FEE_MIN_CONSTRUCT = 5_000; // 0.005
const FEE_MIN_RELAY = 1_7000; // 0.017
const FEE_MIN_CURATOR = 10_000; // 0.1

// FUNCS

Expand Down Expand Up @@ -86,6 +88,7 @@ const Params = Object({
acceptFee: UInt, // 0.008
constructFee: UInt, // 0.006
relayFee: UInt, // 0.007
curatorFee: UInt, // 0.1
});

const auctioneerInteract = {
Expand Down Expand Up @@ -115,6 +118,12 @@ const State = Struct([
["royaltyCap", UInt],
["who", Address],
["partTake", UInt],
["acceptFee", UInt],
["constructFee", UInt],
["relayFee", UInt],
["curatorFee", UInt],
["curatorAddr", Address],
["timestamp", UInt],
]);

export const Views = () => [
Expand All @@ -126,7 +135,7 @@ export const Views = () => [
export const Api = () => [
API({
touch: Fun([], Null),
acceptOffer: Fun([], Null),
acceptOffer: Fun([Address], Null),
cancel: Fun([], Null),
}),
];
Expand All @@ -152,6 +161,7 @@ export const App = (map) => {
acceptFee,
constructFee,
relayFee,
curatorFee,
} = declassify(interact.getParams());
});

Expand All @@ -166,21 +176,44 @@ export const App = (map) => {
royaltyCap,
acceptFee,
constructFee,
relayFee
relayFee,
curatorFee
)
.check(() => {
check(tokenAmount > 0, "tokenAmount must be greater than 0");
check(floorPrice > 0, "floorPrice must be greater than 0");
check(floorPrice <= startPrice, "floorPrice must be less than or equal to startPrice"); // fp < sp => auction, fp == sp => sale
check(
floorPrice <= startPrice,
"floorPrice must be less than or equal to startPrice"
); // fp < sp => auction, fp == sp => sale
check(endSecs > 0, "endSecs must be greater than 0");
check(distr.sum() <= royaltyCap, "distr sum must be less than or equal to royaltyCap");
check(royaltyCap == (10 * floorPrice) / 1000000, "royaltyCap must be 10x of floorPrice");
check(acceptFee >= FEE_MIN_ACCEPT, "acceptFee must be greater than or equal to minimum accept fee");
check(constructFee >= FEE_MIN_CONSTRUCT, "constructFee must be greater than or equal to minimum construct fee");
check(relayFee >= FEE_MIN_RELAY, "relayFee must be greater than or equal to minimum relay fee");
check(
distr.sum() <= royaltyCap,
"distr sum must be less than or equal to royaltyCap"
);
check(
royaltyCap == (10 * floorPrice) / 1000000,
"royaltyCap must be 10x of floorPrice"
);
check(
acceptFee >= FEE_MIN_ACCEPT,
"acceptFee must be greater than or equal to minimum accept fee"
);
check(
constructFee >= FEE_MIN_CONSTRUCT,
"constructFee must be greater than or equal to minimum construct fee"
);
check(
relayFee >= FEE_MIN_RELAY,
"relayFee must be greater than or equal to minimum relay fee"
);
check(
curatorFee >= FEE_MIN_CURATOR,
"curatorFee must be greater than or equal to minimum curator fee"
);
})
.pay([
amt + (constructFee + acceptFee + relayFee) + SERIAL_VER,
amt + (constructFee + acceptFee + relayFee + curatorFee) + SERIAL_VER,
[tokenAmount, token],
])
.timeout(relativeTime(ttl), () => {
Expand Down Expand Up @@ -218,10 +251,15 @@ export const App = (map) => {
royaltyCap: royaltyCap,
who: Auctioneer,
partTake: 0,
acceptFee,
constructFee,
relayFee,
curatorFee,
curatorAddr: Auctioneer,
timestamp: referenceConcensusSecs
};

// Step

const [state] = parallelReduce([initialState])
.define(() => {
v.state.set(State.fromObject(state));
Expand All @@ -235,7 +273,7 @@ export const App = (map) => {
"token balance accurate after closed"
)
.invariant(
implies(!state.closed, balance() == acceptFee + relayFee),
implies(!state.closed, balance() == acceptFee + relayFee + curatorFee),
"balance accurate before close"
)
// TODO add invariant balance accurate after close
Expand Down Expand Up @@ -267,7 +305,8 @@ export const App = (map) => {
];
})
// api: accepts offer
.api_(a.acceptOffer, () => {
.api_(a.acceptOffer, (cAddr) => {
check(cAddr != this, "cannot accept offer as curator");
return [
state.currentPrice,
(k) => {
Expand All @@ -288,13 +327,15 @@ export const App = (map) => {
transfer(cent).to(addr);
transfer(sellerTake).to(Auctioneer);
transfer([acceptFee + diff, [tokenAmount, token]]).to(this);
transfer(curatorFee).to(cAddr);
return [
{
...state,
currentPrice: bal,
who: this,
closed: true,
partTake,
curatorAddr: cAddr,
},
];
},
Expand All @@ -306,7 +347,7 @@ export const App = (map) => {
return [
(k) => {
k(null);
transfer([acceptFee, [tokenAmount, token]]).to(this);
transfer([acceptFee + curatorFee, [tokenAmount, token]]).to(this);
return [
{
...state,
Expand Down