diff --git a/Lesson-1/assignment/yours.sol b/Lesson-1/assignment/yours.sol index dfdb2c4..49a3a3c 100644 --- a/Lesson-1/assignment/yours.sol +++ b/Lesson-1/assignment/yours.sol @@ -1 +1,66 @@ /*作业请提交在这个目录下*/ + +pragma solidity ^0.4.14; + +contract Payroll { + uint salary = 1 ether; //工资 + address employee; //员工地址 + address owner; //老板地址 + uint lastPayday ; // 上次发薪水的时间 + + uint constant payDuration = 10 seconds;// 发薪水的时间间隔 + + //设置老板地址 + function Payroll() public { + owner = msg.sender; + } + + + function updateEmployeeAddressSalary(address e, uint s){ + require(msg.sender == owner); + require(s>0); + + //修改前先结余 + if(employee != 0x0 ){ + uint shouldPay = salary*(now-lastPayday)/payDuration; + employee.transfer(shouldPay); + } + + employee = e; + salary = s * 1 ether; + lastPayday = now; + + } + + + + + //给智能合约打钱 + function addFund() payable returns (uint) { + return this.balance; + } + + //计算智能合约的钱能支付薪水多少次 + function calculateRunway() returns (uint) { + return this.balance/salary; + } + + //智能合约的钱是否足够支付薪水 + function hasEnoughFund() returns (bool) { + return calculateRunway() > 0; + } + + //获得薪水 + function getPaid() { + require(msg.sender == employee); + + uint nextPayday = lastPayday + payDuration; + + assert(nextPayday0; + } + + function getPaid() { + + var (employee,index) = _findEmployee(msg.sender); + require(employee.id == msg.sender); + + uint nextPayday = employee.lastPayday+payDuration; + require(nextPayday0; + } + + function getPaid() { + + var (employee,index) = _findEmployee(msg.sender); + require(employee.id == msg.sender); + + uint nextPayday = employee.lastPayday+payDuration; + require(nextPayday 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 Substracts 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; + } +} diff --git a/Lesson-3/assignment/addEmployee.png b/Lesson-3/assignment/addEmployee.png new file mode 100644 index 0000000..309003d Binary files /dev/null and b/Lesson-3/assignment/addEmployee.png differ diff --git a/Lesson-3/assignment/addFund.png b/Lesson-3/assignment/addFund.png new file mode 100644 index 0000000..bb48977 Binary files /dev/null and b/Lesson-3/assignment/addFund.png differ diff --git a/Lesson-3/assignment/calculateRunway.png b/Lesson-3/assignment/calculateRunway.png new file mode 100644 index 0000000..ba01533 Binary files /dev/null and b/Lesson-3/assignment/calculateRunway.png differ diff --git a/Lesson-3/assignment/getPaid.png b/Lesson-3/assignment/getPaid.png new file mode 100644 index 0000000..46bae07 Binary files /dev/null and b/Lesson-3/assignment/getPaid.png differ diff --git a/Lesson-3/assignment/hasEnoughFund.png b/Lesson-3/assignment/hasEnoughFund.png new file mode 100644 index 0000000..7dc8a00 Binary files /dev/null and b/Lesson-3/assignment/hasEnoughFund.png differ diff --git a/Lesson-3/assignment/removeEmployee.png b/Lesson-3/assignment/removeEmployee.png new file mode 100644 index 0000000..0c33cdf Binary files /dev/null and b/Lesson-3/assignment/removeEmployee.png differ diff --git a/Lesson-3/assignment/updateEmployee.png b/Lesson-3/assignment/updateEmployee.png new file mode 100644 index 0000000..c807498 Binary files /dev/null and b/Lesson-3/assignment/updateEmployee.png differ diff --git a/Lesson-3/assignment/yours.sol b/Lesson-3/assignment/yours.sol index dfdb2c4..1aa24b9 100644 --- a/Lesson-3/assignment/yours.sol +++ b/Lesson-3/assignment/yours.sol @@ -1 +1,88 @@ /*作业请提交在这个目录下*/ +pragma solidity ^0.4.14; + +import "./Ownable.sol"; +import "./SafeMath.sol"; + + +contract Payroll is Ownable { + using SafeMath for uint; + struct Employee { + address id; + uint salary; + uint lastPayday; + } + + + uint constant payDuration = 10 seconds; + + mapping(address=>Employee) public employees; + + uint totalSalary =0; + + modifier employeeExists(address employeeId) { + var employee = employees[employeeId]; + assert(employee.id != 0x0); + _; + } + + modifier employeeNotExists(address employeeId) { + var employee = employees[employeeId]; + assert(employee.id == 0x0); + _; + } + + function _partialPaid(Employee employee) private { + uint payment = employee.salary.mul(now.sub(employee.lastPayday)).div(payDuration); + employee.id.transfer(payment); + } + + function addEmployee(address employeeId, uint salary) onlyOwner employeeNotExists(employeeId) { + totalSalary = totalSalary.add(salary.mul(1 ether)); + employees[employeeId]=Employee(employeeId, salary.mul(1 ether), now); + } + + function removeEmployee(address employeeId) onlyOwner employeeExists(employeeId) { + var employee = employees[employeeId]; + totalSalary = totalSalary.sub(employee.salary); + _partialPaid(employee); + delete employees[employeeId]; + } + + + function updateEmployee(address employeeId, uint salary) onlyOwner employeeExists(employeeId) { + var employee = employees[employeeId]; + totalSalary = totalSalary.sub(employee.salary); + _partialPaid(employee); + totalSalary = totalSalary.add(salary.mul(1 ether)); + employee.lastPayday = now; + employee.salary = salary.mul(1 ether); + } + + function changePayAddress(address employeeId) employeeExists(msg.sender) employeeNotExists(employeeId) { + var employee = employees[msg.sender]; + employees[employeeId]=Employee(employeeId, employee.salary.mul(1 ether), employee.lastPayday); + delete employees[msg.sender]; + } + + function addFund() payable returns (uint) { + return this.balance; + } + + function calculateRunway() returns (uint) { + return this.balance.div(totalSalary); + } + + function hasEnoughFund() returns (bool) { + return calculateRunway()>0; + } + + function getPaid() employeeExists(msg.sender) { + var employee = employees[msg.sender]; + uint nextPayday = employee.lastPayday.add(payDuration); + require(nextPayday REACT_APP.test(key)) + .reduce((env, key) => { + env[key] = JSON.stringify(process.env[key]); + return env; + }, { + // Useful for determining whether we’re running in production mode. + // Most importantly, it switches React into the correct mode. + 'NODE_ENV': JSON.stringify( + process.env.NODE_ENV || 'development' + ), + // Useful for resolving the correct path to static assets in `public`. + // For example, . + // This should only be used as an escape hatch. Normally you would put + // images into the `src` and `import` them in code to get their paths. + 'PUBLIC_URL': JSON.stringify(publicUrl) + }); + return {'process.env': processEnv}; +} + +module.exports = getClientEnvironment; diff --git a/Lesson-4/assignment/payroll/config/jest/cssTransform.js b/Lesson-4/assignment/payroll/config/jest/cssTransform.js new file mode 100644 index 0000000..aa17d12 --- /dev/null +++ b/Lesson-4/assignment/payroll/config/jest/cssTransform.js @@ -0,0 +1,12 @@ +// This is a custom Jest transformer turning style imports into empty objects. +// http://facebook.github.io/jest/docs/tutorial-webpack.html + +module.exports = { + process() { + return 'module.exports = {};'; + }, + getCacheKey(fileData, filename) { + // The output is always the same. + return 'cssTransform'; + }, +}; diff --git a/Lesson-4/assignment/payroll/config/jest/fileTransform.js b/Lesson-4/assignment/payroll/config/jest/fileTransform.js new file mode 100644 index 0000000..927eb30 --- /dev/null +++ b/Lesson-4/assignment/payroll/config/jest/fileTransform.js @@ -0,0 +1,10 @@ +const path = require('path'); + +// This is a custom Jest transformer turning file imports into filenames. +// http://facebook.github.io/jest/docs/tutorial-webpack.html + +module.exports = { + process(src, filename) { + return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';'; + }, +}; diff --git a/Lesson-4/assignment/payroll/config/paths.js b/Lesson-4/assignment/payroll/config/paths.js new file mode 100644 index 0000000..96c3dfb --- /dev/null +++ b/Lesson-4/assignment/payroll/config/paths.js @@ -0,0 +1,46 @@ +var path = require('path'); +var fs = require('fs'); + +// Make sure any symlinks in the project folder are resolved: +// https://github.com/facebookincubator/create-react-app/issues/637 +var appDirectory = fs.realpathSync(process.cwd()); +function resolveApp(relativePath) { + return path.resolve(appDirectory, relativePath); +} + +// We support resolving modules according to `NODE_PATH`. +// This lets you use absolute paths in imports inside large monorepos: +// https://github.com/facebookincubator/create-react-app/issues/253. + +// It works similar to `NODE_PATH` in Node itself: +// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders + +// We will export `nodePaths` as an array of absolute paths. +// It will then be used by Webpack configs. +// Jest doesn’t need this because it already handles `NODE_PATH` out of the box. + +// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. +// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. +// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 + +var nodePaths = (process.env.NODE_PATH || '') + .split(process.platform === 'win32' ? ';' : ':') + .filter(Boolean) + .filter(folder => !path.isAbsolute(folder)) + .map(resolveApp); + +// config after eject: we're in ./config/ +module.exports = { + // Changed from build to build_webpack so smart contract compilations are not overwritten. + appBuild: resolveApp('build_webpack'), + appPublic: resolveApp('public'), + appHtml: resolveApp('public/index.html'), + appIndexJs: resolveApp('src/index.js'), + appPackageJson: resolveApp('package.json'), + appSrc: resolveApp('src'), + yarnLockFile: resolveApp('yarn.lock'), + testsSetup: resolveApp('src/setupTests.js'), + appNodeModules: resolveApp('node_modules'), + ownNodeModules: resolveApp('node_modules'), + nodePaths: nodePaths +}; diff --git a/Lesson-4/assignment/payroll/config/polyfills.js b/Lesson-4/assignment/payroll/config/polyfills.js new file mode 100644 index 0000000..7e60150 --- /dev/null +++ b/Lesson-4/assignment/payroll/config/polyfills.js @@ -0,0 +1,14 @@ +if (typeof Promise === 'undefined') { + // Rejection tracking prevents a common issue where React gets into an + // inconsistent state due to an error, but it gets swallowed by a Promise, + // and the user has no idea what causes React's erratic future behavior. + require('promise/lib/rejection-tracking').enable(); + window.Promise = require('promise/lib/es6-extensions.js'); +} + +// fetch() polyfill for making API calls. +require('whatwg-fetch'); + +// Object.assign() is commonly used with React. +// It will use the native implementation if it's present and isn't buggy. +Object.assign = require('object-assign'); diff --git a/Lesson-4/assignment/payroll/config/webpack.config.dev.js b/Lesson-4/assignment/payroll/config/webpack.config.dev.js new file mode 100644 index 0000000..821743a --- /dev/null +++ b/Lesson-4/assignment/payroll/config/webpack.config.dev.js @@ -0,0 +1,242 @@ +var autoprefixer = require('autoprefixer'); +var webpack = require('webpack'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); +var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); +var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); +var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); +var getClientEnvironment = require('./env'); +var paths = require('./paths'); + + + +// Webpack uses `publicPath` to determine where the app is being served from. +// In development, we always serve from the root. This makes config easier. +var publicPath = '/'; +// `publicUrl` is just like `publicPath`, but we will provide it to our app +// as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. +// Omit trailing slash as %PUBLIC_PATH%/xyz looks better than %PUBLIC_PATH%xyz. +var publicUrl = ''; +// Get environment variables to inject into our app. +var env = getClientEnvironment(publicUrl); + +// This is the development configuration. +// It is focused on developer experience and fast rebuilds. +// The production configuration is different and lives in a separate file. +module.exports = { + // You may want 'eval' instead if you prefer to see the compiled output in DevTools. + // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343. + devtool: 'cheap-module-source-map', + // These are the "entry points" to our application. + // This means they will be the "root" imports that are included in JS bundle. + // The first two entry points enable "hot" CSS and auto-refreshes for JS. + entry: [ + // Include an alternative client for WebpackDevServer. A client's job is to + // connect to WebpackDevServer by a socket and get notified about changes. + // When you save a file, the client will either apply hot updates (in case + // of CSS changes), or refresh the page (in case of JS changes). When you + // make a syntax error, this client will display a syntax error overlay. + // Note: instead of the default WebpackDevServer client, we use a custom one + // to bring better experience for Create React App users. You can replace + // the line below with these two lines if you prefer the stock client: + // require.resolve('webpack-dev-server/client') + '?/', + // require.resolve('webpack/hot/dev-server'), + require.resolve('react-dev-utils/webpackHotDevClient'), + // We ship a few polyfills by default: + require.resolve('./polyfills'), + // Finally, this is your app's code: + paths.appIndexJs + // We include the app code last so that if there is a runtime error during + // initialization, it doesn't blow up the WebpackDevServer client, and + // changing JS code would still trigger a refresh. + ], + output: { + // Next line is not used in dev but WebpackDevServer crashes without it: + path: paths.appBuild, + // Add /* filename */ comments to generated require()s in the output. + pathinfo: true, + // This does not produce a real file. It's just the virtual path that is + // served by WebpackDevServer in development. This is the JS bundle + // containing code from all our entry points, and the Webpack runtime. + filename: 'static/js/bundle.js', + // This is the URL that app is served from. We use "/" in development. + publicPath: publicPath + }, + resolve: { + // This allows you to set a fallback for where Webpack should look for modules. + // We read `NODE_PATH` environment variable in `paths.js` and pass paths here. + // We use `fallback` instead of `root` because we want `node_modules` to "win" + // if there any conflicts. This matches Node resolution mechanism. + // https://github.com/facebookincubator/create-react-app/issues/253 + fallback: paths.nodePaths, + // These are the reasonable defaults supported by the Node ecosystem. + // We also include JSX as a common component filename extension to support + // some tools, although we do not recommend using it, see: + // https://github.com/facebookincubator/create-react-app/issues/290 + extensions: ['.js', '.json', '.jsx', ''], + alias: { + // Support React Native Web + // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ + 'react-native': 'react-native-web' + } + }, + + module: { + // First, run the linter. + // It's important to do this before Babel processes the JS. + preLoaders: [ + { + test: /\.(js|jsx)$/, + loader: 'eslint', + include: paths.appSrc, + } + ], + loaders: [ + // Default loader: load all assets that are not handled + // by other loaders with the url loader. + // Note: This list needs to be updated with every change of extensions + // the other loaders match. + // E.g., when adding a loader for a new supported file extension, + // we need to add the supported extension to this loader too. + // Add one new line in `exclude` for each loader. + // + // "file" loader makes sure those assets get served by WebpackDevServer. + // When you `import` an asset, you get its (virtual) filename. + // In production, they would get copied to the `build` folder. + // "url" loader works like "file" loader except that it embeds assets + // smaller than specified limit in bytes as data URLs to avoid requests. + // A missing `test` is equivalent to a match. + { + exclude: [ + /\.html$/, + /\.(js|jsx)$/, + /\.css$/, + /\.json$/, + /\.woff$/, + /\.woff2$/, + /\.(ttf|svg|eot)$/ + ], + loader: 'url', + query: { + limit: 10000, + name: 'static/media/[name].[hash:8].[ext]' + } + }, + // Process JS with Babel. + { + test: /\.(js|jsx)$/, + include: paths.appSrc, + loader: 'babel', + query: { + + // This is a feature of `babel-loader` for webpack (not Babel itself). + // It enables caching results in ./node_modules/.cache/babel-loader/ + // directory for faster rebuilds. + cacheDirectory: true + } + }, + // "postcss" loader applies autoprefixer to our CSS. + // "css" loader resolves paths in CSS and adds assets as dependencies. + // "style" loader turns CSS into JS modules that inject