Skip to content

Commit

Permalink
Adding tests for the Simple Auction smart contract.
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Stefanov <[email protected]>
  • Loading branch information
stefan-stefanooov committed Nov 7, 2023
1 parent 0481257 commit e445d19
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ artifacts/@openzeppelin
artifacts/build-info
artifacts/contracts
artifacts/
artifacts/hardhat
.openzeppelin/unknown-298.json
.env
test-results.*
Expand Down
78 changes: 78 additions & 0 deletions contracts/solidity/simple-auction/SimpleAuction.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract SimpleAuction {
address payable public beneficiary;
uint public auctionEndTime;
address public highestBidder;
uint public highestBid;

mapping(address => uint) pendingReturns;
bool ended;

event HighestBidIncreased(address bidder, uint amount);
event AuctionEnded(address winner, uint amount);
event FundReturned(address recepient, uint amount);

/// The auction has already ended.
error AuctionAlreadyEnded();
/// There is already a higher or equal bid.
error BidNotHighEnough();
/// The auction has not ended yet.
error AuctionNotYetEnded();
/// The function auctionEnd has already been called.
error AuctionEndAlreadyCalled();

constructor(
uint biddingTime,
address payable beneficiaryAddress
) {
auctionEndTime = block.timestamp + biddingTime;
beneficiary = beneficiaryAddress;
}

function bid() external payable {

if (block.timestamp > auctionEndTime)
revert('AuctionAlreadyEnded');

if (msg.value <= highestBid)
revert('BidNotHighEnough');

if (highestBid != 0) {
pendingReturns[highestBidder] += highestBid;
}

highestBidder = msg.sender;
highestBid = msg.value;
emit HighestBidIncreased(msg.sender, msg.value);
}

/// Withdraw a bid that was overbid.
function withdraw() external returns (bool) {
uint amount = pendingReturns[msg.sender];
if (amount > 0) {
pendingReturns[msg.sender] = 0;
if (!payable(msg.sender).send(amount)) {
pendingReturns[msg.sender] = amount;
emit FundReturned(msg.sender, amount);
return false;
}
}
return true;
}

/// End the auction and send the highest bid
/// to the beneficiary.
function auctionEnd() external {
if (block.timestamp < auctionEndTime)
revert AuctionNotYetEnded();
if (ended)
revert AuctionEndAlreadyCalled();

ended = true;
emit AuctionEnded(highestBidder, highestBid);

beneficiary.transfer(highestBid);
}
}
1 change: 0 additions & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,3 @@ module.exports = {
},
},
}

5 changes: 1 addition & 4 deletions test/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,10 @@ const Contract = {
Defaults: 'Defaults',
NonExisting: 'NonExisting',
NonExtDup: 'NonExtDup',
AddressContract: 'AddressContract',
Recipient: 'Recipient',
Inheritance: 'Inheritance',
ControlStructures: 'ControlStructures',
Defaults: 'Defaults',
AssignmentReferenceTypes: 'AssignmentReferenceTypes',
DestructuringReturns: 'DestructuringReturns',
SimpleAuction: 'SimpleAuction',
}

const CALL_EXCEPTION = 'CALL_EXCEPTION'
Expand Down
1 change: 0 additions & 1 deletion test/solidity/errors/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,5 +122,4 @@ describe('@solidityequiv2 Solidity Errors', function () {
expect(receipt.events[0].args.code).to.equal(18)
expect(receipt.events[0].args.message).to.equal('panic')
})

})
118 changes: 118 additions & 0 deletions test/solidity/simple-auction/simple-auction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
const { expect } = require('chai')
const { ethers } = require('hardhat')
const Constants = require('../../constants')
const Utils = require('../../hts-precompile/utils')

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

describe('Solidity Simple Auction example', function () {
let factory, signers, wallet, wallet1,
contract, hasError, bidAmount,
contractShortLived, bidAmountSmall, initialEvent
const CONTRACT_DURATION = 10000000000
const CONTRACT_SHORT_DURATION = 1
const TRANSACTION_VALUE = '100'
const TRANSACTION_VALUE_SMALL = '10'

before(async function () {
signers = await ethers.getSigners()
wallet = signers[0]
wallet1 = signers[1]

factory = await ethers.getContractFactory(Constants.Contract.SimpleAuction)
contractShortLived = await factory.deploy(CONTRACT_SHORT_DURATION, wallet1.address)
await contractShortLived.deployed();

bidAmount = ethers.utils.parseUnits(TRANSACTION_VALUE, 'gwei')
bidAmountSmall = ethers.utils.parseUnits(TRANSACTION_VALUE_SMALL, 'gwei')
await sleep(5000)
})

beforeEach(async function () {
hasError = false
contract = await factory.deploy(CONTRACT_DURATION, wallet.address)
await contract.deployed();

const trx = await contract.bid({ value: bidAmountSmall })
const receipt = await trx.wait()
initialEvent = receipt.events[0].event
})

it('should confirm "bid" function works', async function () {
const highestBid = await contract.highestBid()
const highestBidder = await contract.highestBidder()

expect(highestBid.mul(Utils.tinybarToWeibarCoef)).to.equal(bidAmountSmall)
expect(highestBidder).to.equal(wallet.address)
expect(initialEvent).to.equal('HighestBidIncreased')
})

it('should confirm bid not high enough scenario works: BidNotHighEnough', async function () {
try {
const tr = await contract.bid({ value: bidAmountSmall })
const receipt = await tr.wait();
expect(receipt).to.not.be.null
} catch (error) {
hasError = true
expect(error.code).to.be.equal('CALL_EXCEPTION')
}

expect(hasError).to.equal(true)
})

it('should revert a bid with "AuctionAlreadyEnded" error', async function () {
try {
console.log("Waiting for the next block")
await sleep(5000)
console.log("Done")
const tr = await contractShortLived.bid({ value: bidAmountSmall })
await tr.wait()
} catch (error) {
hasError = true
}

expect(hasError).to.equal(true)
})

it('should confirm "withdraw" function works', async function () {
expect(initialEvent, "Initial bid").to.equal('HighestBidIncreased')

const initialHighestBidder = await contract.highestBidder()
const previousContractBalance = await ethers.provider.getBalance(contract.address)
expect(previousContractBalance, `Initial Contract balance to be: ${bidAmountSmall}`).to.equal(bidAmountSmall)
expect(initialHighestBidder, `Initial Highest bidder to be: ${initialHighestBidder}`).to.equal(wallet.address)

const tr = await contract.connect(wallet1).bid({ value: bidAmount })
await tr.wait()

await sleep(1000)
const newHighestBidder = await contract.highestBidder()
expect(newHighestBidder, "New Highest bidder to be: --Wallet1--").to.equal(wallet1.address)
const currentContractBalance = await ethers.provider.getBalance(contract.address)

const combined = bidAmount.add(bidAmountSmall)
expect(currentContractBalance, "The contract balance to be the combined of the two transactions").to.equal(combined)

// Call the withdraw function with the previous highest bidder's address
const withdrawTx = await contract.connect(wallet).withdraw()
await withdrawTx.wait()

await sleep(1000)
// Check that the amount of Ether returned to the previous highest bidder is correct
const newContractBalance = await ethers.provider.getBalance(contract.address)
expect(newContractBalance, "The new balance to be bidAmount").to.equal(bidAmount)
})

it('should confirm "auctionEnd" function works', async function () {
expect(initialEvent, "Initial bid").to.equal('HighestBidIncreased')
const previousContractBalance = await ethers.provider.getBalance(contract.address)
expect(previousContractBalance, `Initial Contract balance to be: ${bidAmountSmall}`).to.equal(bidAmountSmall)

const tr = await contractShortLived.connect(wallet).auctionEnd()
await tr.wait()

await sleep(1000)
const contractBalance = await ethers.provider.getBalance(contract.address)
expect(contractBalance, `Contract balance after "auctionEnd" to be: ${bidAmountSmall}`).to.equal(bidAmountSmall)
})
})

0 comments on commit e445d19

Please sign in to comment.