├── README.md ├── Inheritance ├── Destroyable.sol ├── Ownable.sol ├── ExternalContract.sol └── HelloWorld.sol ├── Part 3: Inputting Data Within an Array.sol ├── Question 1.sol ├── Part 4: Public Mapping.sol ├── Part 1: Variables.sol ├── Part 12: Data Location Assignment.sol ├── Question 4.sol ├── Part 5: Private Mapping.sol ├── Part 6: Private Mapping with If & Else.sol ├── Part 2: Variables and Functions.sol ├── Part 7: Private Visibility.sol ├── Part 9: Require and Assert Without Notes.sol ├── Part 13: Assignment Answer.sol ├── Part 15: Receiving Money.sol ├── Identity Management.sol ├── Part 10: Modifiers.sol ├── Part 14: Events.sol ├── Part 16: Balance Modifier.sol ├── Part 17: Transfer.sol ├── Part 18: Send.sol ├── Aeromexico - Updated.sol ├── Aeromexico.sol ├── CertificateOfOrigin.sol ├── Smart Certification.sol ├── Part 19: Payable vs. Normal Address.sol ├── Part 11: Data Location.sol └── Part 8: Require and Assert with Notes.sol /README.md: -------------------------------------------------------------------------------- 1 | # blockchainforbusiness 2 | Welcome to Blockchain for Business. 3 | In here, you will find all the files related to the course. 4 | Good luck! 5 | -------------------------------------------------------------------------------- /Inheritance/Destroyable.sol: -------------------------------------------------------------------------------- 1 | import "./Ownable.sol"; 2 | pragma solidity 0.6.6; 3 | contract Destroyable is Ownable { 4 | 5 | 6 | function destroy() public onlyOwner { 7 | address payable receiver = msg.sender; 8 | selfdestruct(receiver); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Inheritance/Ownable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Ownable { 3 | 4 | address public owner; 5 | 6 | modifier onlyOwner (){ 7 | require (msg.sender == owner); 8 | _; 9 | } 10 | constructor () public{ 11 | owner = msg.sender; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Part 3: Inputting Data Within an Array.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person { 4 | string name; 5 | uint height; 6 | uint age; 7 | } 8 | Person [] public people; 9 | function createPerson (string memory name, uint height, uint age) public{ 10 | 11 | Person memory newPerson; 12 | newPerson.name = name; 13 | newPerson.age = age; 14 | newPerson.height = height; 15 | people.push (newPerson); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Question 1.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract HelloWorld { 4 | 5 | string public message = "Hello World; 6 | 7 | uint public number = 123; 8 | 9 | bool public ishappy = true 10 | 11 | address public contractCreator = 0xBf2916234279507F56f8A4F79889529dd9CCA018; 12 | 13 | uint [] public numbers = [1,20,45]; 14 | 15 | string [] public messages = ["hello", "hello hatem", "hello world"]; 16 | 17 | function getMessage () public view returns (string memory){ 18 | return message; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Part 4: Public Mapping.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person { 4 | 5 | string name; 6 | uint age; 7 | uint height; 8 | } 9 | 10 | mapping (address => Person) public people; 11 | 12 | function createPerson (string memory name, uint age, uint height) public{ 13 | 14 | address creator = msg.sender; 15 | 16 | Person memory newPerson; 17 | newPerson.name = name; 18 | newPerson.age= age; 19 | newPerson.height= height; 20 | 21 | people [creator] = newPerson; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Part 1: Variables.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract HelloWorld { 4 | 5 | string public message = "Hello World"; 6 | 7 | uint public number = 123; 8 | 9 | bool public ishappy = true; 10 | 11 | address public contractCreator = 0xBf2916234279507F56f8A4F79889529dd9CCA018; 12 | 13 | uint [] public numbers = [1,20,45]; 14 | //This array here does not need a function, but there is the getNumber function to see how the function works. 15 | 16 | string [] public messages = ["hello", "hello hatem", "hello world"]; 17 | // This array does not need a function to be displayed. 18 | 19 | } 20 | -------------------------------------------------------------------------------- /Part 12: Data Location Assignment.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.1; 2 | contract MemoryAndStorage { 3 | 4 | mapping(uint => User) users; 5 | 6 | struct User{ 7 | uint id; 8 | uint balance; 9 | } 10 | 11 | function addUser(uint id, uint balance) public { 12 | users[id] = User(id, balance); 13 | } 14 | 15 | function updateBalance(uint id, uint balance) public { 16 | User memory user = users[id]; 17 | user.balance = balance; 18 | } 19 | 20 | function getBalance(uint id) view public returns (uint) { 21 | return users[id].balance; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /Question 4.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract HelloWorld { 4 | 5 | string public message = "Hello World"; 6 | 7 | uint [] public numbers = [1,20,45]; 8 | //This array here does not need a function, but there is the getNumber function to see how the function works. 9 | 10 | string [] public messages = ["hello", "hello Karla", "hello world"]; 11 | // This array does not need a function to be displayed. 12 | 13 | function setMessage (string memory newMessage) public{ 14 | message = newMessage; 15 | } 16 | 17 | function addNumber (uint newNumber) public { 18 | numbers.push (newNumber); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Part 5: Private Mapping.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract Identity{ 4 | 5 | struct Person{ 6 | string name; 7 | uint age; 8 | uint height; 9 | } 10 | 11 | mapping (address => Person) private people; 12 | 13 | function createPerson (string memory name, uint age, uint height) public{ 14 | 15 | address creator = msg.sender; 16 | 17 | Person memory newPerson; 18 | newPerson.name = name; 19 | newPerson.age = age; 20 | newPerson.height = height; 21 | 22 | people [creator] = newPerson; 23 | } 24 | 25 | function getPerson () public view returns (string memory name, uint age, uint height){ 26 | address creator = msg.sender; 27 | return (people [creator].name, people [creator].age, people [creator].height); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Part 6: Private Mapping with If & Else.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract Identity{ 4 | struct Person{ 5 | string name; 6 | uint age; 7 | uint height; 8 | bool senior; 9 | } 10 | 11 | mapping (address => Person) private people; 12 | 13 | function createPerson (string memory name, uint age, uint height) public{ 14 | 15 | address creator = msg.sender; 16 | 17 | Person memory newPerson; 18 | newPerson.name=name; 19 | newPerson.age=age; 20 | newPerson.height=height; 21 | 22 | if (age >= 65){ 23 | newPerson.senior = true; 24 | } 25 | else { 26 | newPerson.senior = false; 27 | } 28 | 29 | people [creator] = newPerson; 30 | } 31 | 32 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior) { 33 | address creator = msg.sender; 34 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Part 2: Variables and Functions.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract HelloWorld{ 4 | 5 | string public message = "Hello World"; 6 | 7 | uint public number = 123; 8 | 9 | bool public ishappy = true; 10 | 11 | address public contractCreator = 0xBf2916234279507F56f8A4F79889529dd9CCA018; 12 | 13 | uint [] public numbers = [1,20,45]; 14 | //This array here does not need a function, but there is the getNumber function to see how the function works. 15 | 16 | string [] public messages = ["hello", "hello hatem", "hello world"]; 17 | // This array does not need a function to be displayed. 18 | 19 | function getMessage() public view returns (string memory){ 20 | return message; 21 | } 22 | 23 | function setMessage (string memory newMessage) public{ 24 | message = newMessage; 25 | } 26 | 27 | function getNumber (uint index) public view returns (uint){ 28 | return numbers [index]; 29 | } 30 | function setNumber (uint newNumber, uint index) public{ 31 | numbers [index] = newNumber; 32 | } 33 | function addNumber (uint newNumber) public { 34 | numbers.push (newNumber); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Part 7: Private Visibility.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | mapping (address=>Person) private people; 11 | 12 | function createPerson (string memory name, uint age, uint height) public{ 13 | Person memory newPerson; 14 | newPerson.name = name; 15 | newPerson.age = age; 16 | newPerson.height= height; 17 | 18 | if(age>=65){ 19 | newPerson.senior=true; 20 | } 21 | else { 22 | newPerson.senior = false; 23 | } 24 | insertPerson (newPerson); 25 | //here we need to call the insertPerson function to replace the functionality that we had here before. 26 | } 27 | 28 | function insertPerson (Person memory newPerson) private{ 29 | address creator = msg.sender; 30 | people[creator] = newPerson; 31 | } 32 | 33 | function getperson () public view returns (string memory name, uint age, uint height, bool senior) { 34 | address creator = msg.sender; 35 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Inheritance/ExternalContract.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | // This part is for the interface (definition). 4 | interface HelloWorld { 5 | function createPerson (string calldata name, uint age, uint height) external payable; 6 | } 7 | 8 | //This part is for the location. 9 | contract ExternalContract { 10 | HelloWorld instance = HelloWorld (0x......................); 11 | //This statement: 1. creates a state variable of type "HelloWorld", which is defined in the interface up there. And 12 | // 2. Specifies the location which is the address above. 13 | 14 | function externalCreatePerson (string memory name, uint age, uint height) public payable{ 15 | // we need to call the createPerson function int he HelloWorld Contract. 16 | // We want to forward any Ether to the HelloWorld Contract because the createPerson function expects 1 Ether still 17 | // and we need to send that to this function when we call it and that needs to be forwarded to the HelloWorld contract to 18 | // the createPerson function. That is why, we need the address by deploying the HelloWorld contract, which will give us 19 | // a contract address. 20 | 21 | // We can now use the instance created above to call the following function: 22 | 23 | instance.createPerson{value:msg.value} (name, age, height); 24 | // the quick normal thing to do is usually instance.createPerson (name, age, height); but we also need 25 | // to forward the actual Ether that we got from "externalCreatePerson" into this function "instance.createPerson", 26 | // so we need to have a "value" and in order to attach some Ether to this function call, we will attach 27 | // :msg.value at the end. At this point, you can provide the arguments (name, age, height). 28 | // This means you will have two function calls between {} and (). 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Part 9: Require and Assert Without Notes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | address public owner; 10 | 11 | constructor () public { 12 | owner = msg.sender; 13 | } 14 | 15 | mapping (address =>Person) private people; 16 | address [] private creators; 17 | 18 | function createPerson (string memory name, uint age, uint height) public{ 19 | require (age<150, "age must be below 150"); 20 | Person memory newPerson; 21 | newPerson.name = name; 22 | newPerson.age = age; 23 | newPerson.height = height; 24 | if(age >=65) { 25 | newPerson.senior = true; 26 | } 27 | else { 28 | newPerson.senior = false; 29 | } 30 | insertPerson (newPerson); 31 | creators.push (msg.sender); 32 | assert ( 33 | keccak256 ( 34 | abi.encodePacked ( 35 | people[msg.sender].name, 36 | people[msg.sender].age, 37 | people[msg.sender].height, 38 | people[msg.sender].senior)) == 39 | keccak256 ( 40 | abi.encodePacked ( 41 | newPerson.name, 42 | newPerson.age, 43 | newPerson.height, 44 | newPerson.senior 45 | ) 46 | ) 47 | ); 48 | } 49 | 50 | function insertPerson (Person memory newPerson) private{ 51 | address creator = msg.sender; 52 | people[creator] = newPerson; 53 | } 54 | 55 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 56 | address creator = msg.sender; 57 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 58 | } 59 | 60 | function deletePerson (address creator) public { 61 | require (owner == msg.sender, "message sender is owner"); 62 | delete people[creator]; 63 | assert (people[creator].age == 0); 64 | } 65 | 66 | function getCreator (uint index) public view returns (address){ 67 | require (owner == msg.sender); 68 | return creators[index]; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /Part 13: Assignment Answer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.1; 2 | contract MemoryAndStorage { 3 | 4 | mapping(uint => User) users; 5 | 6 | struct User{ 7 | uint id; 8 | uint balance; 9 | } 10 | 11 | function addUser(uint id, uint balance) public { 12 | users[id] = User(id, balance); 13 | } 14 | 15 | function updateBalance(uint id, uint balance) public { 16 | users[id].balance = balance; 17 | } 18 | 19 | // a user (with small u) is new information. It is defined by referring to the User struct saved in the storage. 20 | // Thus, it consists of an id and a balance. Therefore, the user id and balance must be explained. 21 | // This user is going to have an id within the users mapping. so no changes to the id. 22 | // The id within the struct and the users mapping, is getting stored within the User memory variable . . . or storage? 23 | 24 | // what about the balance? 25 | 26 | // The problem we have here is that we tried to store the id of the mapping users 27 | // within a user memory variable. And then, we went and modified that user memory variable 28 | // and changed its balance, as explained below. Consequently, user became a local variable stored in memory. 29 | 30 | //If you want to store the id of the mapping users within a variable, the easiest solution is 31 | // to change memory to storage. This will allow the local variable user 32 | // to be a direct pointer to the User that is in the mapping value. 33 | 34 | // Another way to solve the problem is to have users[id].balance = balance. 35 | // In here, You are not creating new information that makes reference to other saved information. 36 | // In here, you are not storing the id of the mapping users in a variable that needs reference. 37 | // same like in previous smart contracts, when we did people[creator] = newPerson; 38 | // That is the same thing as the first solution, but accomplished in one line. 39 | // This is because the mapping users is added to storage automatically, so there is no need to mention 40 | // any storage. You will be able in this case to direct and change the balance in the mapping itself. 41 | 42 | function getBalance(uint id) view public returns (uint) { 43 | return users[id].balance; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /Part 15: Receiving Money.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person { 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | 14 | modifier onlyOwner () { 15 | require (msg.sender == owner); 16 | _; 17 | } 18 | 19 | address public owner; 20 | uint public balance; 21 | 22 | constructor () public{ 23 | owner = msg.sender; 24 | } 25 | 26 | mapping (address => Person) private people; 27 | address [] private creators; 28 | 29 | 30 | function createPerson (string memory name, uint age, uint height) public payable{ 31 | require (age < 150, "age must be less than 150"); 32 | require (msg.value >= 1 ether); 33 | balance += msg.value; 34 | //this adds the value to the balance that you defined as a state variable above. 35 | 36 | Person memory newPerson; 37 | newPerson.name = name; 38 | newPerson.age = age; 39 | newPerson.height = height; 40 | if (age >=65){ 41 | newPerson.senior = true; 42 | } 43 | else { 44 | newPerson.senior = false; 45 | } 46 | insertPerson(newPerson); 47 | creators.push (msg.sender); 48 | assert ( 49 | keccak256 ( 50 | abi.encodePacked ( 51 | people[msg.sender].name, 52 | people[msg.sender].age, 53 | people[msg.sender].height, 54 | people[msg.sender].senior)) 55 | == 56 | keccak256 ( 57 | abi.encodePacked ( 58 | newPerson.name, 59 | newPerson.age, 60 | newPerson.height, 61 | newPerson.senior))); 62 | emit personCreated (newPerson.name, newPerson.senior); 63 | } 64 | 65 | function insertPerson (Person memory newPerson) private{ 66 | address creator = msg.sender; 67 | people[creator] = newPerson; 68 | } 69 | 70 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 71 | address creator = msg.sender; 72 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 73 | } 74 | 75 | function deletePerson (address creator) public onlyOwner { 76 | string memory name = people[creator].name; 77 | bool senior = people[creator].senior; 78 | delete people[creator]; 79 | assert (people[creator].age ==0); 80 | emit personDeleted (name, senior, msg.sender); 81 | 82 | } 83 | 84 | function getCreator (uint index) public view onlyOwner returns (address){ 85 | return creators[index]; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /Identity Management.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | address public owner; 10 | 11 | constructor () public{ 12 | owner = msg.sender; 13 | } 14 | 15 | mapping (address =>Person) private people; 16 | address [] private creators; 17 | 18 | function createPerson (string memory name, uint age, uint height) public{ 19 | require (age<150, "age must be below 150"); 20 | Person memory newPerson; 21 | newPerson.name = name; 22 | newPerson.age = age; 23 | newPerson.height = height; 24 | if(age >=65) { 25 | newPerson.senior = true; 26 | } 27 | else { 28 | newPerson.senior = false; 29 | } 30 | insertPerson (newPerson); 31 | creators.push (msg.sender); 32 | assert ( 33 | keccak256 ( 34 | abi.encodePacked ( 35 | people[msg.sender].name, 36 | people[msg.sender].age, 37 | people[msg.sender].height, 38 | people[msg.sender].senior)) == 39 | keccak256 ( 40 | abi.encodePacked ( 41 | newPerson.name, 42 | newPerson.age, 43 | newPerson.height, 44 | newPerson.senior 45 | ) 46 | ) 47 | ); 48 | } 49 | 50 | function insertPerson (Person memory newPerson) private{ 51 | address creator = msg.sender; 52 | people[creator] = newPerson; 53 | } 54 | 55 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 56 | address creator = msg.sender; 57 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 58 | } 59 | 60 | function deletePerson (address creator) public { 61 | require (owner == msg.sender); 62 | delete people[creator]; 63 | assert (people[creator].age == 0); 64 | } 65 | 66 | function getCreatorByNumber (uint index) public view returns (address){ 67 | require (owner == msg.sender); 68 | return creators[index]; 69 | } 70 | 71 | function getCreatorByAddress (address creator) public view returns (string memory name, uint age, uint height, bool senior){ 72 | require (owner == msg.sender); 73 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Part 10: Modifiers.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | address public owner; 10 | 11 | modifier onlyOwner (){ 12 | //the modifier name is onlyOwner because we want to restrict some functions to use of the owner only. 13 | require (msg.sender == owner); 14 | // here we just moved the require function to here instead of under the delete and getCreator functions. 15 | _; 16 | //this means continue the execution. 17 | } 18 | 19 | constructor () public{ 20 | owner = msg.sender; 21 | } 22 | 23 | mapping (address =>Person) private people; 24 | address [] private creators; 25 | 26 | function createPerson (string memory name, uint age, uint height) public{ 27 | require (age<150, "age must be below 150"); 28 | Person memory newPerson; 29 | newPerson.name = name; 30 | newPerson.age = age; 31 | newPerson.height = height; 32 | if(age >=65) { 33 | newPerson.senior = true; 34 | } 35 | else { 36 | newPerson.senior = false; 37 | } 38 | insertPerson (newPerson); 39 | creators.push (msg.sender); 40 | assert ( 41 | keccak256 ( 42 | abi.encodePacked ( 43 | people[msg.sender].name, 44 | people[msg.sender].age, 45 | people[msg.sender].height, 46 | people[msg.sender].senior 47 | ) 48 | ) 49 | == 50 | keccak256 ( 51 | abi.encodePacked ( 52 | newPerson.name, 53 | newPerson.age, 54 | newPerson.height, 55 | newPerson.senior 56 | ) 57 | ) 58 | ); 59 | } 60 | 61 | function insertPerson (Person memory newPerson) private{ 62 | address creator = msg.sender; 63 | people[creator] = newPerson; 64 | } 65 | 66 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 67 | address creator = msg.sender; 68 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 69 | } 70 | 71 | function deletePerson (address creator) public onlyOwner { 72 | delete people[creator]; 73 | assert (people[creator].age == 0); 74 | } 75 | 76 | function getCreator (uint index) public view onlyOwner returns (address){ 77 | return creators[index]; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /Part 14: Events.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | address public owner; 14 | 15 | modifier onlyOwner (){ 16 | //the modifier name is onlyOwner because we want to restrict some functions to use of the owner only. 17 | require (msg.sender == owner); 18 | // here we just moved the require function to here instead of under the delete and getCreator functions. 19 | _; 20 | //this means continue the execution. 21 | } 22 | 23 | constructor () public{ 24 | owner = msg.sender; 25 | } 26 | 27 | mapping (address =>Person) private people; 28 | address [] private creators; 29 | 30 | function createPerson (string memory name, uint age, uint height) public{ 31 | require (age<150, "age must be below 150"); 32 | Person memory newPerson; 33 | newPerson.name = name; 34 | newPerson.age = age; 35 | newPerson.height = height; 36 | if(age >=65) { 37 | newPerson.senior = true; 38 | } 39 | else { 40 | newPerson.senior = false; 41 | } 42 | insertPerson (newPerson); 43 | creators.push (msg.sender); 44 | assert ( 45 | keccak256 ( 46 | abi.encodePacked ( 47 | people[msg.sender].name, 48 | people[msg.sender].age, 49 | people[msg.sender].height, 50 | people[msg.sender].senior 51 | ) 52 | ) 53 | == 54 | keccak256 ( 55 | abi.encodePacked ( 56 | newPerson.name, 57 | newPerson.age, 58 | newPerson.height, 59 | newPerson.senior 60 | ) 61 | ) 62 | ); 63 | 64 | emit personCreated (newPerson.name, newPerson.senior); 65 | 66 | } 67 | 68 | function insertPerson (Person memory newPerson) private{ 69 | address creator = msg.sender; 70 | people[creator] = newPerson; 71 | } 72 | 73 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 74 | address creator = msg.sender; 75 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 76 | } 77 | 78 | function deletePerson (address creator) public onlyOwner { 79 | string memory name = people[creator].name; 80 | bool senior = people[creator].senior; 81 | //here we tried to save the data locally first before getting deleted. 82 | // because this data will be used to reflect a personDeleted event. 83 | 84 | delete people[creator]; 85 | assert (people[creator].age == 0); 86 | emit personDeleted (name, senior, msg.sender); 87 | } 88 | 89 | function getCreator (uint index) public view onlyOwner returns (address){ 90 | return creators[index]; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /Part 16: Balance Modifier.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person { 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | 14 | modifier onlyOwner () { 15 | require (msg.sender == owner); 16 | _; 17 | } 18 | 19 | modifier costs (uint cost){ 20 | // instead of writing the uint cost as uint 1 ether, 21 | // the uint cost argument is written as such to help the modifier adapt to different costs 22 | // and not only to 1 ether as specified below. 23 | // In other words, the modifier can then be used for different functions. 24 | // This will be a dynamic modifier that will be used for multiple different functions. 25 | // It will make the code looks nicer and void confusion. 26 | // Therefore, whenever the argument cost is written at the end of the title of a function, 27 | // it will be triggered. 28 | 29 | // We can use this method on different functions and specify different costs, 30 | // while still using the same modifier. 31 | 32 | require (msg.value >= cost); 33 | _; 34 | } 35 | 36 | address public owner; 37 | uint public balance; 38 | 39 | constructor () public{ 40 | owner = msg.sender; 41 | } 42 | 43 | mapping (address => Person) private people; 44 | address [] private creators; 45 | 46 | 47 | function createPerson (string memory name, uint age, uint height) public payable costs (1 ether) { 48 | require (age < 150, "age must be less than 150"); 49 | balance += msg.value; 50 | 51 | Person memory newPerson; 52 | newPerson.name = name; 53 | newPerson.age = age; 54 | newPerson.height = height; 55 | if (age >=65){ 56 | newPerson.senior = true; 57 | } 58 | else { 59 | newPerson.senior = false; 60 | } 61 | insertPerson(newPerson); 62 | creators.push (msg.sender); 63 | assert ( 64 | keccak256 ( 65 | abi.encodePacked ( 66 | people[msg.sender].name, 67 | people[msg.sender].age, 68 | people[msg.sender].height, 69 | people[msg.sender].senior)) 70 | == 71 | keccak256 ( 72 | abi.encodePacked ( 73 | newPerson.name, 74 | newPerson.age, 75 | newPerson.height, 76 | newPerson.senior))); 77 | emit personCreated (newPerson.name, newPerson.senior); 78 | } 79 | 80 | function insertPerson (Person memory newPerson) private{ 81 | address creator = msg.sender; 82 | people[creator] = newPerson; 83 | } 84 | 85 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 86 | address creator = msg.sender; 87 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 88 | } 89 | 90 | function deletePerson (address creator) public onlyOwner { 91 | string memory name = people[creator].name; 92 | bool senior = people[creator].senior; 93 | delete people[creator]; 94 | assert (people[creator].age ==0); 95 | emit personDeleted (name, senior, msg.sender); 96 | 97 | } 98 | 99 | function getCreator (uint index) public view onlyOwner returns (address){ 100 | return creators[index]; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Inheritance/HelloWorld.sol: -------------------------------------------------------------------------------- 1 | import "./Ownable.sol"; 2 | import "./Destroyable.sol"; 3 | pragma solidity 0.6.6; 4 | contract HelloWorld is Ownable, Destroyable { 5 | struct Person{ 6 | string name; 7 | uint age; 8 | uint height; 9 | bool senior; 10 | } 11 | event personCreated (string name, bool senior); 12 | event personDeleted (string name, bool senior, address deletedBy); 13 | 14 | uint public balance; 15 | 16 | 17 | 18 | modifier costs (uint cost){ 19 | require (msg.value >= cost); 20 | _; 21 | } 22 | 23 | 24 | 25 | mapping (address =>Person) private people; 26 | address [] private creators; 27 | 28 | function createPerson (string memory name, uint age, uint height) public payable costs (1 ether) { 29 | require (age<150, "age must be below 150"); 30 | balance += msg.value; 31 | 32 | Person memory newPerson; 33 | newPerson.name = name; 34 | newPerson.age = age; 35 | newPerson.height = height; 36 | if(age >=65) { 37 | newPerson.senior = true; 38 | } 39 | else { 40 | newPerson.senior = false; 41 | } 42 | insertPerson (newPerson); 43 | creators.push (msg.sender); 44 | assert ( 45 | keccak256 ( 46 | abi.encodePacked ( 47 | people[msg.sender].name, 48 | people[msg.sender].age, 49 | people[msg.sender].height, 50 | people[msg.sender].senior 51 | ) 52 | ) 53 | == 54 | keccak256 ( 55 | abi.encodePacked ( 56 | newPerson.name, 57 | newPerson.age, 58 | newPerson.height, 59 | newPerson.senior 60 | ) 61 | ) 62 | ); 63 | 64 | emit personCreated (newPerson.name, newPerson.senior); 65 | 66 | } 67 | 68 | function insertPerson (Person memory newPerson) private{ 69 | address creator = msg.sender; 70 | people[creator] = newPerson; 71 | } 72 | 73 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 74 | address creator = msg.sender; 75 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 76 | } 77 | 78 | function deletePerson (address creator) public onlyOwner { 79 | string memory name = people[creator].name; 80 | bool senior = people[creator].senior; 81 | delete people[creator]; 82 | assert (people[creator].age == 0); 83 | emit personDeleted (name, senior, msg.sender); 84 | 85 | } 86 | 87 | function getCreator (uint index) public view onlyOwner returns (address){ 88 | return creators[index]; 89 | } 90 | 91 | function withdrawAll () public onlyOwner returns (uint){ 92 | uint toTransfer = balance; 93 | balance = 0; 94 | if (msg.sender.send (toTransfer)){ // if this is succss 95 | return toTransfer; // the owner will receive the money inside the wallet 96 | } 97 | else { // if this is failure 98 | balance = toTransfer; // no changes will happen to the money inside the wallet 99 | return 0; // the owner will receive zero; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /Part 17: Transfer.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract HelloWorld { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | uint public balance; 14 | address public owner; 15 | 16 | modifier onlyOwner (){ 17 | require (msg.sender == owner); 18 | _; 19 | } 20 | 21 | modifier costs (uint cost){ 22 | require (msg.value >= cost); 23 | _; 24 | } 25 | 26 | constructor () public{ 27 | owner = msg.sender; 28 | } 29 | 30 | mapping (address =>Person) private people; 31 | address [] private creators; 32 | 33 | function createPerson (string memory name, uint age, uint height) public payable costs (1 ether) { 34 | require (age<150, "age must be below 150"); 35 | balance += msg.value; 36 | 37 | Person memory newPerson; 38 | newPerson.name = name; 39 | newPerson.age = age; 40 | newPerson.height = height; 41 | if(age >=65) { 42 | newPerson.senior = true; 43 | } 44 | else { 45 | newPerson.senior = false; 46 | } 47 | insertPerson (newPerson); 48 | creators.push (msg.sender); 49 | assert ( 50 | keccak256 ( 51 | abi.encodePacked ( 52 | people[msg.sender].name, 53 | people[msg.sender].age, 54 | people[msg.sender].height, 55 | people[msg.sender].senior 56 | ) 57 | ) 58 | == 59 | keccak256 ( 60 | abi.encodePacked ( 61 | newPerson.name, 62 | newPerson.age, 63 | newPerson.height, 64 | newPerson.senior 65 | ) 66 | ) 67 | ); 68 | 69 | emit personCreated (newPerson.name, newPerson.senior); 70 | 71 | } 72 | 73 | function insertPerson (Person memory newPerson) private{ 74 | address creator = msg.sender; 75 | people[creator] = newPerson; 76 | } 77 | 78 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 79 | address creator = msg.sender; 80 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 81 | } 82 | 83 | function deletePerson (address creator) public onlyOwner { 84 | string memory name = people[creator].name; 85 | bool senior = people[creator].senior; 86 | delete people[creator]; 87 | assert (people[creator].age == 0); 88 | emit personDeleted (name, senior, msg.sender); 89 | 90 | } 91 | 92 | function getCreator (uint index) public view onlyOwner returns (address){ 93 | return creators[index]; 94 | } 95 | 96 | function withdrawAll () public onlyOwner returns (uint) { 97 | uint toTransfer = balance; // This is the balance that exists in the wallet 98 | balance =0; // this is the balance after withdrawing all 99 | msg.sender.transfer (toTransfer); 100 | return toTransfer; // return the updated new balance after withdrawal. The balance that exists in the wallet. 101 | 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Part 18: Send.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract HelloWorld { 3 | struct Person{ 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | uint public balance; 14 | address public owner; 15 | 16 | modifier onlyOwner (){ 17 | require (msg.sender == owner); 18 | _; 19 | } 20 | 21 | modifier costs (uint cost){ 22 | require (msg.value >= cost); 23 | _; 24 | } 25 | 26 | constructor () public{ 27 | owner = msg.sender; 28 | } 29 | 30 | mapping (address =>Person) private people; 31 | address [] private creators; 32 | 33 | function createPerson (string memory name, uint age, uint height) public payable costs (1 ether) { 34 | require (age<150, "age must be below 150"); 35 | balance += msg.value; 36 | 37 | Person memory newPerson; 38 | newPerson.name = name; 39 | newPerson.age = age; 40 | newPerson.height = height; 41 | if(age >=65) { 42 | newPerson.senior = true; 43 | } 44 | else { 45 | newPerson.senior = false; 46 | } 47 | insertPerson (newPerson); 48 | creators.push (msg.sender); 49 | assert ( 50 | keccak256 ( 51 | abi.encodePacked ( 52 | people[msg.sender].name, 53 | people[msg.sender].age, 54 | people[msg.sender].height, 55 | people[msg.sender].senior 56 | ) 57 | ) 58 | == 59 | keccak256 ( 60 | abi.encodePacked ( 61 | newPerson.name, 62 | newPerson.age, 63 | newPerson.height, 64 | newPerson.senior 65 | ) 66 | ) 67 | ); 68 | 69 | emit personCreated (newPerson.name, newPerson.senior); 70 | 71 | } 72 | 73 | function insertPerson (Person memory newPerson) private{ 74 | address creator = msg.sender; 75 | people[creator] = newPerson; 76 | } 77 | 78 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 79 | address creator = msg.sender; 80 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 81 | } 82 | 83 | function deletePerson (address creator) public onlyOwner { 84 | string memory name = people[creator].name; 85 | bool senior = people[creator].senior; 86 | delete people[creator]; 87 | assert (people[creator].age == 0); 88 | emit personDeleted (name, senior, msg.sender); 89 | 90 | } 91 | 92 | function getCreator (uint index) public view onlyOwner returns (address){ 93 | return creators[index]; 94 | } 95 | 96 | function withdrawAll () public onlyOwner returns (uint){ 97 | uint toTransfer = balance; // This is the balance inside the wallet. 98 | balance = 0; // this is the balance displayed after withdrawing the money. 99 | if (msg.sender.send (toTransfer)){ 100 | return toTransfer; // the owner receives the balance inside the wallet. 101 | } 102 | else { 103 | balance = toTransfer; // the balance displayed is the balance inside the wallet with no changes. 104 | return 0; // the owner receives nothing (zero) 105 | } 106 | 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /Aeromexico - Updated.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | 3 | contract Aeromexico { 4 | uint public certificate_counter; 5 | 6 | // Structs 7 | struct Certificate { 8 | string ipfsHash; 9 | uint timeOfIssue; 10 | address issuer; 11 | address recipient; 12 | } 13 | 14 | // Mappings 15 | mapping(string => address) issuerOfCertificate; 16 | mapping(address => string) issuer; 17 | mapping(address => string) recipient; 18 | mapping(string => address[]) allRecipientOfCertificate; 19 | mapping(uint => Certificate) certificateIdentifier; 20 | mapping(address => uint[]) recipientCertificates; 21 | mapping(address => uint[]) issuerCertificates; 22 | mapping(address => bool) isIssuer; 23 | mapping(address => bool) isRecipient; 24 | 25 | // Events 26 | event IssuerRegistered(address indexed issuer, string IPFS_hash); 27 | event RecipientRegistered(address indexed recipient, string IPFS_hash); 28 | event CertificateRegistered(address indexed issuer, string IPFS_hash); 29 | event CertificateIssued(uint indexed certificate, address indexed issuer, address indexed recipient); 30 | 31 | // Functions 32 | function registerIssuer(string memory IPFS_hash) public { 33 | require((isIssuer[msg.sender] == false), "Issuer already registered"); 34 | issuer[msg.sender] = IPFS_hash; 35 | isIssuer[msg.sender] = true; 36 | emit IssuerRegistered(msg.sender, IPFS_hash); 37 | } 38 | 39 | function registerRecipient(string memory IPFS_hash) public { 40 | require(isRecipient[msg.sender] == false, "Recipient already registered"); 41 | recipient[msg.sender] = IPFS_hash; 42 | isRecipient[msg.sender] = true; 43 | emit RecipientRegistered(msg.sender, IPFS_hash); 44 | } 45 | 46 | function registerCertificate(string memory IPFS_hash) public { 47 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 48 | issuerOfCertificate[IPFS_hash] = msg.sender; 49 | emit CertificateRegistered(msg.sender, IPFS_hash); 50 | } 51 | 52 | function issueCertificate(address _recipient, string memory certificate_hash) public { 53 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 54 | require(isRecipient[_recipient] == true, "Recipient not registered to be issued a certificate"); 55 | require(issuerOfCertificate[certificate_hash] == msg.sender, "Issuer not registered to issue this certificate"); 56 | Certificate memory cert; 57 | uint id = ++certificate_counter; 58 | cert.ipfsHash = certificate_hash; 59 | cert.timeOfIssue = now; 60 | cert.issuer = msg.sender; 61 | cert.recipient = _recipient; 62 | certificateIdentifier[id] = cert; 63 | recipientCertificates[_recipient].push(id); 64 | issuerCertificates[msg.sender].push(id); 65 | allRecipientOfCertificate[certificate_hash].push(_recipient); 66 | emit CertificateIssued(id, msg.sender, _recipient); 67 | } 68 | 69 | function getIssuerOfCertificate(string memory IPFS_hash) public view returns (address) { 70 | return issuerOfCertificate[IPFS_hash]; 71 | } 72 | 73 | function getIssuer(address _issuer) public view returns (string memory) { 74 | return issuer[_issuer]; 75 | } 76 | 77 | function getRecipient(address _recipient) public view returns (string memory ) { 78 | return recipient[_recipient]; 79 | } 80 | 81 | function getRecipientCertificates(address _recipient) public view returns (uint256[] memory) { 82 | return recipientCertificates[_recipient]; 83 | } 84 | 85 | function getIssuerCertificates(address _issuer) public view returns (uint256[] memory) { 86 | return issuerCertificates[_issuer]; 87 | } 88 | 89 | function getCertificateIdentifier(uint _id) public view returns (string memory, uint, address, address){ 90 | Certificate memory cert = certificateIdentifier[_id]; 91 | return (cert.ipfsHash, cert.timeOfIssue, cert.issuer, cert.recipient); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /Aeromexico.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.23; 2 | 3 | contract Aeromexico { 4 | uint public certificate_counter; 5 | 6 | // Structs 7 | struct Certificate { 8 | string ipfsHash; 9 | uint timeOfIssue; 10 | address issuer; 11 | address recipient; 12 | } 13 | 14 | // Mappings 15 | mapping(string => address) issuerOfCertificate; 16 | mapping(address => string) issuer; 17 | mapping(address => string) recipient; 18 | mapping(string => address[]) allRecipientOfCertificate; 19 | mapping(uint => Certificate) certificateIdentifier; 20 | mapping(address => uint[]) recipientCertificates; 21 | mapping(address => uint[]) issuerCertificates; 22 | mapping(address => bool) isIssuer; 23 | mapping(address => bool) isRecipient; 24 | 25 | // Events 26 | event IssuerRegistered(address indexed issuer, string IPFS_hash); 27 | event RecipientRegistered(address indexed recipient, string IPFS_hash); 28 | event CertificateRegistered(address indexed issuer, string IPFS_hash); 29 | event CertificateIssued(uint indexed certificate, address indexed issuer, address indexed recipient); 30 | 31 | // Functions 32 | function registerIssuer(string IPFS_hash) public { 33 | require((isIssuer[msg.sender] == false), "Issuer already registered"); 34 | issuer[msg.sender] = IPFS_hash; 35 | isIssuer[msg.sender] = true; 36 | emit IssuerRegistered(msg.sender, IPFS_hash); 37 | } 38 | 39 | function registerRecipient(string IPFS_hash) public { 40 | require(isRecipient[msg.sender] == false, "Recipient already registered"); 41 | recipient[msg.sender] = IPFS_hash; 42 | isRecipient[msg.sender] = true; 43 | emit RecipientRegistered(msg.sender, IPFS_hash); 44 | } 45 | 46 | function registerCertificate(string IPFS_hash) public { 47 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 48 | issuerOfCertificate[IPFS_hash] = msg.sender; 49 | emit CertificateRegistered(msg.sender, IPFS_hash); 50 | } 51 | 52 | function issueCertificate(address _recipient, string certificate_hash) public { 53 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 54 | require(isRecipient[_recipient] == true, "Recipient not registered to be issued a certificate"); 55 | require(issuerOfCertificate[certificate_hash] == msg.sender, "Issuer not registered to issue this certificate"); 56 | Certificate memory cert; 57 | uint id = ++certificate_counter; 58 | cert.ipfsHash = certificate_hash; 59 | cert.timeOfIssue = now; 60 | cert.issuer = msg.sender; 61 | cert.recipient = _recipient; 62 | certificateIdentifier[id] = cert; 63 | recipientCertificates[_recipient].push(id); 64 | issuerCertificates[msg.sender].push(id); 65 | allRecipientOfCertificate[certificate_hash].push(_recipient); 66 | emit CertificateIssued(id, msg.sender, _recipient); 67 | } 68 | 69 | function getIssuerOfCertificate(string IPFS_hash) public view returns (address) { 70 | return issuerOfCertificate[IPFS_hash]; 71 | } 72 | 73 | function getIssuer(address _issuer) public view returns (string) { 74 | return issuer[_issuer]; 75 | } 76 | 77 | function getRecipient(address _recipient) public view returns (string) { 78 | return recipient[_recipient]; 79 | } 80 | 81 | function getAllRecipientOfCertificate(string IPFS_hash) public view returns (address[]) { 82 | return allRecipientOfCertificate[IPFS_hash]; 83 | } 84 | 85 | function getRecipientCertificates(address _recipient) public view returns (uint[]) { 86 | return recipientCertificates[_recipient]; 87 | } 88 | 89 | function getIssuerCertificates(address _issuer) public view returns (uint[]) { 90 | return issuerCertificates[_issuer]; 91 | } 92 | 93 | function getCertificateIdentifier(uint _id) public view returns (string, uint, address, address){ 94 | Certificate memory cert = certificateIdentifier[_id]; 95 | return (cert.ipfsHash, cert.timeOfIssue, cert.issuer, cert.recipient); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /CertificateOfOrigin.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.23; 2 | 3 | contract CertificateOfOrigin { 4 | uint public certificate_counter; 5 | 6 | // Structs 7 | struct Certificate { 8 | string ipfsHash; 9 | uint timeOfIssue; 10 | address issuer; 11 | address recipient; 12 | } 13 | 14 | // Mappings 15 | mapping(string => address) issuerOfCertificate; 16 | mapping(address => string) issuer; 17 | mapping(address => string) recipient; 18 | mapping(string => address[]) allRecipientOfCertificate; 19 | mapping(uint => Certificate) certificateIdentifier; 20 | mapping(address => uint[]) recipientCertificates; 21 | mapping(address => uint[]) issuerCertificates; 22 | mapping(address => bool) isIssuer; 23 | mapping(address => bool) isRecipient; 24 | 25 | // Events 26 | event IssuerRegistered(address indexed issuer, string IPFS_hash); 27 | event RecipientRegistered(address indexed recipient, string IPFS_hash); 28 | event CertificateRegistered(address indexed issuer, string IPFS_hash); 29 | event CertificateIssued(uint indexed certificate, address indexed issuer, address indexed recipient); 30 | 31 | // Functions 32 | function registerIssuer(string IPFS_hash) public { 33 | require((isIssuer[msg.sender] == false), "Issuer already registered"); 34 | issuer[msg.sender] = IPFS_hash; 35 | isIssuer[msg.sender] = true; 36 | emit IssuerRegistered(msg.sender, IPFS_hash); 37 | } 38 | 39 | function registerRecipient(string IPFS_hash) public { 40 | require(isRecipient[msg.sender] == false, "Recipient already registered"); 41 | recipient[msg.sender] = IPFS_hash; 42 | isRecipient[msg.sender] = true; 43 | emit RecipientRegistered(msg.sender, IPFS_hash); 44 | } 45 | 46 | function registerCertificate(string IPFS_hash) public { 47 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 48 | issuerOfCertificate[IPFS_hash] = msg.sender; 49 | emit CertificateRegistered(msg.sender, IPFS_hash); 50 | } 51 | 52 | function issueCertificate(address _recipient, string certificate_hash) public { 53 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 54 | require(isRecipient[_recipient] == true, "Recipient not registered to be issued a certificate"); 55 | require(issuerOfCertificate[certificate_hash] == msg.sender, "Issuer not registered to issue this certificate"); 56 | Certificate memory cert; 57 | uint id = ++certificate_counter; 58 | cert.ipfsHash = certificate_hash; 59 | cert.timeOfIssue = now; 60 | cert.issuer = msg.sender; 61 | cert.recipient = _recipient; 62 | certificateIdentifier[id] = cert; 63 | recipientCertificates[_recipient].push(id); 64 | issuerCertificates[msg.sender].push(id); 65 | allRecipientOfCertificate[certificate_hash].push(_recipient); 66 | emit CertificateIssued(id, msg.sender, _recipient); 67 | } 68 | 69 | function getIssuerOfCertificate(string IPFS_hash) public view returns (address) { 70 | return issuerOfCertificate[IPFS_hash]; 71 | } 72 | 73 | function getIssuer(address _issuer) public view returns (string) { 74 | return issuer[_issuer]; 75 | } 76 | 77 | function getRecipient(address _recipient) public view returns (string) { 78 | return recipient[_recipient]; 79 | } 80 | 81 | function getAllRecipientOfCertificate(string IPFS_hash) public view returns (address[]) { 82 | return allRecipientOfCertificate[IPFS_hash]; 83 | } 84 | 85 | function getRecipientCertificates(address _recipient) public view returns (uint[]) { 86 | return recipientCertificates[_recipient]; 87 | } 88 | 89 | function getIssuerCertificates(address _issuer) public view returns (uint[]) { 90 | return issuerCertificates[_issuer]; 91 | } 92 | 93 | function getCertificateIdentifier(uint _id) public view returns (string, uint, address, address){ 94 | Certificate memory cert = certificateIdentifier[_id]; 95 | return (cert.ipfsHash, cert.timeOfIssue, cert.issuer, cert.recipient); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Smart Certification.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.4.23; 2 | 3 | contract AmericanInstituteOfMonterrey { 4 | uint public certificate_counter; 5 | 6 | // Structs 7 | struct Certificate { 8 | string ipfsHash; 9 | uint timeOfIssue; 10 | address issuer; 11 | address recipient; 12 | } 13 | 14 | // Mappings 15 | mapping(string => address) issuerOfCertificate; 16 | mapping(address => string) issuer; 17 | mapping(address => string) recipient; 18 | mapping(string => address[]) allRecipientOfCertificate; 19 | mapping(uint => Certificate) certificateIdentifier; 20 | mapping(address => uint[]) recipientCertificates; 21 | mapping(address => uint[]) issuerCertificates; 22 | mapping(address => bool) isIssuer; 23 | mapping(address => bool) isRecipient; 24 | 25 | // Events 26 | event IssuerRegistered(address indexed issuer, string IPFS_hash); 27 | event RecipientRegistered(address indexed recipient, string IPFS_hash); 28 | event CertificateRegistered(address indexed issuer, string IPFS_hash); 29 | event CertificateIssued(uint indexed certificate, address indexed issuer, address indexed recipient); 30 | 31 | // Functions 32 | function registerIssuer(string IPFS_hash) public { 33 | require((isIssuer[msg.sender] == false), "Issuer already registered"); 34 | issuer[msg.sender] = IPFS_hash; 35 | isIssuer[msg.sender] = true; 36 | emit IssuerRegistered(msg.sender, IPFS_hash); 37 | } 38 | 39 | function registerRecipient(string IPFS_hash) public { 40 | require(isRecipient[msg.sender] == false, "Recipient already registered"); 41 | recipient[msg.sender] = IPFS_hash; 42 | isRecipient[msg.sender] = true; 43 | emit RecipientRegistered(msg.sender, IPFS_hash); 44 | } 45 | 46 | function registerCertificate(string IPFS_hash) public { 47 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 48 | issuerOfCertificate[IPFS_hash] = msg.sender; 49 | emit CertificateRegistered(msg.sender, IPFS_hash); 50 | } 51 | 52 | function issueCertificate(address _recipient, string certificate_hash) public { 53 | require(isIssuer[msg.sender] == true, "Issuer not registered to register a certificate"); 54 | require(isRecipient[_recipient] == true, "Recipient not registered to be issued a certificate"); 55 | require(issuerOfCertificate[certificate_hash] == msg.sender, "Issuer not registered to issue this certificate"); 56 | Certificate memory cert; 57 | uint id = ++certificate_counter; 58 | cert.ipfsHash = certificate_hash; 59 | cert.timeOfIssue = now; 60 | cert.issuer = msg.sender; 61 | cert.recipient = _recipient; 62 | certificateIdentifier[id] = cert; 63 | recipientCertificates[_recipient].push(id); 64 | issuerCertificates[msg.sender].push(id); 65 | allRecipientOfCertificate[certificate_hash].push(_recipient); 66 | emit CertificateIssued(id, msg.sender, _recipient); 67 | } 68 | 69 | function getIssuerOfCertificate(string IPFS_hash) public view returns (address) { 70 | return issuerOfCertificate[IPFS_hash]; 71 | } 72 | 73 | function getIssuer(address _issuer) public view returns (string) { 74 | return issuer[_issuer]; 75 | } 76 | 77 | function getRecipient(address _recipient) public view returns (string) { 78 | return recipient[_recipient]; 79 | } 80 | 81 | function getAllRecipientOfCertificate(string IPFS_hash) public view returns (address[]) { 82 | return allRecipientOfCertificate[IPFS_hash]; 83 | } 84 | 85 | function getRecipientCertificates(address _recipient) public view returns (uint[]) { 86 | return recipientCertificates[_recipient]; 87 | } 88 | 89 | function getIssuerCertificates(address _issuer) public view returns (uint[]) { 90 | return issuerCertificates[_issuer]; 91 | } 92 | 93 | function getCertificateIdentifier(uint _id) public view returns (string, uint, address, address){ 94 | Certificate memory cert = certificateIdentifier[_id]; 95 | return (cert.ipfsHash, cert.timeOfIssue, cert.issuer, cert.recipient); 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Part 19: Payable vs. Normal Address.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person { 4 | string name; 5 | uint age; 6 | uint height; 7 | bool senior; 8 | } 9 | 10 | event personCreated (string name, bool senior); 11 | event personDeleted (string name, bool senior, address deletedBy); 12 | 13 | 14 | modifier costs (uint cost){ 15 | require (msg.value >= cost); 16 | _; 17 | } 18 | 19 | modifier onlyOwner () { 20 | require (msg.sender == owner); 21 | _; 22 | } 23 | 24 | address public owner; 25 | uint public balance; 26 | 27 | constructor () public{ 28 | owner = msg.sender; 29 | } 30 | 31 | mapping (address => Person) private people; 32 | address [] private creators; 33 | 34 | 35 | function createPerson (string memory name, uint age, uint height) public payable costs(1 ether) { 36 | require (age < 150, "age must be less than 150"); 37 | balance+= msg.value; 38 | 39 | Person memory newPerson; 40 | newPerson.name = name; 41 | newPerson.age = age; 42 | newPerson.height = height; 43 | if (age >=65){ 44 | newPerson.senior = true; 45 | } 46 | else { 47 | newPerson.senior = false; 48 | } 49 | insertPerson(newPerson); 50 | creators.push (msg.sender); 51 | assert ( 52 | keccak256 ( 53 | abi.encodePacked ( 54 | people[msg.sender].name, 55 | people[msg.sender].age, 56 | people[msg.sender].height, 57 | people[msg.sender].senior)) 58 | == 59 | keccak256 ( 60 | abi.encodePacked ( 61 | newPerson.name, 62 | newPerson.age, 63 | newPerson.height, 64 | newPerson.senior))); 65 | emit personCreated (newPerson.name, newPerson.senior); 66 | } 67 | 68 | function insertPerson (Person memory newPerson) private{ 69 | address creator = msg.sender; 70 | // There is a difference between address and address payable. 71 | // address creator is a normal address. 72 | // msg.sender is an address of the person connecting with the contract by default in solidity. 73 | // In here, we assigned it the variable creator. so if we use creator.send() instead of 74 | // msg.sender.send(), we will get a compilation error because address creator is not a payable address. 75 | // And msg.sender has the capacity to become a payable by default. 76 | 77 | // A payable address is the one that sends and transfers. 78 | //The reason solidity has this is to force the actual developer of the contract to rethink about which address shall 79 | // send, receive or handle money to limit the amount of errors we do. 80 | // If you want the creator address to send, then it is very easy 81 | // because msg.sender can become a payable address. All you need is to add payable after address, like this for example: 82 | 83 | // address payable creator = msg.sender; 84 | // creator.send(10 ether); 85 | 86 | // The hardest part is if you want a non-payable address to become a payable address, like this: 87 | // address payable test = creator; 88 | // This is a case where we walk from a non-payable address (creator) to a payable address (test). 89 | // The only way to make this possible is to cast the creator into a uint160(creator) and then you cast all 90 | // that to an address, like this; 91 | // address payable test = address (uint160(creator)); 92 | 93 | // And that was how you go from a normal address to a payable address. 94 | 95 | people[creator] = newPerson; 96 | } 97 | 98 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 99 | address creator = msg.sender; 100 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 101 | } 102 | 103 | function deletePerson (address creator) public onlyOwner { 104 | string memory name = people[creator].name; 105 | bool senior = people[creator].senior; 106 | delete people[creator]; 107 | assert (people[creator].age ==0); 108 | emit personDeleted (name, senior, msg.sender); 109 | 110 | } 111 | 112 | function getCreator (uint index) public view onlyOwner returns (address){ 113 | return creators[index]; 114 | } 115 | 116 | function withdrawAll () public onlyOwner returns (uint) { 117 | uint toTransfer = balance; 118 | balance = 0; 119 | msg.sender.transfer (toTransfer); 120 | return toTransfer; 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /Part 11: Data Location.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | 4 | //data location is where we tell solidity to save the data. 5 | 6 | // There are three different data locations: 7 | 8 | //storage: everything that is saved permanently, like state and some local variables: 9 | // mapping, structs, and arrays. 10 | //In our HelloWorld contract, the owner variable and the mapping data people[creator] are examples. 11 | // They will all be in storage and live as long as the contract remains. 12 | 13 | //memory: It is saved only during a function execution, like the function input "string memory name". 14 | //this means the name will be kept and saved throughout the function execution, 15 | //until we reach the buttom of this function and its execution, then 16 | //the name as a parameter and argument for this function will be lost. 17 | //That's why we initialize the newPerson variable locally 18 | //under the function. Then, we set all its properties, 19 | //Then, we insert it into the mapping through insertPerson(newPerson) and people[creator] = newPerson 20 | //because the mapping is by default in storage. 21 | //And that last step is the part when we save a copy of newPerson of the struct Person into the mapping. 22 | //so we do save the name, but we save it into our mapping. 23 | 24 | //stack: The stack memory usually sorts out itself. It is the least important of the three. 25 | //it is meant to hold local variables of value types, like uint, bool and variables that 26 | //are lower than 256 bits in size. The variables gets deleted here as well when the function is executed. 27 | //when it comes to the function arguments, 28 | //they are always defauled to memory and you don't need to specify the data locations for them. 29 | // unlike strings, where you need to specify their data locations. 30 | //This explains why we don't type memory when we set them within the function. 31 | 32 | 33 | struct Person{ 34 | string name; 35 | uint age; 36 | uint height; 37 | bool senior; 38 | } 39 | 40 | modifier onlyOwner () { 41 | require (msg.sender == owner); 42 | _; 43 | } 44 | 45 | address public owner; 46 | 47 | constructor () public{ 48 | owner = msg.sender; 49 | } 50 | 51 | mapping (address => Person) private people; 52 | address [] private creators; 53 | 54 | function createPerson (string memory name, uint age, uint height) public{ 55 | // 56 | require (age < 150, 'age must be less than 150'); 57 | Person memory newPerson; 58 | // this means the instance of the struct Person will be deleted after the function execution. 59 | newPerson.name = name; 60 | newPerson.age = age; 61 | newPerson.height = height; 62 | if(age >= 65){ 63 | newPerson.senior = true; 64 | } 65 | else { 66 | newPerson.senior = false; 67 | } 68 | 69 | insertPerson(newPerson); 70 | creators.push (msg.sender); 71 | 72 | assert ( 73 | keccak256 ( 74 | abi.encodePacked ( 75 | people[msg.sender].name, 76 | people[msg.sender].age, 77 | people[msg.sender].height, 78 | people[msg.sender].senior)) 79 | == 80 | keccak256 ( 81 | abi.encodePacked ( 82 | newPerson.name, 83 | newPerson.age, 84 | newPerson.height, 85 | newPerson.senior))); 86 | 87 | } 88 | 89 | function insertPerson (Person memory newPerson) private{ 90 | address creator = msg.sender; 91 | people[creator] = newPerson; 92 | } 93 | 94 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior){ 95 | address creator = msg.sender; 96 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 97 | } 98 | 99 | function deletePerson (address creator) public onlyOwner { 100 | delete people[creator]; 101 | assert (people[creator].age == 0); 102 | } 103 | 104 | function getCreator (uint index) public view onlyOwner returns (address){ 105 | return creators[index]; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /Part 8: Require and Assert with Notes.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.6; 2 | contract Identity{ 3 | struct Person{ 4 | 5 | string name; 6 | uint age; 7 | uint height; 8 | bool senior; 9 | } 10 | 11 | address public owner; 12 | //to save the owner of the address in a variable that will be used later. 13 | 14 | constructor () public { 15 | owner = msg.sender; 16 | } 17 | //time is important here: 18 | //you want the owner to be set automatically at the time of the contract creation 19 | //and not to be modified later by anyone. 20 | 21 | //to the owner variable, we will assign the owner = msg.sender in the constructor 22 | //because we want the message sender to be the owner (the one who initiated the contract creation). 23 | 24 | //Thus, this will allow us to set the owner automatically and once at the time of the contract creation 25 | //by adding the owner to the constructor. 26 | 27 | 28 | mapping (address=>Person) private people; 29 | address [] private creators; 30 | //we need an address array called "creators" to check the addresses of the owners. 31 | // we are going to keep it private to be accessed by the owner; 32 | // now we need to create a getter fuction for it that will be public, but accessed only by the owner. 33 | 34 | function createPerson (string memory name, uint age, uint height) public{ 35 | 36 | require (age<150, "age must be below 150"); 37 | Person memory newPerson; 38 | newPerson.name = name; 39 | newPerson.age = age; 40 | newPerson.height = height; 41 | if (age >=65){ 42 | newPerson.senior = true; 43 | } 44 | else{ 45 | newPerson.senior = false; 46 | } 47 | insertPerson(newPerson); 48 | //this adds the Person above that gets created to the mapping. How? 49 | //by exceuting the following function"insertPerson". 50 | 51 | creators.push (msg.sender); 52 | //this is to add addresses of the creators (message senders or the people interracting with the contract) 53 | //to the array when the they create a Person. 54 | //In other words, this will add an entry into the array with the person that added Person. 55 | //P.S. msg.sender is defined under the next insertPerson function. 56 | 57 | assert ( 58 | keccak256 ( 59 | abi.encodePacked ( 60 | people[msg.sender].name, 61 | people[msg.sender].age, 62 | people[msg.sender].height, 63 | people[msg.sender].senior 64 | ) 65 | ) 66 | == 67 | keccak256 ( 68 | abi.encodePacked ( 69 | newPerson.name, 70 | newPerson.age, 71 | newPerson.height, 72 | newPerson.senior 73 | ) 74 | ) 75 | ); 76 | // All of that is to assert that people[msg.sender] == newPerson. 77 | //Remember, newPerson when it gets created, it is associated with an address. 78 | //that you later on get with the "getCreator function". 79 | 80 | //"assert" makes sure that the addresses of the creators (message senders) within the mapping "people" 81 | //are equal to the Person data (newPerson) that gets created by them. 82 | 83 | //In other words, the hashing of the message senders addresses 84 | //should be equal to the hashing of the Person data they input. 85 | 86 | // You want to make sure that msg.sender = newPerson. Look at the next function for reference. 87 | } 88 | 89 | function insertPerson (Person memory newPerson) private { 90 | address creator = msg.sender; 91 | //The address creator is the one who inputs the information. 92 | 93 | people [creator] = newPerson; 94 | //The creator key within the people mapping gives us the value of new added Person. 95 | } 96 | 97 | function getPerson () public view returns (string memory name, uint age, uint height, bool senior) { 98 | address creator = msg.sender; 99 | return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior); 100 | } 101 | 102 | function deletePerson (address creator) public{ 103 | // here we are trying to explain that we will delete a person by using the address of the creator. 104 | 105 | require (msg.sender == owner); 106 | //here we are trying to limit the delete function to the owner of the contract 107 | //who used also the address of the creator. 108 | 109 | // as far as I understand the owner is the creator, but it the "require" error handling 110 | //restricts our use to the term "owner", so we need to use the term "owner" for the "require" functionality. 111 | 112 | delete people [creator]; 113 | //This is the how part: 114 | //this will delete the value from the mapping (people [creator]). 115 | 116 | assert(people[creator].age == 0); 117 | // all Person requirement, including age, shall be left as 0 after deleting. 118 | //In here we are asserting that the age requirement will be left as 0 after deleting Person. 119 | } 120 | 121 | function getCreator (uint index) public view returns (address) { 122 | require (msg.sender == owner, "caller must be owner"); 123 | return creators [index]; 124 | 125 | } 126 | 127 | } 128 | --------------------------------------------------------------------------------