Last active
December 10, 2017 05:40
-
-
Save alexvandesande/8a3840154fcb1957398482d57bc3ed35 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
One of the takeaways I had from the ENS workshop, is that if buying domains | |
from secundary services is easy and quick, it will take the pressure off the | |
main ENS system to be perfect. So since I didn’t see any decent reselling | |
contract I decided to try my luck on my own. It's not yet finalized but shows | |
some characteristics I want on the service. | |
## Both instant buy and actions | |
One of the feedbacks I had is that many domain owners do not know how to price | |
their own names. Some wanted to get rid of some test names they had, others | |
wanted to make sure they took the best out of their "investment". So this | |
contract allows both possibilities: an "instant buy" button and a possibility | |
of an auction. Once someone bids, instant buy is disabled | |
## Traditional Auctions | |
Auctions work the traditional way, with the highest bidder paying the top price. | |
To prevent sniping, new bid, the auction end date is extended for 24 hours. | |
To prevent someone from indefintely extending an auction by outbidding by a few | |
cents, it's not enough to outbid the last person, but to outbid them by a margin | |
that increases proportionally to how much the auction lasts. On the first day, | |
you need to outbid the last bid for at least 20%, then 40%, 60%, etc. | |
For example, if you want to participate on an auction that has lasted for | |
five days already, you need to double the last bidder and so on. | |
## Referral Fee | |
We want to encourage many entrepreneurs to be able to build competing | |
marketplaces without needing to create their own contracts, so I added an | |
optional referral fee. Referral amounts can be anything from 0% to 20% and | |
will go to anyone. Interface developers are encouraged to set it to | |
themselves and select any fee they want. This also means that by executing | |
the contract directly from the command line the buyer can have up to a 20% | |
discount on the purchase, something sellers should be aware of when setting prices. | |
Because of the rolling margin, you always need to outbid by at least 20%, | |
so bidders can't take advantadge of this to win a bid by underbidding. | |
*/ | |
pragma solidity ^0.4.2; | |
contract Deed { | |
address public owner; | |
address public previousOwner; | |
} | |
contract Registrar { | |
function transfer(bytes32 _hash, address newOwner); | |
function entries(bytes32 _hash) constant returns (uint, Deed, uint, uint, uint); | |
} | |
contract Reseller { | |
Registrar public registrar; | |
mapping (string => name) names; | |
mapping (address => uint256) canWithdraw; | |
event NameTransferred(string _name, address from, address to); | |
event NewInstantPrice(string _name, uint newPrice); | |
event NewMinimumBid(string _name, uint newMinimumBid); | |
event NewBid(string _name, uint bid); | |
struct name { | |
uint instantPrice; | |
uint minBid; | |
uint biddingStarted; | |
uint lastBid; | |
address lastBidder; | |
uint biddingEnds; | |
address referral; | |
uint referralAmount; | |
} | |
modifier onlyNameOwner(string _name) { | |
Deed deed; | |
(,deed,,,) = registrar.entries(sha3(_name)); | |
require(deed.previousOwner() == msg.sender); | |
_; | |
} | |
function Reseller(address hashRegistrar) { | |
registrar = Registrar(hashRegistrar); | |
} | |
function setInstantPrice(string _name, uint instantPrice) onlyNameOwner(_name) { | |
name storage n = names[_name]; | |
require(n.biddingStarted == 0); | |
n.instantPrice = instantPrice; | |
NewInstantPrice(_name, instantPrice); | |
} | |
function setMinBid(string _name, uint minimumBid) onlyNameOwner(_name) { | |
name storage n = names[_name]; | |
require(n.biddingStarted == 0); | |
n.minBid = minimumBid; | |
NewMinimumBid(_name, minimumBid); | |
} | |
// Only to be used internally | |
function transferName(string _name, address to, uint value) internal { | |
// Get the proper information | |
Deed deed; | |
(,deed,,,) = registrar.entries(sha3(_name)); | |
address previousOwner = deed.previousOwner(); | |
// transfer the name | |
registrar.transfer(sha3(_name), to); | |
NameTransferred(_name, previousOwner, to); | |
// Clear Name records | |
names[_name] = name({ | |
instantPrice: 0, | |
minBid: 0, | |
biddingStarted: 0, | |
lastBid:0, | |
lastBidder:0, | |
biddingEnds:0, | |
referral: 0, | |
referralAmount: 0 | |
}); | |
// and at last, pay the seller | |
previousOwner.transfer(value); | |
} | |
function returnName(string _name) onlyNameOwner(_name) { | |
name storage n = names[_name]; | |
require(n.biddingStarted == 0); | |
transferName(_name, msg.sender, 0); | |
} | |
function buyNow(string _name, address referral, uint referralAmount) payable { | |
require(msg.value >= names[_name].instantPrice); | |
name storage n = names[_name]; | |
require(n.biddingStarted == 0); // Once auctions started, instant buy is disabled | |
transferName(_name, msg.sender, msg.value); | |
referral.transfer((1000*n.lastBid*n.referralAmount)/1000); | |
} | |
// In order for auctions not to drag on forever bids need to be increasinly bigger | |
// to be valid. After 1 day, you need to outbid by at least 20%, after 2 days, 40% and so on | |
function minimumBid(string _name) constant returns (uint minBid) { | |
name storage n = names[_name]; | |
return n.biddingStarted == 0 ? | |
n.minBid : | |
n.lastBid + n.lastBid*20*(1 days + now - n.biddingStarted)/(1 days * 100); | |
} | |
function bid(string _name, address referral, uint referralAmount) payable { | |
require(msg.value > minimumBid(_name)); | |
require(referralAmount < 200); | |
// try to Withdraw any previous bids | |
tryWithdraw(); | |
name storage n = names[_name]; | |
require(now < n.biddingEnds); | |
canWithdraw[n.lastBidder] += n.lastBid; | |
n.lastBidder = msg.sender; | |
n.lastBid = msg.value; | |
n.biddingEnds = now + 24 hours; | |
// Referral are optional parameters | |
n.referral = referral; | |
n.referralAmount = referralAmount; | |
if (n.biddingStarted == 0) n.biddingStarted = now; | |
NewBid(_name, msg.value); | |
} | |
function finalizeAuction(string _name) { | |
name storage n = names[_name]; | |
require(now > n.biddingEnds); | |
n.referral.transfer((1000*n.lastBid*n.referralAmount)/1000); | |
transferName(_name, n.lastBidder, n.lastBid); | |
} | |
function tryWithdraw() { | |
uint withdrawalAmount = canWithdraw[msg.sender]; | |
canWithdraw[msg.sender] = 0; | |
// If it cannot withdraw, then revert the change | |
if(!msg.sender.send(withdrawalAmount)) canWithdraw[msg.sender] = withdrawalAmount; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment