This repository was archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 391
updated tutorial contracts #29
Open
alexvandesande
wants to merge
3
commits into
ethereum:master
Choose a base branch
from
alexvandesande:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
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; | ||
} | ||
|
||
} | ||
|
This file contains 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
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) { | ||
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++]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps more intuitive:
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you check that this compiles? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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"; | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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 toaddress
for the ABI.