Created
May 3, 2019 08:55
-
-
Save joshorig/9f50427cdbe10478109608dd13be2cd3 to your computer and use it in GitHub Desktop.
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.5.0; | |
contract SupplyChain { | |
/* set owner */ | |
address owner; | |
/* Add a variable called skuCount to track the most recent sku # */ | |
uint private skuCount; | |
/* Add a line that creates a public mapping that maps the SKU (a number) to an Item. | |
Call this mappings items | |
*/ | |
/* Add a line that creates an enum called State. This should have 4 states | |
ForSale | |
Sold | |
Shipped | |
Received | |
(declaring them in this order is important for testing) | |
*/ | |
enum State{ForSale, Sold, Shipped, Received} | |
/* Create a struct named Item. | |
Here, add a name, sku, price, state, seller, and buyer | |
We've left you to figure out what the appropriate types are, | |
if you need help you can ask around :) | |
*/ | |
struct Item { | |
string name; | |
uint sku; | |
uint256 price; | |
State state; | |
address payable seller; | |
address payable buyer; | |
} | |
mapping(uint => Item) public items; | |
/* Create 4 events with the same name as each possible State (see above) | |
Each event should accept one argument, the sku*/ | |
event ForSale(uint sku, string name); | |
event Sold(uint sku); | |
event Shipped(uint sku); | |
event Received(uint sku); | |
/* Create a modifer that checks if the msg.sender is the owner of the contract */ | |
modifier verifyOwner(){ | |
require( | |
msg.sender == owner, | |
"Only the owner can call this function" | |
); | |
_; | |
} | |
modifier verifyCaller(address _address) { | |
require( | |
msg.sender == _address, | |
"Only verified role players can call this function" | |
); | |
_; | |
} | |
modifier restrictCaller(address _address) { | |
require( | |
msg.sender != _address, | |
"This caller cannot perform this function" | |
); | |
_; | |
} | |
modifier paidEnough(uint _price) { | |
require( | |
msg.value >= _price, | |
"You dont have enough money to make this purchase" | |
); | |
_; | |
} | |
modifier checkValue(uint _sku) { | |
//refund them after pay for item (why it is before, _ checks for logic before func) | |
_; | |
uint _price = items[_sku].price; | |
uint amountToRefund = msg.value - _price; | |
items[_sku].buyer.transfer(amountToRefund); | |
} | |
/* For each of the following modifiers, use what you learned about modifiers | |
to give them functionality. For example, the forSale modifier should require | |
that the item with the given sku has the state ForSale. */ | |
modifier checkItemState(uint _sku, State state){ | |
require( | |
items[_sku].state == state, | |
"This item is for sale." | |
); | |
_; | |
} | |
constructor() public { | |
owner = msg.sender; | |
skuCount = 0; | |
} | |
function addItem(string memory _name, uint _price) public returns(bool){ | |
items[skuCount] = Item(_name, skuCount, _price, State.ForSale, msg.sender, address(0)); | |
emit ForSale(skuCount, _name); | |
skuCount = skuCount + 1; | |
return true; | |
} | |
/* Add a keyword so the function can be paid. This function should transfer money | |
to the seller, set the buyer as the person who called this transaction, and set the state | |
to Sold. Be careful, this function should use 3 modifiers to check if the item is for sale, | |
if the buyer paid enough, and check the value after the function is called to make sure the buyer is | |
refunded any excess ether sent. Remember to call the event associated with this function!*/ | |
function buyItem(uint sku) | |
public | |
payable | |
checkItemState(sku,State.ForSale) | |
paidEnough(items[sku].price) | |
restrictCaller(items[sku].seller) | |
checkValue(sku) | |
{ | |
items[sku].state = State.Sold; | |
/*The address that calls the function is assigned as the buyer*/ | |
items[sku].buyer = msg.sender; | |
emit Sold(items[sku].sku); | |
items[sku].seller.transfer(items[sku].price); | |
} | |
/* Add 2 modifiers to check if the item is sold already, and that the person calling this function | |
is the seller. Change the state of the item to shipped. Remember to call the event associated with this function!*/ | |
function shipItem(uint sku) | |
public | |
checkItemState(sku,State.Sold) | |
verifyCaller(items[sku].seller) | |
{ | |
items[sku].state = State.Shipped; | |
emit Shipped(items[sku].sku); | |
} | |
/* Add 2 modifiers to check if the item is shipped already, and that the person calling this function | |
is the buyer. Change the state of the item to received. Remember to call the event associated with this function!*/ | |
function receiveItem(uint sku) | |
public | |
checkItemState(sku,State.Shipped) | |
verifyCaller(items[sku].buyer) | |
{ | |
items[sku].state = State.Received; | |
emit Received(items[sku].sku); | |
} | |
/* We have these functions completed so we can run tests, just ignore it :) */ | |
function fetchItem(uint _sku) public view returns (string memory name, uint sku, uint price, uint state, address seller, address buyer) { | |
name = items[_sku].name; | |
sku = items[_sku].sku; | |
price = items[_sku].price; | |
state = uint(items[_sku].state); | |
seller = items[_sku].seller; | |
buyer = items[_sku].buyer; | |
return (name, sku, price, state, seller, buyer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment