Created
November 21, 2018 21:12
-
-
Save jcb82/b5991669c7d46e74e2a7cf11c8346dd8 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.25+commit.59dbf8f1.js&optimize=false&gist=
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
import "./Bidders.sol"; | |
contract SimpleAuction is Auction { | |
// constructor | |
constructor(address _sellerAddress, | |
address _judgeAddress, | |
address _timerAddress, | |
address _winner, | |
uint _winningPrice) public payable | |
Auction (_sellerAddress, _judgeAddress, _timerAddress) { | |
if (_winner != 0) | |
declareWinner(_winner, _winningPrice); | |
} | |
function declareWinner(address _winner, uint _winningPrice) public { | |
winnerAddress = _winner; | |
winningPrice = _winningPrice; | |
} | |
//can receive money | |
function() public payable {} | |
} | |
contract ArbitrationTest { | |
SimpleAuction testAuction; | |
// Adjust this to change the test code's initial balance | |
uint public initialBalance = 1000000000 wei; | |
Participant judge; | |
Participant seller; | |
Participant winner; | |
Participant other; | |
//can receive money | |
function() public payable {} | |
constructor() public payable {} | |
function setupContracts(bool winnerDeclared, bool hasJudge) public { | |
judge = new Participant(Auction(0)); | |
winner = new Participant(Auction(0)); | |
seller = new Participant(Auction(0)); | |
other = new Participant(Auction(0)); | |
if (hasJudge) | |
testAuction = new SimpleAuction(seller, judge, 0, 0, 100); | |
else | |
testAuction = new SimpleAuction(seller, 0, 0, 0, 100); | |
address(testAuction).transfer(100 wei); | |
if (winnerDeclared) | |
testAuction.declareWinner(winner, 100); | |
judge.setAuction(testAuction); | |
seller.setAuction(testAuction); | |
winner.setAuction(testAuction); | |
other.setAuction(testAuction); | |
} | |
function testCreateContracts() public { | |
setupContracts(false, true); | |
Assert.isFalse(false, "this test should not fail"); | |
Assert.isTrue(true, "this test should never fail"); | |
Assert.equal(uint(7), uint(7), "this test should never fail"); | |
} | |
function testEarlyFinalize() public { | |
setupContracts(false, true); | |
Assert.isFalse(judge.callFinalize(), "finalize with no declared winner should be rejected"); | |
} | |
function testEarlyRefund() public { | |
setupContracts(false, true); | |
Assert.isFalse(judge.callRefund(), "refund with no declared winner should be rejected"); | |
} | |
function testUnauthorizedRefund() public { | |
setupContracts(true, true); | |
Assert.isFalse(winner.callRefund(), "unauthorized refund call should be rejected"); | |
Assert.isFalse(other.callRefund(), "unauthorized refund call should be rejected"); | |
setupContracts(true, false); | |
Assert.isFalse(judge.callRefund(), "unauthorized refund call should be rejected"); | |
} | |
function testUnauthorizedFinalize() public { | |
setupContracts(true, true); | |
Assert.isFalse(seller.callFinalize(), "unauthorized finalize call should be rejected"); | |
Assert.isFalse(other.callFinalize(), "unauthorized finalize call should be rejected"); | |
} | |
function testJudgeFinalize() public { | |
setupContracts(true, true); | |
Assert.isTrue(judge.callFinalize(), "judge finalize call should succeed"); | |
Assert.isTrue(seller.callWithdraw(), "seller withdraw call should succeed"); | |
Assert.equal(address(seller).balance, 100, "seller should receive funds after finalize"); | |
} | |
function testWinnerFinalize() public { | |
setupContracts(true, true); | |
Assert.isTrue(winner.callFinalize(), "winner finalize call should succeed"); | |
Assert.isTrue(seller.callWithdraw(), "seller withdraw call should succeed"); | |
Assert.equal(address(seller).balance, 100, "seller should receive funds after finalize"); | |
} | |
function testPublicFinalize() public { | |
setupContracts(true, false); | |
Assert.isTrue(other.callFinalize(), "public finalize call should succeed"); | |
Assert.isTrue(seller.callWithdraw(), "seller withdraw call should succeed"); | |
Assert.equal(address(seller).balance, 100, "seller should receive funds after finalize"); | |
} | |
function testJudgeRefund() public { | |
setupContracts(true, true); | |
Assert.isTrue(judge.callRefund(), "judge refund call should succeed"); | |
Assert.isTrue(winner.callWithdraw(), "seller withdraw call should succeed"); | |
Assert.equal(address(winner).balance, 100, "winner should receive funds after refund"); | |
} | |
function testSellerRefund() public { | |
setupContracts(true, false); | |
Assert.isTrue(seller.callRefund(), "seller refund call should succeed"); | |
Assert.isTrue(winner.callWithdraw(), "seller withdraw call should succeed"); | |
Assert.equal(address(winner).balance, 100, "winner should receive funds after refund"); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./Timer.sol"; | |
contract Auction { | |
address internal judgeAddress; | |
address internal timerAddress; | |
address internal sellerAddress; | |
address internal winnerAddress; | |
uint winningPrice; | |
// TODO: place your code here | |
// constructor | |
constructor(address _sellerAddress, | |
address _judgeAddress, | |
address _timerAddress) public { | |
judgeAddress = _judgeAddress; | |
timerAddress = _timerAddress; | |
sellerAddress = _sellerAddress; | |
if (sellerAddress == 0) | |
sellerAddress = msg.sender; | |
} | |
// This is provided for testing | |
// You should use this instead of block.number directly | |
// You should not modify this function. | |
function time() public view returns (uint) { | |
if (timerAddress != 0) | |
return Timer(timerAddress).getTime(); | |
return block.number; | |
} | |
function getWinner() public view returns (address winner) { | |
return winnerAddress; | |
} | |
function getWinningPrice() public view returns (uint price) { | |
return winningPrice; | |
} | |
// If no judge is specified, anybody can call this. | |
// If a judge is specified, then only the judge or winning bidder may call. | |
function finalize() public { | |
// TODO: place your code here | |
} | |
// This can ONLY be called by seller or the judge (if a judge exists). | |
// Money should only be refunded to the winner. | |
function refund() public { | |
// TODO: place your code here | |
} | |
// Withdraw funds from the contract. | |
// If called, all funds available to the caller should be refunded. | |
// This should be the *only* place the contract ever transfers funds out. | |
// Ensure that your withdrawal functionality is not vulnerable to | |
// re-entrancy or unchecked-spend vulnerabilities. | |
function withdraw() public { | |
//TODO: place your code here | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
contract Bidders {} | |
contract Participant { | |
Auction auction; | |
constructor(Auction _auction) public { | |
setAuction(_auction); | |
} | |
function setAuction(Auction _auction) public { | |
auction = _auction; | |
} | |
//wrapped call | |
function callFinalize() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("finalize()"))); | |
} | |
//wrapped call | |
function callRefund() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("refund()"))); | |
} | |
//wrapped call | |
function callWithdraw() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("withdraw()"))); | |
} | |
//can receive money | |
function() public payable {} | |
} | |
contract DutchAuctionBidder { | |
DutchAuction auction; | |
constructor(DutchAuction _auction) public { | |
auction = _auction; | |
} | |
//wrapped call | |
function bid(uint bidValue) public returns (bool success){ | |
success = address(auction).call.value(bidValue).gas(200000)(bytes4 (keccak256("bid()"))); | |
} | |
//wrapped call | |
function callWithdraw() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("withdraw()"))); | |
} | |
//can receive money | |
function() public payable{} | |
} | |
contract EnglishAuctionBidder { | |
EnglishAuction auction; | |
constructor(EnglishAuction _auction) public { | |
auction = _auction; | |
} | |
//wrapped call | |
function bid(uint bidValue) public returns (bool success){ | |
success = address(auction).call.value(bidValue).gas(200000)(bytes4 (keccak256("bid()"))); | |
} | |
//wrapped call | |
function callWithdraw() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("withdraw()"))); | |
} | |
//can receive money | |
function() public payable{} | |
} | |
contract VickreyAuctionBidder { | |
VickreyAuction auction; | |
bytes32 nonce; | |
constructor(VickreyAuction _auction, bytes32 _nonce) public { | |
auction = _auction; | |
nonce = _nonce; | |
} | |
function setNonce(bytes32 _newNonce) public { | |
nonce = _newNonce; | |
} | |
//wrapped call | |
function commitBid(uint _bidValue) public returns (bool success) { | |
success = commitBid(_bidValue, auction.bidDepositAmount()); | |
} | |
//wrapped call | |
function commitBid(uint _bidValue, uint _depositValue) public returns (bool success) { | |
bytes32 commitment = keccak256(abi.encodePacked(_bidValue, nonce)); | |
success = address(auction).call.value(_depositValue).gas(200000)(bytes4 (keccak256("commitBid(bytes32)")), commitment); | |
} | |
//wrapped call | |
function revealBid(uint _bidValue) public returns (bool success) { | |
success = address(auction).call.value(_bidValue).gas(200000)(bytes4 (keccak256("revealBid(bytes32)")), nonce); | |
} | |
//wrapped call | |
function callWithdraw() public returns (bool success) { | |
success = address(auction).call.gas(200000)(bytes4 (keccak256("withdraw()"))); | |
} | |
//can receive money | |
function() public payable{} | |
} | |
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
pragma solidity ^0.4.18; | |
import "./Auction.sol"; | |
contract DutchAuction is Auction { | |
uint public initialPrice; | |
uint public biddingPeriod; | |
uint public offerPriceDecrement; | |
// TODO: place your code here | |
// constructor | |
constructor(address _sellerAddress, | |
address _judgeAddress, | |
address _timerAddress, | |
uint _initialPrice, | |
uint _biddingPeriod, | |
uint _offerPriceDecrement) public | |
Auction (_sellerAddress, _judgeAddress, _timerAddress) { | |
initialPrice = _initialPrice; | |
biddingPeriod = _biddingPeriod; | |
offerPriceDecrement = _offerPriceDecrement; | |
// TODO: place your code here | |
} | |
function bid() public payable{ | |
// TODO: place your code here | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
import "./Bidders.sol"; | |
contract DutchAuctionTest { | |
DutchAuction testAuction; | |
Timer t; | |
// Adjust this to change the test code's initial balance | |
uint public initialBalance = 1000000000 wei; | |
//can receive money | |
function() public payable {} | |
constructor() public payable {} | |
function setupContracts() public { | |
t = new Timer(0); | |
testAuction = new DutchAuction(this, 0, t, 300, 10, 20); | |
} | |
function makeBid(uint bidValue, | |
uint bidTime, | |
uint expectedPrice, | |
bool expectedResult, | |
string message) internal { | |
DutchAuctionBidder bidder = new DutchAuctionBidder(testAuction); | |
address(bidder).transfer(bidValue); | |
uint oldTime = t.getTime(); | |
t.setTime(bidTime); | |
uint initialAuctionBalance = address(testAuction).balance; | |
address currentWinner = testAuction.getWinner(); | |
bool result = bidder.bid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
Assert.equal(currentWinner, testAuction.getWinner(), "no winner should be declared after invalid bid"); | |
} | |
else{ | |
Assert.isTrue(result, message); | |
Assert.equal(address(testAuction).balance, initialAuctionBalance + expectedPrice, "auction should retain final price"); | |
Assert.equal(address(bidder).balance, bidValue - expectedPrice, "bidder should be refunded excess bid amount"); | |
Assert.equal(testAuction.getWinner(), bidder, "bidder should be declared the winner"); | |
} | |
t.setTime(oldTime); | |
} | |
function testCreateDutchAuction() public { | |
setupContracts(); | |
//do nothing, just verify that the constructor actually ran | |
} | |
function testLowBids() public { | |
setupContracts(); | |
makeBid(299, 0, 0, false, "low bid should be rejected"); | |
makeBid(240, 2, 0, false, "low bid should be rejected"); | |
makeBid(100, 5, 0, false, "low bid should be rejected"); | |
} | |
function testExactBid() public { | |
setupContracts(); | |
makeBid(300, 0, 300, true, "exact bid should be accepted"); | |
setupContracts(); | |
makeBid(280, 1, 280, true, "exact bid should be accepted"); | |
setupContracts(); | |
makeBid(120, 9, 120, true, "exact bid should be accepted"); | |
} | |
function testValidBidAfterInvalid() public { | |
setupContracts(); | |
makeBid(299, 0, 0, false, "low bid should be rejected"); | |
makeBid(300, 0, 300, true, "valid bid after failed bid should succeed"); | |
} | |
function testLateBid() public { | |
setupContracts(); | |
makeBid(300, 10, 0, false, "late bid should be rejected"); | |
} | |
function testSecondValidBid() public { | |
setupContracts(); | |
makeBid(280, 1, 280, true, "exact bid should be accepted"); | |
makeBid(300, 0, 0, false, "second bid should be rejected"); | |
} | |
function testRefundHighBid() public { | |
setupContracts(); | |
makeBid(300, 2, 260, true, "high bid should be accepted"); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./Auction.sol"; | |
contract EnglishAuction is Auction { | |
uint public initialPrice; | |
uint public biddingPeriod; | |
uint public minimumPriceIncrement; | |
// TODO: place your code here | |
// constructor | |
constructor(address _sellerAddress, | |
address _judgeAddress, | |
address _timerAddress, | |
uint _initialPrice, | |
uint _biddingPeriod, | |
uint _minimumPriceIncrement) public | |
Auction (_sellerAddress, _judgeAddress, _timerAddress) { | |
initialPrice = _initialPrice; | |
biddingPeriod = _biddingPeriod; | |
minimumPriceIncrement = _minimumPriceIncrement; | |
// TODO: place your code here | |
} | |
function bid() public payable{ | |
// TODO: place your code here | |
} | |
// Need to override the default implementation | |
function getWinner() public view returns (address winner){ | |
return winner; | |
// TODO: place your code here | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
import "./Bidders.sol"; | |
contract EnglishAuctionTest { | |
EnglishAuction testAuction; | |
EnglishAuctionBidder alice; | |
EnglishAuctionBidder bob; | |
EnglishAuctionBidder carol; | |
Timer t; | |
// Adjust this to change the test code's initial balance | |
uint public initialBalance = 1000000000 wei; | |
//can receive money | |
function() public payable {} | |
constructor() public payable {} | |
function setupContracts() public { | |
t = new Timer(0); | |
testAuction = new EnglishAuction(this, 0, t, 300, 10, 20); | |
alice = new EnglishAuctionBidder(testAuction); | |
bob = new EnglishAuctionBidder(testAuction); | |
carol = new EnglishAuctionBidder(testAuction); | |
} | |
function makeBid(EnglishAuctionBidder bidder, | |
uint bidValue, | |
uint bidTime, | |
bool expectedResult, | |
string message) internal { | |
uint oldTime = t.getTime(); | |
uint oldBalance = address(testAuction).balance; | |
t.setTime(bidTime); | |
address(bidder).transfer(bidValue); | |
bool result = bidder.bid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
} | |
else { | |
Assert.isTrue(result, message); | |
Assert.equal(address(testAuction).balance - oldBalance, bidValue, "auction should retain bid amount"); | |
} | |
t.setTime(oldTime); | |
} | |
function testCreateEnglishAuction() public { | |
setupContracts(); | |
//do nothing, just verify that the constructor actually ran | |
} | |
function testLowInitialBids() public { | |
setupContracts(); | |
makeBid(alice, 0, 0, false, "low bid should be rejected"); | |
makeBid(alice, 299, 9, false, "low bid should be rejected"); | |
} | |
function testSingleValidBid() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
t.setTime(10); | |
Assert.equal(testAuction.getWinner(), address(alice), "single bidder should be declared the winner"); | |
} | |
function testEarlyWinner() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
t.setTime(9); | |
Assert.equal(testAuction.getWinner(), 0, "no bidder should be declared before deadline"); | |
} | |
function testLowFollowupBids() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
makeBid(bob, 319, 9, false, "low bid should be rejected"); | |
makeBid(bob, 250, 7, false, "low bid should be rejected"); | |
} | |
function testRefundAfterOutbid() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
makeBid(bob, 320, 8, true, "valid bid should be accepted"); | |
Assert.equal(address(bob).balance, 0, "bidder should not retain funds"); | |
Assert.equal(address(testAuction).balance, 620, "auction should retain bidders' funds in escrow"); | |
Assert.equal(address(alice).balance, 0, "outbid bidder should not receive early refund"); | |
alice.callWithdraw(); | |
Assert.equal(address(alice).balance, 300, "outbid bidder should be able to withdraw refund"); | |
} | |
function testLateBids() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
makeBid(bob, 320, 10, false, "late bid should be rejected"); | |
makeBid(carol, 500, 12, false, "late bid should be rejected"); | |
} | |
function testIncreaseBid() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
makeBid(alice, 350, 5, true, "second valid bid should be accepted"); | |
t.setTime(14); | |
Assert.equal(testAuction.getWinner(), 0, "no bidder should be declared before deadline"); | |
t.setTime(15); | |
Assert.equal(testAuction.getWinner(), address(alice), "repeat bidder should be declared the winner"); | |
Assert.equal(address(alice).balance, 0, "bidder should not retain funds"); | |
Assert.equal(address(testAuction).balance, 650, "auction should retain bidder's funds in escrow"); | |
alice.callWithdraw(); | |
Assert.equal(address(alice).balance, 300, "outbid bidder should be able to withdraw funds"); | |
Assert.equal(address(testAuction).balance, 350, "auction should retain bidder's funds in escrow"); | |
} | |
function testExtendedBidding() public { | |
setupContracts(); | |
makeBid(alice, 300, 0, true, "valid bid should be accepted"); | |
makeBid(bob, 310, 4, false, "invalid bid should be rejected"); | |
makeBid(carol, 400, 8, true, "valid bid should be accepted"); | |
makeBid(bob, 450, 12, true, "valid bid should be accepted"); | |
makeBid(alice, 650, 15, true, "valid bid should be accepted"); | |
makeBid(bob, 660, 16, false, "invalid bid should be rejected"); | |
makeBid(alice, 750, 20, true, "valid bid should be accepted"); | |
makeBid(carol, 1337, 29, true, "valid bid should be accepted"); | |
t.setTime(38); | |
Assert.equal(testAuction.getWinner(), 0, "no bidder should be declared before deadline"); | |
t.setTime(39); | |
Assert.equal(testAuction.getWinner(), address(carol), "final bidder should be declared the winner"); | |
Assert.equal(address(alice).balance, 0, "bidders should not retain funds"); | |
Assert.equal(address(bob).balance, 970, "bidders should not retain funds"); | |
Assert.equal(address(carol).balance, 0, "bidders should not retain funds"); | |
alice.callWithdraw(); | |
bob.callWithdraw(); | |
carol.callWithdraw(); | |
Assert.equal(address(carol).balance, 400, "bidders should get valid refunds"); | |
Assert.equal(address(bob).balance, 1420, "bidders should get valid refunds"); | |
Assert.equal(address(alice).balance, 1700, "bidders should get valid refunds"); | |
Assert.equal(address(testAuction).balance, 1337, "auction should retain bidder's funds in escrow"); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
contract Migrations { | |
address public owner; | |
uint public last_completed_migration; | |
modifier restricted() { | |
if (msg.sender == owner) _; | |
} | |
constructor() public { | |
owner = msg.sender; | |
} | |
function setCompleted(uint completed) public restricted { | |
last_completed_migration = completed; | |
} | |
function upgrade(address new_address) public restricted { | |
Migrations upgraded = Migrations(new_address); | |
upgraded.setCompleted(last_completed_migration); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./Timer.sol"; | |
import "./Auction.sol"; | |
import "./DutchAuction.sol"; | |
import "./EnglishAuction.sol"; | |
import "./VickreyAuction.sol"; | |
library Assert { | |
function isFalse(bool value, string message) public pure { | |
message = message; | |
if (value) | |
revert(); | |
} | |
function isTrue(bool value, string message) public pure { | |
message = message; | |
if (!value) | |
revert(); | |
} | |
function equal(uint value1, uint value2, string message) public pure { | |
message = message; | |
if (value1 != value2) | |
revert(); | |
} | |
function equal(bytes32 value1, bytes32 value2, string message) public pure { | |
message = message; | |
if (value1 != value2) | |
revert(); | |
} | |
function equal(address value1, address value2, string message) public pure { | |
message = message; | |
if (value1 != value2) | |
revert(); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
// Simple contract to store time. You should not need to be modify this contract. | |
contract Timer { | |
uint time; | |
uint startTime; | |
address owner; | |
// constructor | |
constructor(uint _startTime) public { | |
owner = msg.sender; | |
time = _startTime; | |
startTime = _startTime; | |
} | |
function getTime() public view returns (uint) { | |
return time; | |
} | |
function resetTime() public ownerOnly { | |
time = startTime; | |
} | |
function setTime(uint _newTime) public ownerOnly { | |
time = _newTime; | |
} | |
function offsetTime(uint _offset) public ownerOnly { | |
time += _offset; | |
} | |
modifier ownerOnly { | |
if (msg.sender != owner) | |
revert(); | |
_; | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./Auction.sol"; | |
contract VickreyAuction is Auction { | |
uint public minimumPrice; | |
uint public biddingDeadline; | |
uint public revealDeadline; | |
uint public bidDepositAmount; | |
// TODO: place your code here | |
// constructor | |
constructor(address _sellerAddress, | |
address _judgeAddress, | |
address _timerAddress, | |
uint _minimumPrice, | |
uint _biddingPeriod, | |
uint _revealPeriod, | |
uint _bidDepositAmount) public | |
Auction (_sellerAddress, _judgeAddress, _timerAddress) { | |
minimumPrice = _minimumPrice; | |
bidDepositAmount = _bidDepositAmount; | |
biddingDeadline = time() + _biddingPeriod; | |
revealDeadline = time() + _biddingPeriod + _revealPeriod; | |
// TODO: place your code here | |
} | |
// Record the player's bid commitment | |
// Make sure exactly bidDepositAmount is provided (for new bids) | |
// Bidders can update their previous bid for free if desired. | |
// Only allow commitments before biddingDeadline | |
function commitBid(bytes32 bidCommitment) public payable { | |
// NOOP to silence compiler warning. Delete me. | |
bidCommitment ^= 0; | |
// TODO: place your code here | |
} | |
// Check that the bid (msg.value) matches the commitment. | |
// If the bid is correctly opened, the bidder can withdraw their deposit. | |
function revealBid(bytes32 nonce) public payable returns(bool isHighestBidder) { | |
// NOOPs to silence compiler warning. Delete me. | |
nonce ^= 0; | |
isHighestBidder = false; | |
// TODO: place your code here | |
} | |
// Need to override the default implementation | |
function getWinner() public view returns (address winner){ | |
// TODO: place your code here | |
return winner; | |
} | |
// finalize() must be extended here to provide a refund to the winner | |
// based on the final sale price (the second highest bid, or reserve price). | |
function finalize() public { | |
// TODO: place your code here | |
// call the general finalize() logic | |
super.finalize(); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
import "./Bidders.sol"; | |
contract VickreyAuctionTestAdvanced { | |
VickreyAuction testAuction; | |
VickreyAuctionBidder alice; | |
VickreyAuctionBidder bob; | |
VickreyAuctionBidder carol; | |
uint bidderCounter; | |
Timer t; | |
// Adjust this to change the test code's initial balance | |
uint public initialBalance = 1000000000 wei; | |
//can receive money | |
function() public payable {} | |
constructor() public payable {} | |
function setupContracts() public { | |
t = new Timer(0); | |
testAuction = new VickreyAuction(this, 0, t, 300, 10, 10, 1000); | |
bidderCounter += 1; | |
alice = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
bob = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
carol = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
} | |
function commitBid(VickreyAuctionBidder bidder, | |
uint bidValue, | |
uint bidTime, | |
bool expectedResult, | |
string message) internal { | |
uint oldTime = t.getTime(); | |
t.setTime(bidTime); | |
uint initialAuctionBalance = address(testAuction).balance; | |
address(bidder).transfer(testAuction.bidDepositAmount()); | |
bool result = bidder.commitBid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
} | |
else { | |
Assert.isTrue(result, message); | |
Assert.equal(address(testAuction).balance, initialAuctionBalance + testAuction.bidDepositAmount(), "auction should retain deposit"); | |
} | |
t.setTime(oldTime); | |
} | |
function revealBid(VickreyAuctionBidder bidder, | |
uint bidValue, | |
uint bidTime, | |
bool expectedResult, | |
string message) internal { | |
uint oldTime = t.getTime(); | |
t.setTime(bidTime); | |
address(bidder).transfer(bidValue); | |
bool result = bidder.revealBid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
} | |
else { | |
Assert.isTrue(result, message); | |
} | |
t.setTime(oldTime); | |
} | |
function testMinimalBidder() public { | |
setupContracts(); | |
commitBid(bob, 300, 9, true, "valid bid commitment should be accepted"); | |
revealBid(bob, 300, 19, true, "valid bid reveal should be accepted"); | |
t.setTime(20); | |
Assert.equal(address(bob), testAuction.getWinner(), "winner should be declared after auction end"); | |
testAuction.finalize(); | |
Assert.equal(address(bob).balance, 0, "winner should not receive early refund"); | |
bob.callWithdraw(); | |
Assert.equal(address(bob).balance, 1000, "winner should received partial refund"); | |
} | |
function testRevealChangedBid() public { | |
setupContracts(); | |
address(alice).transfer(2548); | |
Assert.isTrue(alice.commitBid(500, 1000), "valid bid should be accepted"); | |
t.setTime(1); | |
Assert.isTrue(alice.commitBid(550, 0), "valid bid change should be accepted"); | |
revealBid(alice, 500, 14, false, "incorrect bid reveal should be rejected"); | |
revealBid(alice, 550, 14, true, "correct bid reveal should be accepted"); | |
t.setTime(20); | |
Assert.equal(address(alice), testAuction.getWinner(), "winner should be declared after auction end"); | |
testAuction.finalize(); | |
Assert.equal(address(alice).balance, 2048, "winner should not receive early refund"); | |
alice.callWithdraw(); | |
Assert.equal(address(alice).balance, 3298, "winner should received partial refund"); | |
} | |
function testMultipleBiddersOne() public { | |
setupContracts(); | |
commitBid(alice, 500, 1, true, "correct bid should be accepted"); | |
commitBid(bob, 617, 2, true, "correct bid should be accepted"); | |
commitBid(carol, 650, 3, true, "correct bid should be accepted"); | |
revealBid(alice, 500, 14, true, "correct bid reveal should be accepted"); | |
revealBid(bob, 617, 15, true, "correct bid reveal should be accepted"); | |
revealBid(carol, 650, 16, true, "correct bid reveal should be accepted"); | |
t.setTime(20); | |
Assert.equal(address(carol), testAuction.getWinner(), "winner should be declared after auction end"); | |
testAuction.finalize(); | |
alice.callWithdraw(); | |
bob.callWithdraw(); | |
carol.callWithdraw(); | |
Assert.equal(address(alice).balance, 1500, "loser should received full refund"); | |
Assert.equal(address(bob).balance, 1617, "loser should received full refund"); | |
Assert.equal(address(carol).balance, 1033, "winner should received partial refund"); | |
} | |
function testMultipleBiddersTwo() public { | |
setupContracts(); | |
commitBid(alice, 500, 1, true, "correct bid should be accepted"); | |
commitBid(bob, 617, 2, true, "correct bid should be accepted"); | |
commitBid(carol, 650, 3, true, "correct bid reveal should be accepted"); | |
revealBid(carol, 650, 14, true, "correct bid reveal should be accepted"); | |
revealBid(alice, 500, 15, true, "correct bid reveal should be accepted"); | |
revealBid(bob, 617, 16, true, "correct bid reveal should be accepted"); | |
t.setTime(20); | |
Assert.equal(address(carol), testAuction.getWinner(), "winner should be declared after auction end"); | |
testAuction.finalize(); | |
alice.callWithdraw(); | |
bob.callWithdraw(); | |
carol.callWithdraw(); | |
Assert.equal(address(alice).balance, 1500, "loser should received full refund"); | |
Assert.equal(address(bob).balance, 1617, "loser should received full refund"); | |
Assert.equal(address(carol).balance, 1033, "winner should received partial refund"); | |
} | |
} |
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
pragma solidity ^0.4.18; | |
import "./TestFramework.sol"; | |
import "./Bidders.sol"; | |
contract VickreyAuctionTestBasic { | |
VickreyAuction testAuction; | |
VickreyAuctionBidder alice; | |
VickreyAuctionBidder bob; | |
VickreyAuctionBidder carol; | |
uint bidderCounter; | |
Timer t; | |
// Adjust this to change the test code's initial balance | |
uint public initialBalance = 1000000000 wei; | |
//can receive money | |
function() public payable {} | |
constructor() public payable {} | |
function setupContracts() public { | |
t = new Timer(0); | |
testAuction = new VickreyAuction(this, 0, t, 300, 10, 10, 1000); | |
bidderCounter += 1; | |
alice = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
bob = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
carol = new VickreyAuctionBidder(testAuction, bytes32(bidderCounter)); | |
} | |
function commitBid(VickreyAuctionBidder bidder, | |
uint bidValue, | |
uint bidTime, | |
bool expectedResult, | |
string message) internal { | |
uint oldTime = t.getTime(); | |
t.setTime(bidTime); | |
uint initialAuctionBalance = address(testAuction).balance; | |
address(bidder).transfer(testAuction.bidDepositAmount()); | |
bool result = bidder.commitBid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
} | |
else { | |
Assert.isTrue(result, message); | |
Assert.equal(address(testAuction).balance, initialAuctionBalance + testAuction.bidDepositAmount(), "auction should retain deposit"); | |
} | |
t.setTime(oldTime); | |
} | |
function revealBid(VickreyAuctionBidder bidder, | |
uint bidValue, | |
uint bidTime, | |
bool expectedResult, | |
string message) internal { | |
uint oldTime = t.getTime(); | |
t.setTime(bidTime); | |
address(bidder).transfer(bidValue); | |
bool result = bidder.revealBid(bidValue); | |
if (expectedResult == false) { | |
Assert.isFalse(result, message); | |
} | |
else { | |
Assert.isTrue(result, message); | |
} | |
t.setTime(oldTime); | |
} | |
function testCreateVickreyAuction() public { | |
setupContracts(); | |
//do nothing, just verify that the constructor actually ran | |
} | |
function testCommitBids() public { | |
setupContracts(); | |
commitBid(alice, 10, 1, true, "valid bid commitment should be accepted"); | |
commitBid(bob, 1000, 2, true, "valid bid commitment should be accepted"); | |
commitBid(carol, 340, 7, true, "valid bid commitment should be accepted"); | |
} | |
function testLateBidCommitments() public { | |
setupContracts(); | |
commitBid(carol, 340, 7, true, "valid bid commitment should be accepted"); | |
commitBid(alice, 300, 10, false, "late bid commitment should be rejected"); | |
commitBid(bob, 3000, 100, false, "late bid commitment should be rejected"); | |
} | |
function testExcessBidDeposit() public { | |
setupContracts(); | |
address(alice).transfer(1067); | |
Assert.isFalse(alice.commitBid(1000, 1067), "bid with excess deposit should be rejected"); | |
Assert.equal(address(alice).balance, 1067, "bid with excess deposit should be rejected"); | |
} | |
function testChangeBidCommitmentRefund() public { | |
setupContracts(); | |
address(alice).transfer(2548); | |
Assert.isTrue(alice.commitBid(500, 1000), "valid bid should be accepted"); | |
t.setTime(1); | |
Assert.isTrue(alice.commitBid(550, 0), "valid bid change #1 should be accepted"); | |
t.setTime(2); | |
Assert.isTrue(alice.commitBid(450, 0), "valid bid change #2 should be accepted"); | |
t.setTime(3); | |
Assert.isFalse(alice.commitBid(300, 1000), "invalid bid #3 change should be rejected"); | |
Assert.equal(address(testAuction).balance, 1000, "bid changes should still capture deposit"); | |
Assert.equal(address(alice).balance, 1548, "bid changes should not capture additional deposit"); | |
} | |
function testEarlyReveal() public { | |
setupContracts(); | |
commitBid(alice, 340, 7, true, "valid bid commitment should be accepted"); | |
revealBid(alice, 340, 9, false, "early bid reveal should be rejected"); | |
} | |
function testLateReveal() public { | |
setupContracts(); | |
commitBid(alice, 340, 7, true, "valid bid commitment should be accepted"); | |
revealBid(alice, 340, 20, false, "early bid reveal should be rejected"); | |
} | |
function testInvalidReveal() public { | |
setupContracts(); | |
commitBid(alice, 340, 7, true, "valid bid commitment should be accepted"); | |
commitBid(bob, 380, 8, true, "valid bid commitment should be accepted"); | |
revealBid(alice, 320, 14, false, "incorrect bid reveal should be rejected"); | |
bob.setNonce(1); | |
revealBid(bob, 380, 16, false, "incorrect bid reveal should be rejected"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment