Starter code for Solidity programming assignment.
Designed for use with the Remix web IDE
| pragma solidity ^0.4.18; | |
| import "./TestFramework.sol"; | |
| import "./Bidders.sol"; | |
| contract SimpleAuction is Auction { | |
| // constructor | |
| function SimpleAuction(address _sellerAddress, | |
| address _judgeAddress, | |
| address _timerAddress, | |
| address _winner) public | |
| Auction (_sellerAddress, _judgeAddress, _timerAddress) { | |
| if (_winner != 0) | |
| declareWinner(_winner); | |
| } | |
| function declareWinner(address _winner) public { | |
| winnerAddress = _winner; | |
| } | |
| //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 {} | |
| 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); | |
| else | |
| testAuction = new SimpleAuction(seller, 0, 0, 0); | |
| testAuction.transfer(100 wei); | |
| if (winnerDeclared) | |
| testAuction.declareWinner(winner); | |
| 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"); | |
| Assert.equal(bytes32(7), bytes32(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.equal(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.equal(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.equal(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.equal(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.equal(winner.balance, 100, "winner should receive funds after refund"); | |
| } | |
| } | |
| pragma solidity ^0.4.18; | |
| import "./Timer.sol"; | |
| contract Auction { | |
| address internal judgeAddress; | |
| address internal timerAddress; | |
| address internal sellerAddress; | |
| address internal winnerAddress; | |
| // constructor | |
| function Auction(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; | |
| } | |
| // 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 | |
| } | |
| function getWinner() public returns (address winner){ | |
| return winnerAddress; | |
| } | |
| } |
| pragma solidity ^0.4.18; | |
| import "./TestFramework.sol"; | |
| contract Bidders {} | |
| contract Participant { | |
| Auction auction; | |
| function Participant(Auction _auction) public { | |
| setAuction(_auction); | |
| } | |
| function setAuction(Auction _auction) public { | |
| auction = _auction; | |
| } | |
| //wrapped call | |
| function callFinalize() public returns (bool success) { | |
| success = auction.call.gas(200000)(bytes4 (keccak256("finalize()"))); | |
| } | |
| //wrapped call | |
| function callRefund() public returns (bool success) { | |
| success = auction.call.gas(200000)(bytes4 (keccak256("refund()"))); | |
| } | |
| //can receive money | |
| function() public payable {} | |
| } | |
| contract DutchAuctionBidder { | |
| DutchAuction auction; | |
| function DutchAuctionBidder(DutchAuction _auction) public { | |
| auction = _auction; | |
| } | |
| //wrapped call | |
| function bid(uint bidValue) public returns (bool success){ | |
| success = auction.call.value(bidValue).gas(200000)(bytes4 (keccak256("bid()"))); | |
| } | |
| //can receive money | |
| function() public payable{} | |
| } | |
| contract EnglishAuctionBidder { | |
| EnglishAuction auction; | |
| function EnglishAuctionBidder(EnglishAuction _auction) public { | |
| auction = _auction; | |
| } | |
| //wrapped call | |
| function bid(uint bidValue) public returns (bool success){ | |
| success = auction.call.value(bidValue).gas(200000)(bytes4 (keccak256("bid()"))); | |
| } | |
| //can receive money | |
| function() public payable{} | |
| } | |
| contract VickreyAuctionBidder { | |
| VickreyAuction auction; | |
| bytes32 nonce; | |
| function VickreyAuctionBidder(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(_bidValue, nonce); | |
| success = auction.call.value(_depositValue).gas(200000)(bytes4 (keccak256("commitBid(bytes32)")), commitment); | |
| } | |
| //wrapped call | |
| function revealBid(uint _bidValue) public returns (bool success) { | |
| success = auction.call.value(_bidValue).gas(200000)(bytes4 (keccak256("revealBid(bytes32)")), nonce); | |
| } | |
| //can receive money | |
| function() public payable{} | |
| } |
| 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 | |
| function DutchAuction(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 | |
| } | |
| } |
| 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 {} | |
| 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); | |
| bidder.transfer(bidValue); | |
| uint oldTime = t.getTime(); | |
| t.setTime(bidTime); | |
| uint initialAuctionBalance = 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(testAuction.balance, initialAuctionBalance + expectedPrice, "auction should retain final price"); | |
| Assert.equal(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"); | |
| } | |
| } |
| 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 | |
| function EnglishAuction(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 | |
| } | |
| //TODO: place your code here | |
| //Need to override the default implementation | |
| function getWinner() public returns (address winner){ | |
| return 0; | |
| } | |
| } |
| 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 {} | |
| 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(); | |
| t.setTime(bidTime); | |
| bidder.transfer(bidValue); | |
| bool result = bidder.bid(bidValue); | |
| if (expectedResult == false) { | |
| Assert.isFalse(result, message); | |
| } | |
| else { | |
| Assert.isTrue(result, message); | |
| Assert.equal(testAuction.balance, 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(bob.balance, 0, "bidder should not retain funds"); | |
| Assert.equal(testAuction.balance, 320, "auction should retain bidder's funds in escrow"); | |
| Assert.equal(alice.balance, 300, "outbid bidder should receive 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(alice.balance, 300, "bidder should not retain funds"); | |
| Assert.equal(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(carol.balance, 400, "bidders should get valid refunds"); | |
| Assert.equal(bob.balance, 1420, "bidders should get valid refunds"); | |
| Assert.equal(alice.balance, 1700, "bidders should get valid refunds"); | |
| Assert.equal(testAuction.balance, 1337, "auction should retain bidder's funds in escrow"); | |
| } | |
| } |
| 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 { | |
| if (value) | |
| revert(); | |
| } | |
| function isTrue(bool value, string message) public { | |
| if (!value) | |
| revert(); | |
| } | |
| function equal(uint value1, uint value2, string message) public { | |
| if (value1 != value2) | |
| revert(); | |
| } | |
| function equal(bytes32 value1, bytes32 value2, string message) public { | |
| if (value1 != value2) | |
| revert(); | |
| } | |
| function equal(address value1, address value2, string message) public { | |
| if (value1 != value2) | |
| revert(); | |
| } | |
| } |
| 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 | |
| function Timer(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(); | |
| _; | |
| } | |
| } |
| 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 | |
| function VickreyAuction(address _sellerAddress, | |
| address _judgeAddress, | |
| address _timerAddress, | |
| uint _minimumPrice, | |
| uint _biddingPeriod, | |
| uint _revealPeriod, | |
| uint _bidDepositAmount) | |
| 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 at least 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 { | |
| // TODO: place your code here | |
| } | |
| // Check that the bid (msg.value) matches the commitment | |
| // If the bid is below the minimum price, it is ignored but the deposit is returned. | |
| // If the bid is below the current highest known bid, the bid value and deposit are returned. | |
| // If the bid is the new highest known bid, the deposit is returned and the previous high bidder's bid is returned. | |
| function revealBid(bytes32 nonce) public payable returns(bool isHighestBidder) { | |
| // TODO: place your code here | |
| } | |
| // finalize() must be extended here to provide a refund to the winner | |
| function finalize() public { | |
| //TODO: place your code here | |
| // call the general finalize() logic | |
| super.finalize(); | |
| } | |
| } |
| 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 {} | |
| function VickreyAuctionTestAdvanced() 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 = testAuction.balance; | |
| bidder.transfer(testAuction.bidDepositAmount()); | |
| bool result = bidder.commitBid(bidValue); | |
| if (expectedResult == false) { | |
| Assert.isFalse(result, message); | |
| } | |
| else { | |
| Assert.isTrue(result, message); | |
| Assert.equal(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); | |
| 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(bob.balance, 1000, "winner should received partial refund"); | |
| } | |
| function testRevealChangedBid() public { | |
| setupContracts(); | |
| alice.transfer(2548); | |
| Assert.isTrue(alice.commitBid(500, 1000), "valid bid should be accepted"); | |
| t.setTime(1); | |
| Assert.isTrue(alice.commitBid(550, 1097), "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(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(); | |
| Assert.equal(alice.balance, 1500, "loser should received full refund"); | |
| Assert.equal(bob.balance, 1617, "loser should received full refund"); | |
| Assert.equal(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(); | |
| Assert.equal(alice.balance, 1500, "loser should received full refund"); | |
| Assert.equal(bob.balance, 1617, "loser should received full refund"); | |
| Assert.equal(carol.balance, 1033, "winner should received partial refund"); | |
| } | |
| } |
| 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 {} | |
| function VickreyAuctionTestAdvanced() 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 = testAuction.balance; | |
| bidder.transfer(testAuction.bidDepositAmount()); | |
| bool result = bidder.commitBid(bidValue); | |
| if (expectedResult == false) { | |
| Assert.isFalse(result, message); | |
| } | |
| else { | |
| Assert.isTrue(result, message); | |
| Assert.equal(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); | |
| 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(); | |
| alice.transfer(1067); | |
| Assert.isTrue(alice.commitBid(1000, 1067), "bid with excess deposit should be accepted"); | |
| Assert.equal(alice.balance, 67, "bid with excess deposit should be partially refunded"); | |
| Assert.equal(testAuction.balance, 1000, "bid with excess deposit should be retain exact deposit"); | |
| } | |
| function testChangeBidCommitmentRefund() public { | |
| setupContracts(); | |
| alice.transfer(2548); | |
| Assert.isTrue(alice.commitBid(500, 1000), "valid bid should be accepted"); | |
| t.setTime(1); | |
| Assert.isTrue(alice.commitBid(550, 1097), "valid bid change #1 should be accepted"); | |
| t.setTime(2); | |
| Assert.isTrue(alice.commitBid(450, 401), "valid bid #2 change should be accepted"); | |
| t.setTime(3); | |
| Assert.isTrue(alice.commitBid(600, 0), "valid bid #3 change should be accepted"); | |
| Assert.equal(testAuction.balance, 1000, "bid changes should still capture deposit"); | |
| Assert.equal(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"); | |
| } | |
| } |