From 11114eb08d518c23a689b04ed20d0175e1fc50e5 Mon Sep 17 00:00:00 2001 From: Xinwen Wang Date: Wed, 14 Mar 2018 20:45:25 -0400 Subject: [PATCH 1/6] upload lesson 2 --- Lesson-2/README.md | 16 +++++++++++ Lesson-2/assignment/README.md | 10 +++++++ Lesson-2/assignment/yours.sol | 1 + Lesson-2/orgin/README.md | 3 +++ Lesson-2/orgin/payroll.sol | 50 +++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+) create mode 100644 Lesson-2/README.md create mode 100644 Lesson-2/assignment/README.md create mode 100644 Lesson-2/assignment/yours.sol create mode 100644 Lesson-2/orgin/README.md create mode 100644 Lesson-2/orgin/payroll.sol diff --git a/Lesson-2/README.md b/Lesson-2/README.md new file mode 100644 index 00000000..1fdc5b30 --- /dev/null +++ b/Lesson-2/README.md @@ -0,0 +1,16 @@ +## 硅谷live以太坊智能合约频道官方地址 + +### 第二课《智能合约设计进阶-多员工薪酬系统》 + +目录结构 +
| +
|--orgin 课程初始代码 +
| +
|--assignment 课程作业提交代码 +
+### 本节知识点 +第2课:智能合约设计进阶-多员工薪酬系统 +- 动态静态数组的不同 +- 函数输入参数检查 revert +- 循环与遍历的安全性 +- 程序运行错误检查和容错:assert与require diff --git a/Lesson-2/assignment/README.md b/Lesson-2/assignment/README.md new file mode 100644 index 00000000..a1fa2d04 --- /dev/null +++ b/Lesson-2/assignment/README.md @@ -0,0 +1,10 @@ +## 硅谷live以太坊智能合约 第二课作业 +这里是同学提交作业的目录 + +### 第二课:课后作业 +完成今天的智能合约添加100ETH到合约中 +- 加入十个员工,每个员工的薪水都是1ETH +每次加入一个员工后调用calculateRunway这个函数,并且记录消耗的gas是多少?Gas变化么?如果有 为什么? +- 如何优化calculateRunway这个函数来减少gas的消耗? +提交:智能合约代码,gas变化的记录,calculateRunway函数的优化 + diff --git a/Lesson-2/assignment/yours.sol b/Lesson-2/assignment/yours.sol new file mode 100644 index 00000000..dfdb2c48 --- /dev/null +++ b/Lesson-2/assignment/yours.sol @@ -0,0 +1 @@ +/*作业请提交在这个目录下*/ diff --git a/Lesson-2/orgin/README.md b/Lesson-2/orgin/README.md new file mode 100644 index 00000000..0309d947 --- /dev/null +++ b/Lesson-2/orgin/README.md @@ -0,0 +1,3 @@ +## 硅谷live以太坊智能合约 第二课《智能合约设计进阶-多员工薪酬系统》 + +这里是每一课的初始代码,有需要的同学可以参考 diff --git a/Lesson-2/orgin/payroll.sol b/Lesson-2/orgin/payroll.sol new file mode 100644 index 00000000..62e380e4 --- /dev/null +++ b/Lesson-2/orgin/payroll.sol @@ -0,0 +1,50 @@ +pragma solidity ^0.4.14; + +contract Payroll { + struct Employee { + address id; + uint salary; + uint lastPayday; + } + + uint constant payDuration = 10 seconds; + + address owner; + Employee[] employees; + + function Payroll() { + owner = msg.sender; + } + + function _partialPaid(Employee employee) private { + } + + function _findEmployee(address employeeId) private returns (Employee, uint) { + } + + function addEmployee(address employeeId, uint salary) { + } + + function removeEmployee(address employeeId) { + } + + function updateEmployee(address employeeId, uint salary) { + } + + function addFund() payable returns (uint) { + } + + function calculateRunway() returns (uint) { + uint totalSalary = 0; + for (uint i = 0; i < employees.length; i++) { + totalSalary += employees[i].salary; + } + return this.balance / totalSalary; + } + + function hasEnoughFund() returns (bool) { + } + + function getPaid() { + } +} From d9e38af9564076332be67cc15df4f22b07252128 Mon Sep 17 00:00:00 2001 From: Xinwen Wang Date: Sun, 18 Mar 2018 10:51:50 -0400 Subject: [PATCH 2/6] Upload lesson 3 --- Lesson-Team-A/README.md | 16 ++++++++++++++++ Lesson-Team-A/assignment/README.md | 14 ++++++++++++++ Lesson-Team-A/assignment/yours.sol | 1 + Lesson-Team-A/orgin/README.md | 3 +++ Lesson-Team-A/orgin/payroll.sol | 0 5 files changed, 34 insertions(+) create mode 100644 Lesson-Team-A/README.md create mode 100644 Lesson-Team-A/assignment/README.md create mode 100644 Lesson-Team-A/assignment/yours.sol create mode 100644 Lesson-Team-A/orgin/README.md create mode 100644 Lesson-Team-A/orgin/payroll.sol diff --git a/Lesson-Team-A/README.md b/Lesson-Team-A/README.md new file mode 100644 index 00000000..ba26ced6 --- /dev/null +++ b/Lesson-Team-A/README.md @@ -0,0 +1,16 @@ +## 硅谷live以太坊智能合约频道官方地址 + +### 第三课《智能合约后端优化和产品化》 + +目录结构 +
| +
|--orgin 课程初始代码 +
| +
|--assignment 课程作业提交代码 +
+### 本节知识点 +第3课:智能合约后端优化和产品化 +- 如何通过数据结构优化降低合约执行成本 +- 合约的继承 +- 巧用modifier +- 以太坊函数库的使用和基本介绍 diff --git a/Lesson-Team-A/assignment/README.md b/Lesson-Team-A/assignment/README.md new file mode 100644 index 00000000..01011eb4 --- /dev/null +++ b/Lesson-Team-A/assignment/README.md @@ -0,0 +1,14 @@ +## 硅谷live以太坊智能合约 第三课作业 +这里是同学提交作业的目录 + +### 第三课:课后作业 +- 第一题:完成今天所开发的合约产品化内容,使用Remix调用每一个函数,提交函数调用截图 +- 第二题:增加 changePaymentAddress 函数,更改员工的薪水支付地址,思考一下能否使用modifier整合某个功能 +- 第三题(加分题):自学C3 Linearization, 求以下 contract Z 的继承线 +- contract O +- contract A is O +- contract B is O +- contract C is O +- contract K1 is A, B +- contract K2 is A, C +- contract Z is K1, K2 diff --git a/Lesson-Team-A/assignment/yours.sol b/Lesson-Team-A/assignment/yours.sol new file mode 100644 index 00000000..dfdb2c48 --- /dev/null +++ b/Lesson-Team-A/assignment/yours.sol @@ -0,0 +1 @@ +/*作业请提交在这个目录下*/ diff --git a/Lesson-Team-A/orgin/README.md b/Lesson-Team-A/orgin/README.md new file mode 100644 index 00000000..6106ea19 --- /dev/null +++ b/Lesson-Team-A/orgin/README.md @@ -0,0 +1,3 @@ +## 硅谷live以太坊智能合约 第三课 + +这里是每一课的初始代码,有需要的同学可以参考 diff --git a/Lesson-Team-A/orgin/payroll.sol b/Lesson-Team-A/orgin/payroll.sol new file mode 100644 index 00000000..e69de29b From c8edf2b651ef70fe8810a28b4efa1fee792c0466 Mon Sep 17 00:00:00 2001 From: Xinwen Wang Date: Sun, 18 Mar 2018 10:54:03 -0400 Subject: [PATCH 3/6] Upload lesson 3 --- {Lesson-Team-A => Lesson-3}/README.md | 0 {Lesson-Team-A => Lesson-3}/assignment/README.md | 0 {Lesson-Team-A => Lesson-3}/assignment/yours.sol | 0 {Lesson-Team-A => Lesson-3}/orgin/README.md | 0 {Lesson-Team-A => Lesson-3}/orgin/payroll.sol | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {Lesson-Team-A => Lesson-3}/README.md (100%) rename {Lesson-Team-A => Lesson-3}/assignment/README.md (100%) rename {Lesson-Team-A => Lesson-3}/assignment/yours.sol (100%) rename {Lesson-Team-A => Lesson-3}/orgin/README.md (100%) rename {Lesson-Team-A => Lesson-3}/orgin/payroll.sol (100%) diff --git a/Lesson-Team-A/README.md b/Lesson-3/README.md similarity index 100% rename from Lesson-Team-A/README.md rename to Lesson-3/README.md diff --git a/Lesson-Team-A/assignment/README.md b/Lesson-3/assignment/README.md similarity index 100% rename from Lesson-Team-A/assignment/README.md rename to Lesson-3/assignment/README.md diff --git a/Lesson-Team-A/assignment/yours.sol b/Lesson-3/assignment/yours.sol similarity index 100% rename from Lesson-Team-A/assignment/yours.sol rename to Lesson-3/assignment/yours.sol diff --git a/Lesson-Team-A/orgin/README.md b/Lesson-3/orgin/README.md similarity index 100% rename from Lesson-Team-A/orgin/README.md rename to Lesson-3/orgin/README.md diff --git a/Lesson-Team-A/orgin/payroll.sol b/Lesson-3/orgin/payroll.sol similarity index 100% rename from Lesson-Team-A/orgin/payroll.sol rename to Lesson-3/orgin/payroll.sol From 6d9d36be32e0f3c112bf4dc3a8b21820cf01c35c Mon Sep 17 00:00:00 2001 From: Xinwen Wang Date: Wed, 21 Mar 2018 21:29:42 -0400 Subject: [PATCH 4/6] Upload lesson 4 --- Lesson-4/README.md | 16 ++++++++++++++++ Lesson-4/assignment/README.md | 12 ++++++++++++ Lesson-4/assignment/yours.sol | 1 + Lesson-4/orgin/README.md | 3 +++ Lesson-4/orgin/payroll.sol | 1 + 5 files changed, 33 insertions(+) create mode 100644 Lesson-4/README.md create mode 100644 Lesson-4/assignment/README.md create mode 100644 Lesson-4/assignment/yours.sol create mode 100644 Lesson-4/orgin/README.md create mode 100644 Lesson-4/orgin/payroll.sol diff --git a/Lesson-4/README.md b/Lesson-4/README.md new file mode 100644 index 00000000..34bf0bb8 --- /dev/null +++ b/Lesson-4/README.md @@ -0,0 +1,16 @@ +## 硅谷live以太坊智能合约频道官方地址 + +### 第四课《使用Truffle架构进行前后端交互,测试,部署》 + +目录结构 +
| +
|--orgin 课程初始代码 +
| +
|--assignment 课程作业提交代码 +
+### 本节知识点 +第4课:使用Truffle架构进行前后端交互,测试,部署 +- 为什么要用Truffle,Truffle的基本概念 +- Truffle 的command line 功能 +- 初始化项目与Truffle项目目录结构 +- 编译部署合约到testrpc diff --git a/Lesson-4/assignment/README.md b/Lesson-4/assignment/README.md new file mode 100644 index 00000000..871e6be0 --- /dev/null +++ b/Lesson-4/assignment/README.md @@ -0,0 +1,12 @@ +## 硅谷live以太坊智能合约 第四课作业 +这里是同学提交作业的目录 + +### 第四课:课后作业 +- 将第三课完成的payroll.sol程序导入truffle工程 +- 在test文件夹中,写出对如下两个函数的单元测试: +- function addEmployee(address employeeId, uint salary) onlyOwner +- function removeEmployee(address employeeId) onlyOwner employeeExist(employeeId) +- 思考一下我们如何能覆盖所有的测试路径,包括函数异常的捕捉 +- (加分题,选作) +- 写出对以下函数的基于solidity或javascript的单元测试 function getPaid() employeeExist(msg.sender) +- Hint:思考如何对timestamp进行修改,是否需要对所测试的合约进行修改来达到测试的目的? diff --git a/Lesson-4/assignment/yours.sol b/Lesson-4/assignment/yours.sol new file mode 100644 index 00000000..dfdb2c48 --- /dev/null +++ b/Lesson-4/assignment/yours.sol @@ -0,0 +1 @@ +/*作业请提交在这个目录下*/ diff --git a/Lesson-4/orgin/README.md b/Lesson-4/orgin/README.md new file mode 100644 index 00000000..c27ba052 --- /dev/null +++ b/Lesson-4/orgin/README.md @@ -0,0 +1,3 @@ +## 硅谷live以太坊智能合约 第四课 + +这里是每一课的初始代码,有需要的同学可以参考 diff --git a/Lesson-4/orgin/payroll.sol b/Lesson-4/orgin/payroll.sol new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/Lesson-4/orgin/payroll.sol @@ -0,0 +1 @@ + From cebcd6900a7279889a4f4f1713bdae600237f121 Mon Sep 17 00:00:00 2001 From: zihao Date: Sun, 25 Mar 2018 17:47:36 +0800 Subject: [PATCH 5/6] my lesson-4 homework --- Lesson-4/assignment/yours.sol | 163 +++++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/Lesson-4/assignment/yours.sol b/Lesson-4/assignment/yours.sol index dfdb2c48..27bc3e5a 100644 --- a/Lesson-4/assignment/yours.sol +++ b/Lesson-4/assignment/yours.sol @@ -1 +1,162 @@ -/*作业请提交在这个目录下*/ +pragma solidity ^0.4.18; + +import "./SafeMath.sol"; +import "./Ownable.sol"; +import "./PullPayment.sol"; + +/** + * @title Payroll + * @dev Base contract supporting: adding fund, adding employees, removing + * employees, updating employee salary, calculating runway, checking if balance + * is enough, transferring contract ownership, allowing employee to get paid, + * allowing leave-office employee to get severance pay. + */ +contract Payroll is Ownable, PullPayment { + + using SafeMath for uint; + + uint constant PAYMENT_DURATION = 10 seconds; + + struct Employee { + address id; + uint salary; + uint lastPaymentSettlementDate; // the last payment settlement date + } + mapping(address => Employee) employees; + uint public _totalSalary; + + /** + * @dev Throws if an employee doesn't exist. + * @param employeeId The employee id to be checked. + */ + modifier employee_exist(address employeeId) { + require(employees[employeeId].id != 0x0); + _; + } + + /** + * @dev Throws if an employee exists. + * @param employeeId The employee id to be checked. + */ + modifier employee_does_not_exist(address employeeId) { + require(employees[employeeId].id == 0x0); + _; + } + + /** + * @dev Allows caller to settle the current payment of an employee. + * @param employeeId The id of the employee. + */ + function _settlePayment(address employeeId) private { + Employee storage employee = employees[employeeId]; + uint workingdays = now.sub(employee.lastPaymentSettlementDate); + if (workingdays > 0) { + asyncSend( + employee.id, + workingdays.mul(employee.salary).div(PAYMENT_DURATION) + ); + employee.lastPaymentSettlementDate = now; + } + } + + /** + * @dev Allows owner to add an employee. + * @param employeeId The id of the employee. + * @param salary The salary of the employee. + */ + function addEmployee(address employeeId, uint salary) + public + onlyOwner + employee_does_not_exist(employeeId) + { + employees[employeeId] = Employee(employeeId, salary.mul(1 ether), now); + _totalSalary = _totalSalary.add(employees[employeeId].salary); + } + + /** + * @dev Allows owner to remove an employee. + * @param employeeId The id of the employee. + */ + function removeEmployee(address employeeId) + public + onlyOwner + employee_exist(employeeId) + { + _settlePayment(employeeId); + _totalSalary = _totalSalary.sub(employees[employeeId].salary); + delete employees[employeeId]; + } + + /** + * @dev Allows owner to change the salary of an employee. + * @param employeeId The id of the employee. + * @param newSalary The new salary of the employee. + */ + function updateEmployeeSalary(address employeeId, uint newSalary) + public + onlyOwner + employee_exist(employeeId) + { + require(newSalary != employees[employeeId].salary); + _settlePayment(employeeId); // Settle old-rate salary payment + _totalSalary = _totalSalary.add(newSalary).sub(employees[employeeId].salary); + employees[employeeId].salary = newSalary; + } + + /** + * @dev Allows an employee to transferring his payment address. + * @param newEmployeeId The id of the employee. + */ + function changePaymentAddress(address newEmployeeId) + public + employee_exist(msg.sender) + { + require(msg.sender != newEmployeeId); + employees[msg.sender].id = newEmployeeId; + employees[newEmployeeId] = employees[msg.sender]; + delete employees[msg.sender]; + uint payment = payments[msg.sender]; + delete payments[msg.sender]; + asyncSend(newEmployeeId, payment); + } + + /** + * @dev Allows adding funds/balance to the contract. + */ + function addFund() public payable returns (uint) { + return address(this).balance; + } + + /** + * @dev Allows calculating the runway of total salary. + */ + function calculateRunway() public returns (uint) { + return address(this).balance.div(_totalSalary); + } + + /** + * @dev Allows checking if the contract has enough fund. + */ + function hasEnoughFund() public returns (bool) { + return (calculateRunway() > 0); + } + + /** + * @dev Allows employee to get paid. + */ + function getPaid() public employee_exist(msg.sender) { + _settlePayment(msg.sender); + withdrawPayments(); + } + + /** + * @dev Allows left-office employee to get severance pay. + */ + function getSeverancePay() + public + employee_does_not_exist(msg.sender) + { + require(payments[msg.sender] > 0); + withdrawPayments(); + } +} From ebeade2951f9481734e40a388ecbbebc445b02ba Mon Sep 17 00:00:00 2001 From: zihao Date: Sun, 25 Mar 2018 17:47:50 +0800 Subject: [PATCH 6/6] my lesson-4 homework --- Lesson-4/assignment/Ownable.sol | 42 +++++++++++++++++++++++++ Lesson-4/assignment/PullPayment.sol | 43 ++++++++++++++++++++++++++ Lesson-4/assignment/SafeMath.sol | 48 +++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Lesson-4/assignment/Ownable.sol create mode 100644 Lesson-4/assignment/PullPayment.sol create mode 100644 Lesson-4/assignment/SafeMath.sol diff --git a/Lesson-4/assignment/Ownable.sol b/Lesson-4/assignment/Ownable.sol new file mode 100644 index 00000000..54158a2a --- /dev/null +++ b/Lesson-4/assignment/Ownable.sol @@ -0,0 +1,42 @@ +pragma solidity ^0.4.18; + + +/** + * @title Ownable + * @dev The Ownable contract has an owner address, and provides basic authorization control + * functions, this simplifies the implementation of "user permissions". + */ +contract Ownable { + address public owner; + + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + + /** + * @dev The Ownable constructor sets the original `owner` of the contract to the sender + * account. + */ + function Ownable() public { + owner = msg.sender; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(msg.sender == owner); + _; + } + + /** + * @dev Allows the current owner to transfer control of the contract to a newOwner. + * @param newOwner The address to transfer ownership to. + */ + function transferOwnership(address newOwner) public onlyOwner { + require(newOwner != address(0)); + OwnershipTransferred(owner, newOwner); + owner = newOwner; + } + +} diff --git a/Lesson-4/assignment/PullPayment.sol b/Lesson-4/assignment/PullPayment.sol new file mode 100644 index 00000000..fbd32a6f --- /dev/null +++ b/Lesson-4/assignment/PullPayment.sol @@ -0,0 +1,43 @@ +pragma solidity ^0.4.18; + + +import "./SafeMath.sol"; + + +/** + * @title PullPayment + * @dev Base contract supporting async send for pull payments. Inherit from this + * contract and use asyncSend instead of send. + */ +contract PullPayment { + using SafeMath for uint256; + + mapping(address => uint256) public payments; + uint256 public totalPayments; + + /** + * @dev withdraw accumulated balance, called by payee. + */ + function withdrawPayments() public { + address payee = msg.sender; + uint256 payment = payments[payee]; + + require(payment != 0); + require(this.balance >= payment); + + totalPayments = totalPayments.sub(payment); + payments[payee] = 0; + + assert(payee.send(payment)); + } + + /** + * @dev Called by the payer to store the sent amount as credit to be pulled. + * @param dest The destination address of the funds. + * @param amount The amount to transfer. + */ + function asyncSend(address dest, uint256 amount) internal { + payments[dest] = payments[dest].add(amount); + totalPayments = totalPayments.add(amount); + } +} diff --git a/Lesson-4/assignment/SafeMath.sol b/Lesson-4/assignment/SafeMath.sol new file mode 100644 index 00000000..788797ea --- /dev/null +++ b/Lesson-4/assignment/SafeMath.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.4.18; + + +/** + * @title SafeMath + * @dev Math operations with safety checks that throw on error + */ +library SafeMath { + + /** + * @dev Multiplies two numbers, throws on overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + if (a == 0) { + return 0; + } + uint256 c = a * b; + assert(c / a == b); + return c; + } + + /** + * @dev Integer division of two numbers, truncating the quotient. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + // assert(b > 0); // Solidity automatically throws when dividing by 0 + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + return c; + } + + /** + * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + assert(b <= a); + return a - b; + } + + /** + * @dev Adds two numbers, throws on overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + assert(c >= a); + return c; + } +}