Skip to content

Commit

Permalink
Feature/106-bid (#301)
Browse files Browse the repository at this point in the history
* save progress

* save progress

* communityAddress added

* bid contract is working

* bid deploying is working

* test in progress

* save progress

* unit test in progress

* calculateCommunityFee fixed

* 2 more unit test added

* More unit test added

* bid test is done

* pipeline test0

* script fix
  • Loading branch information
etsraphael authored Nov 1, 2023
1 parent 3f42388 commit 50d7c69
Show file tree
Hide file tree
Showing 10 changed files with 46,461 additions and 78,109 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/verifications.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ jobs:
npm run abi
# unit test
- name: unit test
- name: Start node and run tests
run: |
npm run node &
NODE_PID=$!
# Give the node process some time to start up. Adjust this time as needed.
sleep 10
npm run test
# Kill the node process after tests
kill $NODE_PID
130 changes: 130 additions & 0 deletions SmartContracts/contracts/Bid.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";

contract Bid is Ownable, ReentrancyGuard {
uint256 public auctionStartTime;
uint256 public auctionEndTime;
address public highestBidder;
uint256 public highestBid;
address public communityAddress;
uint256 private constant FEE_PERCENT = 1; // 0.1% is represented as 1 / 1000
uint256 public extendTimeInMinutes; // Changed variable name

// List of all bidders
Bidder[] public bidders;
struct Bidder {
address bidderAddress;
uint256 amount;
}

address[] public bidderAddresses;
mapping(address => uint256) public bids;

event AuctionStarted(uint256 startTime, uint256 endTime);
event NewBid(address indexed bidder, uint256 amount);
event Withdrawal(address indexed bidder, uint256 amount);
event AuctionSuccessful(address indexed bidder, uint256 amount);
event CommunityTransfer(address indexed bidder, uint256 amount);

modifier auctionOngoing() {
require(block.timestamp >= auctionStartTime && block.timestamp <= auctionEndTime, "Auction not ongoing");
_;
}

modifier auctionEnded() {
require(block.timestamp > auctionEndTime, "Auction hasn't ended yet");
_;
}

constructor(
address _communityAddress,
uint256 _extendTimeInMinutes,
uint256 _durationInMinutes
) Ownable(_msgSender()) {
communityAddress = _communityAddress;
extendTimeInMinutes = _extendTimeInMinutes;
startAuction(_durationInMinutes);
}

function auctionDone() public view returns (bool) {
return auctionEndTime > block.timestamp;
}

function calculateFee(uint256 _amount) internal pure returns (uint256) {
return Math.mulDiv(_amount, FEE_PERCENT, 1000);
}

function startAuction(uint256 _durationInMinutes) internal {
auctionStartTime = block.timestamp;

(bool secondConversionSuccess, uint256 secondConversion) = Math.tryMul(_durationInMinutes, 60);
require(secondConversionSuccess, "Multiplication overflow");

(bool auctionEndTimeSuccess, uint256 _auctionEndTime) = Math.tryAdd(auctionStartTime, secondConversion);
auctionEndTime = _auctionEndTime;
require(auctionEndTimeSuccess, "Addition overflow");

emit AuctionStarted(auctionStartTime, auctionEndTime);
}

function bid() external payable auctionOngoing nonReentrant {
uint256 fee = calculateFee(msg.value);

(bool actualBidAmountCalculationSuccess, uint256 actualBidAmount) = Math.trySub(msg.value, fee);
require(actualBidAmountCalculationSuccess, "Subtraction overflow");

require(actualBidAmount > highestBid, "Bid amount after fee deduction is not high enough");
require(_msgSender() != highestBidder, "You are already the highest bidder");

uint256 refundAmount = highestBid;
address previousHighestBidder = highestBidder;

// If the bidder hasn't bid before, add to the bidderAddresses array.
if (bids[_msgSender()] == 0) {
bidderAddresses.push(_msgSender());
}

bids[_msgSender()] = actualBidAmount;
highestBidder = _msgSender();
highestBid = actualBidAmount;

// If the auction is about to end, extend the auction by the extendTimeInMinutes
if (auctionEndTime - block.timestamp <= 10 minutes) {
(bool extendedTimeSuccess, uint256 extendedTime) = Math.tryMul(extendTimeInMinutes, 60);
require(extendedTimeSuccess, "Multiplication overflow");
auctionEndTime = block.timestamp + extendedTime;
}

// Transfer the fee to the community address
payable(communityAddress).transfer(fee);
emit CommunityTransfer(_msgSender(), fee);

// Refund the previous highest bidder
if (previousHighestBidder != address(0)) {
payable(previousHighestBidder).transfer(refundAmount);
}

emit NewBid(_msgSender(), actualBidAmount);
}

function withdrawAuctionAmount() external onlyOwner auctionEnded {
payable(owner()).transfer(highestBid);
emit Withdrawal(owner(), highestBid);
emit AuctionSuccessful(highestBidder, highestBid);
}

function getAllBiddersWithAmounts() external view returns (address[] memory, uint256[] memory) {
uint256 length = bidderAddresses.length;
uint256[] memory amounts = new uint256[](length);

for (uint256 i = 0; i < length; i++) {
amounts[i] = bids[bidderAddresses[i]];
}

return (bidderAddresses, amounts);
}
}
Loading

0 comments on commit 50d7c69

Please sign in to comment.