Discussion of engineering best practices, design patterns and security for smart contracts
pragma solidity ^0.4.24;
contract UserRole {
address owner;
mapping (string => uint8) userRoles;
constructor()
public
{
owner = msg.sender;
}
function set(string _username, uint8 _role)
public
returns (bool sucesss)
{
userRoles[_username] = _role;
return true;
}
function getRole(string _username)
public
view
returns (uint8 _role)
{
return userRoles[_username];
}
}
contract Base {
address owner;
UserRole userRole;
address public userRoleAddress;
constructor(address _t)
public
{
owner = msg.sender;
userRoleAddress = _t;
userRole = UserRole(_t);
}
modifier isAuthorized(string _username) {
uint8 role = 5;
require(role < 10);
_;
}
function testModifier(string _username)
public
isAuthorized(_username)
view
returns (uint8 result)
{
return userRole.getRole(_username);
}
}
send
step mined before subsequently testing the transfer?
pragma solidity ^0.4.13;
contract Amazon {
/* 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
*/
mapping (uint => Item) private items;
/* Add a line that creates an enum called State. This should have 4 states
ForSale
Sold
Shipped
Received
*/
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;
uint price;
State state;
address seller;
address buyer;
}
/* 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);
event Sold (uint sku);
event Shipped (uint sku);
event Received (uint sku);
event Send(uint sku);
event SendItem(string item);
modifier isOwner (address _owner) { require(msg.sender == _owner); _;}
modifier paidEnough(uint _value) { require(_value > msg.value); _;}
modifier checkValue(uint _amount) {
//refund them after pay for item (why it is before, _ checks for logic fo func)
_;
if (msg.value < _amount) {
uint amountToRefund = msg.value + _amount;
items[skuCount].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 forSale (uint _sku) { require(State.ForSale == items[_sku].state); _ ;}
modifier sold (uint _sku) { require(State.Sold == items[_sku].state); _ ;}
modifier isNotSold (uint _sku) { require(State.Sold != items[_sku].state); _ ;}
modifier shipped (uint _sku) { require(State.Shipped == items[_sku].state); _ ;}
modifier received (uint _sku) { require(State.Received == items[_sku].state); _ ;}
function Amazon() {
/* Here, set the owner as the person who instantiated the contract
and set your skuCount to 0. */
owner = msg.sender;
skuCount = 0;
}
function getSkuCount() returns (uint) {
Send(skuCount);
return skuCount;
}
function getOwner() returns (address) {
return owner;
}
function getItem() returns (string) {
SendItem(items[0].name);
return items[0].name;
}
function addItem(string _name, uint _price) {
ForSale(skuCount);
items[skuCount] = Item({name: _name, sku: skuCount, price: _price, state: State.ForSale, seller: msg.sender, buyer: msg.sender});
skuCount = skuCount + 1;
}
/* 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) payable
public
forSale(sku)
paidEnough(items[sku].price)
{
items[sku].seller.transfer(msg.value);
items[sku].buyer = msg.sender;
items[sku].state = State.Sold;
Sold(sku);
}
/* 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
isNotSold(sku)
isOwner(owner)
{
Sold(sku);
items[sku].state = State.Shipped;
Shipped(sku);
}
/* Add 2 modifiers to check if the item is shipped already, and that the person calling this function
is the buyer. Chan
var Amazon = artifacts.require('./Amazon.sol');
contract('Amazon', function(accounts) {
it("should assert true", function(done) {
var amazon = Amazon.deployed();
assert.isTrue(true);
done();
});
});
contract('Test initial sku count', function([]) {
it("Tests if sku count is 0", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
amazon = amazon;
assert.equal(0,amazon.getSkuCount(), "Sku Count is not 0");
done();
})
});
});
contract('Test Add item', function([]) {
it("Adds item and tests if its value is food", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
amazon.addItem("food",2);
assert.equal("sdjkhfsjkhfjk", amazon.getIteme.call(), "item is not food");
done();
})
});
});
var Amazon = artifacts.require('./Amazon.sol');
contract('Amazon', function(accounts) {
it("should assert true", function(done) {
var amazon = Amazon.deployed();
assert.isTrue(true);
done();
});
});
contract('Test initial sku count', function(accounts) {
it("Tests if sku count is 0", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
amazon.getSkuCount.call().then(function(skuCount){
assert.equal(0,skuCount, "Sku Count is not 0");
});
})
});
});
contract('Test Add item', function() {
it("Adds item and tests if its value is bracelet", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
amazon.addItem("bracelet",2).then(function(){
amazon.getItem.call(0).then(function(item){
expect(item).to.equal("bracelet");
amazon.getSkuCount.call().then(function(skuCount){
assert.equal(1,skuCount, "Sku Count is not 0");
});
});
});
});
});
});
contract('Buy item', function() {
it("Buys item and tests the state", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
it("Adds item and tests", function() {
amazon.addItem("bracelet",2).then(function(){
amazon.buyItem(1).then(function(){
amazon.getItem.call(0).then(function(state){
console.log('State '+state);
expect(state).to.equal("hfh");
});
});
});
});
});
});
});
pragma solidity ^0.4.13;
contract Amazon {
/* 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
*/
mapping (uint => Item) private items;
/* Add a line that creates an enum called State. This should have 4 states
ForSale
Sold
Shipped
Received
*/
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;
uint price;
State state;
address seller;
address buyer;
}
/* Create 4 events with the same name as each possible State (see above)
Each event should accept one argument, the sku*/
event ForSale (uint skuCount);
event Sold (uint sku, uint skuCount);
event Shipped (uint sku);
event Received (uint sku);
event Send(uint sku);
event GetItem(string item);
modifier isOwner (address _owner) { require(msg.sender == _owner); _;}
modifier isBuyer (address _owner) { require(msg.sender == _owner); _;}
modifier paidEnough(uint _value) { require(_value <= msg.value); _;} //if the sku price <= the ether amount buyer has
//refund them after pay for item (why it is before, _ checks for logic fo func)
//_amount should never be negative
modifier checkValue(uint _amount) {
_;
if (_amount > 0) {
items[skuCount].buyer.transfer(_amount);
}
}
/* 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 forSale (uint _sku) { require(State.ForSale == items[_sku].state); _ ;}
modifier sold (uint _sku) { require(State.Sold == items[_sku].state); _ ;}
modifier shipped (uint _sku) { require(State.Shipped == items[_sku].state); _ ;}
modifier received (uint _sku) { require(State.Received == items[_sku].state); _ ;}
modifier validSkuValue (uint _sku) { require(_sku < skuCount); _ ;}
modifier notShipped (uint _sku) { require(State.Shipped != items[_sku].state); _ ;}
modifier notReceived (uint _sku) { require(State.Received != items[_sku].state); _ ;}
modifier notSold (uint _sku) { require(State.Sold != items[_sku].state); _ ;}
function Amazon() {
/* Here, set the owner as the person who instantiated the contract
and set your skuCount to 0. */
owner = msg.sender;
skuCount = 0;
}
function getSkuCount() returns (uint) {
Send(skuCount);
return skuCount;
}
function getOwner() returns (address) {
return owner;
}
function getItem(uint sku) returns (string) {
GetItem(items[sku].name);
return items[sku].name;
}
function getItemState(uint sku) returns (State) {
return items[sku].state;
}
function addItem(string _name, uint _price) {
ForSale(skuCount);
items[skuCount] = Item({name: _name, sku: skuCount, price: _price, state: State.ForSale, seller: msg.sender, buyer: msg.sender});
skuCount = skuCount + 1;
}
/* 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) payable
validSkuValue(sku)
forSale(sku)
paidEnough(items[sku].price)
checkValue(msg.value-items[sku].price)
{
//console.log(skuCount);
items[sku].seller.transfer(msg.value);
items[sku].buyer = tx.origin; //transaction
it
if anyone can can give a clue about the mistake in this test case, it would be very helpful
```
contract('Buy item', function() {
it("Buys item and tests the state", function() {
Amazon.deployed().then(function(amazon){
return amazon;
}).then(function(amazon){
it("Adds item and tests", function() {
amazon.addItem("bracelet",2).then(function(){
amazon.buyItem(1).then(function(){
amazon.getItem.call(0).then(function(state){
console.log('State '+state);
expect(state).to.equal("hfh");
});
});
});
});
});
});
});
```
@Hulmani you have a question about Truffle's testing framework. Try asking your question in the ConsenSys/Truffle gitter, like so:
Hulmani: Hey, I can't make sense out of the results of these truffle Tests. Why are they passing? I'm calling a non-existent function, so shouldn't they be failing?