Discussion of engineering best practices, design patterns and security for smart contracts
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?
hello i deploy
function deposit(uint256 amount) {
// transfer the tokens from the sender to this contract
balances[msg.sender] = balances[msg.sender].add(amount);
ERC20(tracker_0x_address).transferFrom(msg.sender, this, amount);
}
when call deposit remix alert
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Error: gas required exceeds allowance or always failing transaction at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:1402159 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:932233 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:350777 at o (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:369008) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353607 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:350777 at c (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353883) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353921 at Ht (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:363290) at Object.<anonymous> (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:354010) at e.value (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:933148) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:932715 at n (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:368952) at o (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:369030) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353607 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:932681 at n (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:368952) at o (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:369030) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353607 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:933054 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:354417 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:350777 at c (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353883) at s (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353805) at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:353607 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:354397 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:932936 at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:931373 at i (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/background.js:1:1070602)
truffle migrate --reset
if(receiveBGL > SALESUPPLY.sub(TokenSold)){
//Calculation remaining tokens
uint remainingTokens = SALESUPPLY.sub(TokenSold);
emit LogDebug(remainingTokens);
//Calculating price of token left
uint tokenPriceInWei = remainingTokens.div(rate);
emit LogDebug(tokenPriceInWei);
//Calculation amount of wei to send back
uint amountExceeds = weiPayment.sub(tokenPriceInWei);
emit LogDebug(amountExceeds);
//Sending back to recipient
_recipient.transfer(123);
//Updating token that recipient will receive
receive = remainingTokens;
}
contract contractB {
using SafeMath for uint256;
address tracker_0x_address = 0x6b42FE821b653A0eae1a52249BF5cd58D1100890; // ContractA Address
address to_address = 0xe459024A10b6Ed6189998706B8fd72fD0Dd00b97;
mapping ( address => uint256 ) public balances;
function sendTokens (uint256 amount) public
{
//tokenAddress is the address of the ERC20 token deployed on Ropsten
ERC20(tracker_0x_address).transfer(to_address, amount);
}
}
address
and the other a uint
. In my web3 front end, I almost always want to get both of these properties at the same time. I’ve implemented a get method in the contract that returns both properteis together, and I’m using this rather than declaring each property public. This makes accessing the data in my frontend easier, and actually requires about 1,000 less gas on deployment. Is there any downside to this approach that I’m missing?
Hi I'm trying to create a crowdfund type contract whereby someone can create a 'mother' token and then go on to create child tokens that are forever attached to the mother.
I had a little search and came up with the following code:
import './Child.sol';
mapping(bytes32 => Child) childList;
mapping(bytes32 => Child) childList;
}
function createMotherToken (address producer) public {
producer = msg.sender;
}
function spawnChild(bytes32 childId) {
Child current = new Child();
childList[childId] = current;
}
function callChildFunction(bytes32 childId) {
childList[childId].theChildfunction();
}