Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 29 additions & 13 deletions Election.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,53 @@
pragma solidity ^0.8.28;

contract Election {

string[] public electors;
//["Vasya","Taska","Basta","Papsha"]

uint256 public maxVotes;

uint256 public allVotes;
uint256 public electionEndTime;
address public owner;
bool public isElectionActive;

mapping(address => bool) public userVotes;

mapping(uint256 => uint256) public numberOfVotes;

constructor(string[] memory _electors) {
constructor(string[] memory _electors, uint256 _maxVotes,uint256 _electionEndTime) {
electors = _electors;
maxVotes = _maxVotes;
owner = msg.sender;
isElectionActive = true;
electionEndTime = _electionEndTime + block.timestamp;
}

modifier onlyOwner() {
require(owner == msg.sender, "Not the contract owner");
_;
}

function vote(uint256 _number) public {
require(userVotes[msg.sender]==false, "Your address can't vote");
require(userVotes[msg.sender] == false, "Your address can't vote");
require(_number < electors.length, "Elector does not exist");
require(maxVotes > allVotes, "Maximum number of votes exceeded");
require(owner != msg.sender, "Owner doesn`t vote");
require(isElectionActive == true, 'Elections are closed');
require(block.timestamp < electionEndTime, 'Time of elections is ended');
userVotes[msg.sender] = true;
numberOfVotes[_number] += 1;
allVotes += 1;
}

//add maxVotes functionality
//add contract owner
//contract owner can't vote
//add stop voting functionality
//only owner can't stop voting
//HARD
//add electionTime functionality using block.timestamp
function stopVote() public onlyOwner {
electionEndTime = block.timestamp;
}

function resetMaxVotes(uint256 _newMaxVotes) public onlyOwner {
require(_newMaxVotes > maxVotes,"You can`t decrease maxVotes");
maxVotes = _newMaxVotes;

}
}



Expand All @@ -42,4 +58,4 @@ contract Election {



}
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This project is smart contract, which allows to vote. At first you should declare a list of voters. Then you can determine maximum amount of votes, reset this amount, stop voting.
You can test this contract at [Remix IDE](https://remix.ethereum.org/)
129 changes: 88 additions & 41 deletions Store.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,28 @@ pragma solidity ^0.8.28;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract Store is Ownable {

/// @notice buyer => product_id => quantity
mapping(address => mapping(uint256 => uint256)) public userPurchase;
/// @notice product_id => quantity
mapping(uint256 => uint256) public productsPurchase;

struct Product {
string name;
uint256 id;
uint256 stock;
uint256 price;
}

/// @notice history of purchases
struct PurchaseHistory {
address buyer;
uint256 purchaseId;
uint256 totalAmount;
}
PurchaseHistory[] public purchasesForCurrentBuyer;

Product[] private products;
PurchaseHistory[] public purchases;
uint256 internal purchaseId;

event Purchase(address buyer, uint256 id, uint256 quantity);

Expand All @@ -29,58 +37,66 @@ contract Store is Ownable {

constructor() Ownable(msg.sender) {}

function buy(uint256 _id, uint256 _quantity) payable external {
require(_quantity>0, QuantityCantBeZero());
function buy(uint256 _id, uint256 _quantity) external payable {
require(_quantity > 0, QuantityCantBeZero());
require(getStock(_id) >= _quantity, OutOfStock());

uint256 totalPrice = getPrice(_id)*_quantity;
uint256 totalPrice = getPrice(_id) * _quantity;
require(msg.value >= totalPrice, NotEnoughtFunds());

//buy
_buyProcess(msg.sender,_id,_quantity);
if(msg.value > totalPrice) {
_buyProcess(msg.sender, _id, _quantity);

if (msg.value > totalPrice) {
payable(msg.sender).transfer(msg.value - totalPrice);
}
}

function batchBuy(uint256[] calldata _ids, uint256[] calldata _quantitys) payable external {
function batchBuy(uint256[] calldata _ids, uint256[] calldata _quantitys)
external
payable
{
require(_ids.length == _quantitys.length, "arrays lenghts mismatch");

uint256 totalPrice = 0;

for(uint i = 0; i < _ids.length; i++) {
for (uint256 i = 0; i < _ids.length; i++) {
uint256 q = _quantitys[i];
uint256 id = _ids[i];

require(q>0, QuantityCantBeZero());
require(q > 0, QuantityCantBeZero());
require(getStock(id) >= q, OutOfStock());

totalPrice += getPrice(id)*q;
totalPrice += getPrice(id) * q;
}

require(msg.value >= totalPrice, NotEnoughtFunds());

for(uint i = 0; i < _ids.length; i++) {
for (uint256 i = 0; i < _ids.length; i++) {
uint256 q = _quantitys[i];
uint256 id = _ids[i];

_buyProcess(msg.sender,id,q);
_buyProcess(msg.sender, id, q);
}

if(msg.value > totalPrice) {
if (msg.value > totalPrice) {
payable(msg.sender).transfer(msg.value - totalPrice);
}
}

function _buyProcess(address buyer, uint256 _id, uint256 _quantity) internal {
function _buyProcess(
address buyer,
uint256 _id,
uint256 _quantity
) internal {
Product storage product = findProduct(_id);
product.stock -= _quantity;

userPurchase[buyer][_id] += _quantity;
productsPurchase[_id] += _quantity;

emit Purchase(buyer,_id,_quantity);
setPurchaseHistory(buyer, product.price * _quantity);
emit Purchase(buyer, _id, _quantity);
}

function withdraw() external onlyOwner {
Expand All @@ -90,16 +106,21 @@ contract Store is Ownable {
payable(owner()).transfer(balance);
}

function addProduct(string calldata _name, uint256 _id, uint256 _stock, uint256 _price) external onlyOwner {
function addProduct(
string calldata _name,
uint256 _id,
uint256 _stock,
uint256 _price
) external onlyOwner {
require(!isIdExist(_id), IdAlreadyExist());
products.push(Product(_name,_id,_stock,_price));
products.push(Product(_name, _id, _stock, _price));
}

function deleteProduct(uint256 _id) external onlyOwner {
(bool status, uint256 index) = findIndexById(_id);
require(status,IdDoesNotExist());
require(status, IdDoesNotExist());

products[index] = products[products.length-1];
products[index] = products[products.length - 1];
products.pop();
}

Expand All @@ -113,56 +134,82 @@ contract Store is Ownable {
product.stock = _stock;
}

function getProducts() public view returns(Product[] memory) {
function getProducts() public view returns (Product[] memory) {
return products;
}

function getPrice(uint256 _id) public view returns(uint256) {
function getPrice(uint256 _id) public view returns (uint256) {
Product storage product = findProduct(_id);
return product.price;
}

function getStock(uint256 _id) public view returns(uint256) {
function getStock(uint256 _id) public view returns (uint256) {
Product storage product = findProduct(_id);
return product.stock;
}


function findProduct(uint256 _id) internal view returns(Product storage product) {
for(uint i = 0; i < products.length; i++) {
function findProduct(uint256 _id)
internal
view
returns (Product storage product)
{
for (uint256 i = 0; i < products.length; i++) {
if (products[i].id == _id) {
return products[i];
}
}
revert IdDoesNotExist();
}

function isIdExist(uint256 _id) internal view returns(bool) {
for(uint i = 0; i < products.length; i++) {
if(products[i].id == _id) {
function isIdExist(uint256 _id) internal view returns (bool) {
for (uint256 i = 0; i < products.length; i++) {
if (products[i].id == _id) {
return true;
}
}
return false;
}

function findIndexById(uint256 _id) internal view returns(bool, uint256) {
for(uint i = 0; i < products.length; i++) {
if(products[i].id == _id) {
function findIndexById(uint256 _id) internal view returns (bool, uint256) {
for (uint256 i = 0; i < products.length; i++) {
if (products[i].id == _id) {
return (true, i);
}
}
return (false, 0);
}

//HOMEWORK
// Add refund() function
// Add topSellingProducts() function
// Add getTotalRevenue() function
/// HomeTask

// Add getUserPurchase(address) function
///@notice Set history of purchases of current buyer
/// @param buyer Buyer
/// @param _totalAmout Sum, which buyer spend for purchase
function setPurchaseHistory(address buyer, uint256 _totalAmout) internal {
purchaseId++;
purchases.push(PurchaseHistory(buyer, purchaseId, _totalAmout));
}

// Add DISCOUNT_CODES functionality
/// @notice Refund money for last purchase for buyer
/// @param _buyer Buyer
// function refund(address _buyer) public payable {
// // надо отфлильтровать список транзакций и выбрать транзацию среди них с самым большим id
// PurchaseHistory memory lastPurchase = getLastPurchase(_buyer);
// }


/// @notice Get last purchase of buyer
/// address buyer Buyer
/// @return Purchase with max purchaseId among purchases of buyer
function getLastPurchase(address _buyer)
public
returns (PurchaseHistory memory)
{
for (uint256 i = 0; i < purchases.length; i++) {
if (purchases[i].buyer == _buyer) {
purchasesForCurrentBuyer.push(purchases[i]);
}
}

// Add Struct Purchase (if you want to)
}
return purchasesForCurrentBuyer[purchasesForCurrentBuyer.length - 1];
}
}