Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.

updated tutorial contracts #29

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
247 changes: 247 additions & 0 deletions blind auction/blind-auction-with-renewal.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
//Sample contract
contract hashRegistry
{
address public auction;
address public election;
address public executive;

modifier onlyElection() {
if (msg.sender != election) throw;
_
}

modifier onlyAuction() {
if (msg.sender != auction) throw;
_
}

function changeExecutive(address newExecutive) {
executive = newExecutive;
}

struct Record {
address owner;
uint renewalDate;
mapping (string => string) metadata;
}

mapping (bytes32 => Record) public hashRegistry;

function newRegistry(bytes32 hash, address owner, uint renewalDate) onlyAuction {
hashRegistry[hash] = Record({owner: owner, renewalDate:renewalDate});
}

}

//Sample contract
contract BlindAuction {
// Structures and registries
struct Record {
address owner;
uint renewalDate;
uint previousPeriod;
}

struct Auction {
uint deadline;
uint priceOffered;
uint priceToBePaid;
uint bidPaid;
address currentWinner;
address currentTopBidder;
uint period;
uint firstRegistered;
address previousOwner;
}

struct SealedBid {
uint date;
uint deposit;
address bidder;
}

struct Bid {
bytes32 hashedName;
uint price;
uint period;
address owner;
bytes32 salt;
}

mapping (bytes32 => Record) public registry;
mapping (bytes32 => Auction) public auctions;
mapping (bytes32 => SealedBid) public sealedBids;

// configurable parameters (REPLACE ALL MINUTES FOR DAYS)
uint public refundForInvalidBids = 1;
uint public refundForUnrevealedBids = 1000;
uint public refundForLosingBids = 10;
uint public refundForExtraBid = 1;
uint public earlyRenewalFee = 10000 * 365 minutes;
uint public lateRenewalFee = (3 * earlyRenewalFee) / 2;
uint public newAuctionLength = 7 minutes;
uint public revealPeriod = 2 minutes;
uint public renewalPeriod = 180 minutes;
uint public minAmountOfTimeToRegister = 10 minutes + revealPeriod + renewalPeriod;
uint public maxAmountOfTimeToRegister = 730 minutes;

// public information
uint public unspendabbleFunds;

modifier noDeposits() {
msg.sender.send(msg.value); // give back any money sent automatically
_
}

// New Auctions are created using one array, as this allows
// someone to register a few fake auctions with the real ones
// to obsfuscate the ones they actually want
function newAuctions(bytes32[] newAuctions) noDeposits {
for (uint i = 0; i < newAuctions.length; i++) {
bytes32 newAuction = newAuctions[i];
if(registry[newAuction].owner != 0) throw; // Check if the name is taken,
Auction a = auctions[newAuction]; // and then check if there isn't an auction
if (a.deadline == 0) { // if hasn't been registered yet
a.deadline = now + newAuctionLength; // then set the date to one week in the future
a.firstRegistered = now;
}
}
}

// Sealed bids only register their hash, value and bid date
function newBid(bytes32 sealedBid) {
sealedBids[sealedBid] = SealedBid({date: now, deposit: msg.value, bidder: msg.sender});
}

function createBidSignature(bytes32 hashedName, uint price, uint period, address proposedOwner, bytes32 salt) constant returns (bytes32 signature) {
return sha3(hashedName, price, period, proposedOwner, salt);
}

function revealBid(bytes32 hashedName, uint price, uint period, address proposedOwner, bytes32 salt) noDeposits {
bytes32 sealed = sha3(hashedName, price, period, proposedOwner, salt); // Create the bid signature
SealedBid bid = sealedBids[sealed]; // Loads from the sealed bids
if (bid.date == 0) throw; // and checks if it exists.


uint refund = 0;
Auction auction = auctions[hashedName]; // load information about the auction
if (bid.date > auction.deadline // Check if bid was sent before deadline
|| (proposedOwner != auction.previousOwner && price + (price * period)/earlyRenewalFee > bid.deposit )
|| (proposedOwner == auction.previousOwner && (price * period)/earlyRenewalFee > bid.deposit )
|| period * 1 minutes < minAmountOfTimeToRegister // Check if above the minimum period of days
|| period * 1 minutes > maxAmountOfTimeToRegister // And below the maximum
) { // Bid is overall invalid
refund = refundForInvalidBids;
} else if (now > auction.deadline - revealPeriod - renewalPeriod) { // Bid wasn't revealed in time
refund = refundForUnrevealedBids;

} else if (price < auction.priceToBePaid) { // Bid is valid, but not high enough
refund = refundForLosingBids;
} else if (price > auction.priceToBePaid && price < auction.priceOffered ) {
// Bid is valid, but only high enough to push the price
refund = refundForLosingBids;
auction.priceToBePaid = price;
} else if (price > auction.priceOffered) {
// Bid is the current top winner
refund = 0;
// refund the last top bidder
auction.currentTopBidder.send(auction.bidPaid / refundForLosingBids);
unspendabbleFunds += auction.bidPaid - auction.bidPaid / refund;

// save the information of the current winner
auction.priceToBePaid = auction.priceOffered;
auction.priceOffered = price;
auction.currentWinner = proposedOwner;
auction.currentTopBidder = bid.bidder;
auction.bidPaid = bid.deposit;
auction.period = period;
} else {
refund = 100;
}

if (refund > 0) {
bid.bidder.send(bid.deposit/refund); // refund the bidder partially
unspendabbleFunds += bid.deposit - bid.deposit / refund;
}

sealedBids[sealed] = SealedBid({date: 0, deposit: 0, bidder: 0});
}

function lateRenewal(bytes32 hashedName, uint period) {
Auction auction = auctions[hashedName];

if ( now < auction.deadline - renewalPeriod
|| now > auction.deadline
|| auction.currentWinner == registry[hashedName].owner
|| msg.value < auction.priceOffered * period / lateRenewalFee
|| period < minAmountOfTimeToRegister
|| period > maxAmountOfTimeToRegister
|| period > (now - auction.firstRegistered) * 2
) throw;


uint costWithFee = auction.priceOffered * period / lateRenewalFee; // calculate the fee
msg.sender.send(msg.value - costWithFee); // refund any extra paid
unspendabbleFunds += costWithFee - auction.priceOffered;

//uint price = (msg.value * lateRenewalFee) / period;
uint price = auction.priceOffered * period / earlyRenewalFee;


uint priceWithFee = auction.priceOffered * period / lateRenewalFee;

auction.priceToBePaid = auction.priceOffered;
auction.priceOffered = auction.priceOffered;
auction.currentWinner = registry[hashedName].owner;
auction.currentTopBidder = msg.sender;
auction.bidPaid = msg.value;
auction.period = period;

uint pricePaid = auction.priceToBePaid + (auction.priceToBePaid * period)/earlyRenewalFee;
unspendabbleFunds += pricePaid;
auction.currentTopBidder.send((auction.bidPaid - pricePaid)/refundForExtraBid);

}

function finalizeAuction(bytes32 hashedName) noDeposits {
Auction auction = auctions[hashedName]; // load information about the auction
if (now < auction.deadline) throw; // Is the auction ready to be executed?

//Record record[hashedName]
uint pricePaid;
// Refund the bidder
if (auction.currentWinner == registry[hashedName].owner ) {
pricePaid = (auction.priceToBePaid * auction.period)/earlyRenewalFee;
} else {
pricePaid = auction.priceToBePaid + (auction.priceToBePaid * auction.period)/earlyRenewalFee;
}
unspendabbleFunds += pricePaid;
auction.currentTopBidder.send((auction.bidPaid - pricePaid)/refundForExtraBid);

// Change the Current Records
registry[hashedName] = Record({
owner: auction.currentWinner,
renewalDate: now + auction.period * 1 minutes,
previousPeriod: auction.period
});

// Change the next auction
auctions[hashedName] = Auction({
deadline: now + auction.period * 1 minutes,
priceOffered: 0,
priceToBePaid: 0,
bidPaid: 0,
currentWinner: 0,
currentTopBidder: 0,
period: 0,
firstRegistered: auction.firstRegistered,
previousOwner: auction.currentWinner
});
}

function () {
throw;
}

}

114 changes: 51 additions & 63 deletions getting started/crowdsale.sol
Original file line number Diff line number Diff line change
@@ -1,73 +1,61 @@
contract token {
mapping (address => uint) public balance;
function token() {}
function sendToken(address receiver, uint amount) returns(bool sufficient) { }
}

contract CrowdSale {
contract token { mapping (address => uint) public coinBalanceOf; function token() {} function sendCoin(address receiver, uint amount) returns(bool sufficient) { } }

address public admin;
address public beneficiary;
uint public fundingGoal;
uint public amountRaised;
uint public deadline;
uint public price;
token public tokenReward;
Funder[] public funders;

/* data structure to hold information about campaign contributors */
struct Funder {
address addr;
uint amount;
}

/* at initialization, setup the owner */
function CrowdSale() {
admin = msg.sender;
}

function setup(address _beneficiary, uint _fundingGoal, uint _duration, uint _price, address _reward) returns (bytes32 response){
if (msg.sender == admin && !(beneficiary > 0 && fundingGoal > 0 && deadline > 0)) {
contract CrowdSale {

address public beneficiary;
uint public fundingGoal; uint public amountRaised; uint public deadline; uint public price;
token public tokenReward;
Funder[] public funders;
event FundTransfer(address backer, uint amount, bool isContribution);

/* data structure to hold information about campaign contributors */
struct Funder {
address addr;
uint amount;
}

/* at initialization, setup the owner */
function CrowdSale(address _beneficiary, uint _fundingGoal, uint _duration, uint _price, address _reward) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can directly use token _reward, it will be converted to address for the ABI.

beneficiary = _beneficiary;
fundingGoal = _fundingGoal;
deadline = now + _duration * 1 days;
deadline = now + _duration * 1 minutes;
price = _price;
tokenReward = token(_reward);
return "campaign is set";
} else if (msg.sender != admin) {
return "not authorized";
} else {
return "campaign cannot be changed";
}
}

/* The function without name is the default function that is called whenever anyone sends funds to a contract without specifying any extra data or if the data does not match any of the function signatures */
function () returns (bytes32 response) {
if (msg.data.length != 0) return;
var numFunders = funders.length;
Funder f = funders[numFunders++];
f.addr = msg.sender;
f.amount = msg.value;
amountRaised += f.amount;
tokenReward.sendToken(msg.sender, f.amount/price);
return "thanks for your contribution";
}
tokenReward = token(_reward);
}

/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() returns (bytes32 response) {
if (amountRaised >= fundingGoal){
beneficiary.send(amountRaised);
suicide(beneficiary);
/* The function without name is the default function that is called whenever anyone sends funds to a contract */
function () {
Funder f = funders[funders.length++];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps more intuitive:

funders[funders.length++] = Funder({addr: msg.sender, amount: msg.value});

f.addr = msg.sender;
f.amount = msg.value;
amountRaised += f.amount;
tokenReward.sendCoin(msg.sender, f.amount/price);
FundTransfer(f.addr, f.amount, true);
if (now >= deadline) {
FundTransfer('0x00100000fe219aaaa8b1fe83adc99d59b807f6f9', 2, true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check that this compiles?
I think even if this is possible, the compiler will remove the 1.
Why don't you use an enum to add an additional flag?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah those fund transfer events where just added as a poor man debugging tool. Forgot to take them out

} else {
FundTransfer('0x00200000fe219aaaa8b1fe83adc99d59b807f6f9', 3, true);
}
}
else if (deadline <= block.number){
for (uint i = 0; i < funders.length; i++) {
funders[i].addr.send(funders[i].amount);
funders[i].addr = 0;
funders[i].amount = 0;

modifier afterDeadline() { if (now >= deadline) _ }

/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() afterDeadline {
FundTransfer('0x00300000fe219aaaa8b1fe83adc99d59b807f6f9', 2, true);
if (amountRaised >= fundingGoal){
FundTransfer('0x00400000fe219aaaa8b1fe83adc99d59b807f6f9', 1, false);
beneficiary.send(amountRaised);
FundTransfer(beneficiary, amountRaised, false);
} else {
FundTransfer(0, 11, false);
for (uint i = 0; i < funders.length; ++i) {
funders[i].addr.send(funders[i].amount);
FundTransfer(funders[i].addr, funders[i].amount, false);
}
}
FundTransfer('0x00500000fe219aaaa8b1fe83adc99d59b807f6f9', 111, false);
suicide(beneficiary);
return "Deadline passed";
}
return "Not reached yet";
}
}
}
Loading