diff --git a/contracts/SimpleStorage.sol b/contracts/SimpleStorage.sol
index a70b166..dc25821 100644
--- a/contracts/SimpleStorage.sol
+++ b/contracts/SimpleStorage.sol
@@ -3,12 +3,18 @@ pragma solidity >=0.5.0 <0.8.0;
contract SimpleStorage {
uint256 public storedData;
+ address owner = msg.sender;
+
+ constructor(uint256 _num) public {
+ storedData = _num;
+ }
function getStoredData() public view returns (uint256) {
return storedData;
}
function setStoredData(uint256 x) public {
+ require(msg.sender == owner, "Not the owner!");
storedData = x;
}
}
diff --git a/migrations/2_deploy_simple_storage.js b/migrations/2_deploy_simple_storage.js
index 13b9825..4c30224 100644
--- a/migrations/2_deploy_simple_storage.js
+++ b/migrations/2_deploy_simple_storage.js
@@ -1,5 +1,6 @@
const SimpleStorage = artifacts.require("SimpleStorage");
module.exports = function(deployer) {
- deployer.deploy(SimpleStorage);
+ /* invoke SimpleStorage's constructor, and pass 12 as its first argument */
+ deployer.deploy(SimpleStorage, 12);
}
diff --git a/steps.md b/steps.md
index ce755df..5989e63 100644
--- a/steps.md
+++ b/steps.md
@@ -1,17 +1,19 @@
# Truffle BDD/TDD walkthrough
+- [Truffle BDD/TDD walkthrough](#truffle-bddtdd-walkthrough)
- [Project initialization](#project-initialization)
- [SimpleStorage Behavior](#simplestorage-behavior)
- * [the contract test](#the-contract-test)
- * [the Contract subject](#the-contract-subject)
- * [the migration](#the-migration)
- * [business logic](#business-logic)
- + [define initial deployment value of storedData](#define-initial-deployment-value-of-storeddata)
- - [test: watch it fail](#test--watch-it-fail)
- + [implement getStoredData](#implement-getstoreddata)
- - [test: getStoredData](#test--getstoreddata)
- + [define setStoredData behavior](#define-setstoreddata-behavior)
+ - [the contract test](#the-contract-test)
+ - [the Contract subject](#the-contract-subject)
+ - [the migration](#the-migration)
+ - [business logic](#business-logic)
+ - [define initial deployment value of storedData](#define-initial-deployment-value-of-storeddata)
+ - [test: watch it fail](#test-watch-it-fail)
+ - [implement getStoredData](#implement-getstoreddata)
+ - [test: getStoredData](#test-getstoreddata)
+ - [define setStoredData behavior](#define-setstoreddata-behavior)
- [implement setStoredData](#implement-setstoreddata)
+ - [implement constructor and a way to ensure only the owner is able to execute setStoredData](#implement-constructor-and-a-way-to-ensure-only-the-owner-is-able-to-execute-setstoreddata)
- [Conclusion](#conclusion)
Table of contents generated with markdown-toc
@@ -274,9 +276,12 @@ test, contract and migration pieces in place
Our SimpleStorage contract should have:
- [ ] a state, `storedData`. This is the location to store an integer value
- - [ ] its `storedData` value at deployment be zero
+ - [ ] its `storedData` value at deployment be 12
- [ ] a function `getStoredData`, to retrieve the current `storedData` value.
- [ ] a function `setStoredData`, to set the `storedData` value.
+ - [ ] a constructor to set the initial value of `storedData`.
+ - [ ] a contract `owner`.
+ - [ ] a way to ensure only the contract `owner` is able to call the `setStoredData` function.
### define initial deployment value of storedData
@@ -291,12 +296,12 @@ contract("SimpleStorage", (/* accounts */) => {
assert.isTrue(true);
});
- it("was deployed and it's intial value is 0", async () => {
+ it("was deployed and its intial value is 12", async () => {
// get subject
const ssInstance = await SimpleStorage.deployed();
- // verify it starts with zero
+ // verify it starts with 12
const storedData = await ssInstance.getStoredData.call();
- assert.equal(storedData, 0, `Initial state should be zero`);
+ assert.equal(storedData, 12, `Initial state should be 12`);
});
});
});
@@ -334,7 +339,7 @@ Compiling your contracts...
Contract: SimpleStorage
Initial deployment
✓ should assert true
- 1) was deployed and it's intial value is 0
+ 1) was deployed and its intial value is 12
> No events were emitted
@@ -343,7 +348,7 @@ Compiling your contracts...
1) Contract: SimpleStorage
Initial deployment
- was deployed and it's intial value is 0:
+ was deployed and its intial value is 12:
TypeError: Cannot read property 'call' of undefined
at Context.it (test/simple_storage.js:14:57)
at process._tickCallback (internal/process/next_tick.js:68:7)
@@ -404,7 +409,7 @@ Compiling your contracts...
Contract: SimpleStorage
Initial deployment
✓ should assert true
-✓ was deployed and it's intial value is 0
+✓ was deployed and its intial value is 12
2 passing (63ms)
@@ -414,16 +419,15 @@ Initial deployment
:tada: SimpleStorage has:
- [x] a state, `storedData`. This is the location to store an integer value
- - [x] its `storedData` value at deployment be zero
+ - [x] its `storedData` value at deployment be 12
- [x] a function `getStoredData`, to retrieve the current `storedData` value.
- [ ] a function `setStoredData`, to set the `storedData` value.
-> :question:Something to ponder for later: we didn't initialize the state, yet its initial
-> value is zero. Why do you think that is? If you can't figure out yourself, read this [section](https://solidity.readthedocs.io/en/v0.7.0/control-structures.html#scoping-and-declarations) from the Solidity documentation.
+> :information_desk_person: Please note, we have declared and initialized the storedData variable, but solidity has rules for default values for unintialized variables. See [section](https://solidity.readthedocs.io/en/v0.7.0/control-structures.html#scoping-and-declarations) from the Solidity documentation.
### define setStoredData behavior
-There's one bit of feature missing. Lets implement!
+Lets implement the next part!
- [ ] a function `setStoredData`, to set the `storedData` value.
Add the following `describe` block to our test and run truffle test.
@@ -469,7 +473,7 @@ Compiling your contracts...
Contract: SimpleStorage
Initial deployment
✓ should assert true
-✓ was deployed and it's intial value is 0
+✓ was deployed and its intial value is 12
Functionality
1) should store the value 42
> No events were emitted
@@ -528,7 +532,7 @@ Compiling your contracts...
Contract: SimpleStorage
Initial deployment
✓ should assert true
-✓ was deployed and it's intial value is 0
+✓ was deployed and its intial value is 12
Functionality
1) should store the value 42
> No events were emitted
@@ -588,7 +592,7 @@ Compiling your contracts...
Contract: SimpleStorage
Initial deployment
✓ should assert true
-✓ was deployed and it's intial value is 0
+✓ was deployed and its intial value is 12
Functionality
✓ should store the value 42 (55ms)
@@ -597,6 +601,148 @@ Initial deployment
```
+#### implement constructor and a way to ensure only the owner is able to execute setStoredData
+
+Add the following `it` block to the Functionality `describe` block test and run truffle test.
+
+``` javascript
+it("should not let someone else change the variable", async () => {
+ const [ owner, badBob ] = accounts;
+ const ssInstance = await SimpleStorage.new(42, { from: owner });
+
+ /*
+ *
+ * @comment: if you wanted to interact with web3, here is an
+ * example of checking the balance of an account and outputting
+ * the result to the test console
+ *
+ * const balance = await web3.eth.getBalance(owner);
+ * console.log(balance);
+ *
+ */
+
+ try {
+ await ssInstance.setStoredData(22, { from: badBob });
+ } catch(err) { }
+
+ const storedData = await ssInstance.getStoredData.call();
+ assert.equal(storedData, 42, "storedData was not changed!");
+});
+
+```
+
+> :question: Try to predict the test outcome.
+
+``` sh
+$ truffle test
+```
+
+ see output
+
+``` sh
+$ truffle test
+
+Compiling your contracts...
+===========================
+> Compiling ./contracts/Migrations.sol
+> Compiling ./contracts/SimpleStorage.sol
+> Artifacts written to /tmp/test--42579-z0xosuySymKs
+> Compiled successfully using:
+- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
+
+
+
+Contract: SimpleStorage
+Initial deployment
+✓ should assert true
+✓ was deployed and its intial value is 12
+Functionality
+✓ should store the value 42
+1) should not let someone else change the variable
+> No events were emitted
+
+
+3 passing (82ms)
+ 1 failing
+
+ 1) Contract: SimpleStorage
+ Functionality
+ should not let someone else change the variable:
+ Error: Invalid number of parameters for "undefined". Got 2 expected 0!
+ at Context. (test/simple_storage.js:33:49)
+at processImmediate (internal/timers.js:461:21)
+```
+
+
+
+
+> :information_desk_person: `Error: Invalid number of parameters for "undefined".
+> Got 2 expected 0!`
+> This error indicates that we haven't included a constructor parameter and set
+> the contract owner.
+
+Add and initialize the following state variable to the SimpleStorage contract
+
+``` solidity
+address owner = msg.sender;
+```
+
+Add the following constructor to the SimpleStorage contract
+
+``` solidity
+constructor(uint256 _num) public {
+ storedData = _num;
+}
+```
+
+Add the following require statement to the top of the setStoredData function in SimpleStorage contract
+
+``` solidity
+require(msg.sender == owner, "Not the owner!");
+```
+
+Initialize the storedData value to 12 by adding a parameter in 2_deploy_simple_storage.js
+
+``` solidity
+module.exports = function(deployer) {
+ /* invoke SimpleStorage's constructor, and pass 12 as its first argument */
+ deployer.deploy(SimpleStorage, 12);
+}
+```
+
+Lets run truffle test once again
+
+``` sh
+$ truffle test
+```
+
+see results
+
+``` sh
+Compiling your contracts...
+===========================
+> Compiling ./contracts/Migrations.sol
+> Compiling ./contracts/SimpleStorage.sol
+> Artifacts written to /tmp/test--44360-9r4fMMWnmb6y
+> Compiled successfully using:
+- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
+
+
+
+Contract: SimpleStorage
+Initial deployment
+✓ should assert true
+✓ was deployed and its intial value is 12
+ Functionality
+✓ should store the value 42 (55ms)
+✓ should not let someone else change the variable
+
+
+4 passing (125ms)
+```
+
+
+
:tada: :sparkles: Congratulations! You did it! I hope this exercise was helpful and recommend you
continue exploring.
diff --git a/test/simple_storage.js b/test/simple_storage.js
index 7231fdc..9909279 100644
--- a/test/simple_storage.js
+++ b/test/simple_storage.js
@@ -7,12 +7,12 @@ contract("SimpleStorage", function (accounts) {
assert.isTrue(true);
});
- it("was deployed and it's intial value is 0", async () => {
+ it("was deployed and its intial value is 12", async () => {
// get subject
const ssInstance = await SimpleStorage.deployed();
- // verify it starts with zero
+ // verify it starts with 12
const storedData = await ssInstance.getStoredData.call();
- assert.equal(storedData, 0, `Initial state should be zero`);
+ assert.equal(storedData, 12, `Initial state should be 12`);
});
});
describe("Functionality", () => {
@@ -27,5 +27,28 @@ contract("SimpleStorage", function (accounts) {
const storedData = await ssInstance.getStoredData.call();
assert.equal(storedData, 42, `${storedData} was not stored!`);
});
+
+ it("should not let someone else change the variable", async () => {
+ const [ owner, badBob ] = accounts;
+ const ssInstance = await SimpleStorage.new(42, { from: owner });
+
+ /*
+ *
+ * @comment: if you wanted to interact with web3, here is an
+ * example of checking the balance of an account and outputting
+ * the result to the test console
+ *
+ * const balance = await web3.eth.getBalance(owner);
+ * console.log(balance);
+ *
+ */
+
+ try {
+ await ssInstance.setStoredData(22, { from: badBob });
+ } catch(err) { }
+
+ const storedData = await ssInstance.getStoredData.call();
+ assert.equal(storedData, 42, "storedData was not changed!");
+ });
});
});