├── README.md ├── contracts ├── interfaces │ ├── ISmartToken.sol │ ├── IOwned.sol │ ├── IMyAdvancedToken.sol │ └── IToken.sol ├── helpers │ ├── Hello_mshk_top.sol │ └── Migrations.sol ├── Owned.sol ├── SmartToken.sol ├── Utils.sol ├── Crowdsale.sol ├── MyAdvancedToken.sol └── Token.sol ├── truffle.js └── migrations ├── 1_initial_migration.js └── 2_deploy_contracts.js /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 目录 3 | [toc] 4 | 5 | 智能合约的实例,里面包括简单的代币合约、高级代币合约、众筹合约。 6 | 7 | 如何使用代码的文章教程:[Truffle 4.0、Geth 1.7.2、TestRPC在私有链上搭建智能合约](https://mshk.top/2017/11/truffle-4-0-geth-1-7-2-testrpc/) 8 | -------------------------------------------------------------------------------- /contracts/interfaces/ISmartToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | /* 4 | Standard ISmartyToken interface 5 | */ 6 | contract ISmartToken { 7 | 8 | function issue(address _to, uint256 _value) public; 9 | } 10 | -------------------------------------------------------------------------------- /truffle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // contracts_build_directory: "./output", 3 | networks: { 4 | development: { 5 | host: "localhost", 6 | port: 8545, 7 | network_id: "*" 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("./helpers/Migrations.sol"); 2 | var Hello_mshk_top = artifacts.require("./helpers/Hello_mshk_top.sol"); 3 | module.exports = function(deployer) { 4 | deployer.deploy(Migrations); 5 | deployer.deploy(Hello_mshk_top); 6 | }; 7 | -------------------------------------------------------------------------------- /contracts/helpers/Hello_mshk_top.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Hello_mshk_top { 4 | 5 | //say hello mshk.top 6 | function say() public pure returns (string) { 7 | return "Hello mshk.top"; 8 | } 9 | 10 | //print name 11 | function print(string name) public pure returns (string) { 12 | return name; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /contracts/interfaces/IOwned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | /* 4 | Owned contract interface 5 | */ 6 | contract IOwned { 7 | // this function isn't abstract since the compiler emits automatically generated getter functions as external 8 | function owner() public pure returns (address) {} 9 | 10 | function transferOwnership(address _newOwner) public; 11 | function acceptOwnership() public; 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IMyAdvancedToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | /* 4 | Standard IMyAdvancedToken interface 5 | */ 6 | contract IMyAdvancedToken { 7 | 8 | function _transfer(address _from, address _to, uint256 _value) internal; 9 | function mintToken(address target, uint256 mintedAmount) public; 10 | function freezeAccount(address target, bool freeze) public; 11 | function setPrices(uint256 newSellPrice, uint256 newBuyPrice) public; 12 | function buy() payable public; 13 | function sell(uint256 amount) public; 14 | } 15 | -------------------------------------------------------------------------------- /contracts/helpers/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | modifier restricted() { 8 | if (msg.sender == owner) _; 9 | } 10 | 11 | function Migrations() public { 12 | owner = msg.sender; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | 19 | function upgrade(address new_address) public restricted { 20 | Migrations upgraded = Migrations(new_address); 21 | upgraded.setCompleted(last_completed_migration); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /migrations/2_deploy_contracts.js: -------------------------------------------------------------------------------- 1 | /* global artifacts */ 2 | /* eslint-disable prefer-reflect */ 3 | 4 | const Utils = artifacts.require('./Utils.sol'); 5 | const Owned = artifacts.require('./Owned.sol'); 6 | const Token = artifacts.require('./Token.sol'); 7 | const MyAdvancedToken = artifacts.require('./MyAdvancedToken.sol'); 8 | const SmartToken = artifacts.require('./SmartToken.sol'); 9 | const Crowdsale = artifacts.require('./Crowdsale.sol'); 10 | 11 | module.exports = async (deployer) => { 12 | deployer.deploy(Utils); 13 | deployer.deploy(Owned); 14 | deployer.deploy(Token, 'mshk.top Token', 'MSHK-S', 0); 15 | deployer.deploy(MyAdvancedToken); 16 | await deployer.deploy(SmartToken, 'mshk.top SmartToken', 'MSHK-Smart', 2); 17 | deployer.deploy(Crowdsale, '0x777', 100, 30, SmartToken.address); 18 | }; 19 | -------------------------------------------------------------------------------- /contracts/interfaces/IToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | /* 4 | Standard Token interface 5 | */ 6 | contract IToken { 7 | // these functions aren't abstract since the compiler emits automatically generated getter functions as external 8 | function name() public pure returns (string) {} 9 | function symbol() public pure returns (string) {} 10 | function decimals() public pure returns (uint8) {} 11 | function totalSupply() public pure returns (uint256) {} 12 | function balanceOf(address _owner) public pure returns (uint256) { _owner; } 13 | function allowance(address _owner, address _spender) public pure returns (uint256) { _owner; _spender; } 14 | 15 | function _transfer(address _from, address _to, uint256 _value) internal; 16 | function transfer(address _to, uint256 _value) public returns (bool success); 17 | function transferFrom(address _from, address _to, uint256 _value) public returns (bool success); 18 | function approve(address _spender, uint256 _value) public returns (bool success); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /contracts/Owned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | import './interfaces/IOwned.sol'; 3 | 4 | /* 5 | owned 是一个管理者 6 | */ 7 | contract Owned is IOwned { 8 | address public owner; 9 | address public newOwner; 10 | 11 | event OwnerUpdate(address _prevOwner, address _newOwner); 12 | 13 | /** 14 | * 初始化构造函数 15 | */ 16 | function Owned() public { 17 | owner = msg.sender; 18 | } 19 | 20 | /** 21 | * 判断当前合约调用者是否是管理员 22 | */ 23 | modifier onlyOwner { 24 | assert(msg.sender == owner); 25 | _; 26 | } 27 | 28 | /** 29 | * 指派一个新的管理员 30 | * @param _newOwner address 新的管理员帐户地址 31 | */ 32 | function transferOwnership(address _newOwner) public onlyOwner { 33 | require(_newOwner != owner); 34 | newOwner = _newOwner; 35 | } 36 | 37 | /** 38 | @dev 新的管理员,确认接受做为管理员 39 | */ 40 | function acceptOwnership() public { 41 | require(msg.sender == newOwner); 42 | OwnerUpdate(owner, newOwner); 43 | owner = newOwner; 44 | newOwner = 0x0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /contracts/SmartToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | import './Token.sol'; 3 | import './Owned.sol'; 4 | import './interfaces/ISmartToken.sol'; 5 | 6 | contract SmartToken is ISmartToken, Owned, Token { 7 | 8 | string public version = '0.1'; 9 | 10 | // triggered when a smart token is deployed - the _token address is defined for forward compatibility, in case we want to trigger the event from a factory 11 | event NewSmartToken(address _token); 12 | 13 | /* 初始化合约,并且把初始的所有代币都给这合约的创建者 14 | * @param tokenName 代币名称 15 | * @param tokenSymbol 代币符号 16 | * @param decimalsUnits 代币后面的单位,小数点后面多少个0,以太币一样后面是是18个0 17 | */ 18 | function SmartToken(string tokenName, string tokenSymbol, uint8 decimalsUnits) 19 | public 20 | Token (tokenName, tokenSymbol, decimalsUnits) 21 | { 22 | NewSmartToken(address(this)); 23 | } 24 | 25 | 26 | /** 27 | * 增加代币,并将代币发送给捐赠新用户 28 | * @param _to address 接受代币的地址 29 | * @param _amount uint256 接受代币的数量 30 | */ 31 | function issue(address _to, uint256 _amount) 32 | validAddress(_to) 33 | public 34 | { 35 | _amount = _amount * 10 ** uint256(decimals); 36 | totalSupply = totalSupply + _amount; 37 | balanceOf[_to] = safeAdd(balanceOf[_to], _amount); 38 | 39 | //通知任何监听该交易的客户端 40 | Transfer(this, _to, _amount); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /contracts/Utils.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | /* 4 | Utilities & Common Modifiers 5 | */ 6 | contract Utils { 7 | /** 8 | constructor 9 | */ 10 | function Utils() public { 11 | } 12 | 13 | // verifies that an amount is greater than zero 14 | modifier greaterThanZero(uint256 _amount) { 15 | require(_amount > 0); 16 | _; 17 | } 18 | 19 | // validates an address - currently only checks that it isn't null 20 | modifier validAddress(address _address) { 21 | require(_address != 0x0); 22 | _; 23 | } 24 | 25 | // verifies that the address is different than this contract address 26 | modifier notThis(address _address) { 27 | require(_address != address(this)); 28 | _; 29 | } 30 | 31 | // Overflow protected math functions 32 | 33 | /** 34 | @dev returns the sum of _x and _y, asserts if the calculation overflows 35 | 36 | @param _x value 1 37 | @param _y value 2 38 | 39 | @return sum 40 | */ 41 | function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) { 42 | uint256 z = _x + _y; 43 | assert(z >= _x); 44 | return z; 45 | } 46 | 47 | /** 48 | @dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number 49 | 50 | @param _x minuend 51 | @param _y subtrahend 52 | 53 | @return difference 54 | */ 55 | function safeSub(uint256 _x, uint256 _y) internal pure returns (uint256) { 56 | assert(_x >= _y); 57 | return _x - _y; 58 | } 59 | 60 | /** 61 | @dev returns the product of multiplying _x by _y, asserts if the calculation overflows 62 | 63 | @param _x factor 1 64 | @param _y factor 2 65 | 66 | @return product 67 | */ 68 | function safeMul(uint256 _x, uint256 _y) internal pure returns (uint256) { 69 | uint256 z = _x * _y; 70 | assert(_x == 0 || z / _x == _y); 71 | return z; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /contracts/Crowdsale.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | 3 | 4 | import './Utils.sol'; 5 | import './interfaces/ISmartToken.sol'; 6 | 7 | 8 | /** 9 | * 众筹合约 10 | */ 11 | contract Crowdsale is Utils { 12 | address public beneficiary = 0x0; //受益人地址,测试时为合约创建者 13 | uint256 public fundingGoal = 100 ether; //众筹目标,单位是ether 14 | uint256 public amountRaised = 0; //已筹集金额数量, 单位是wei 15 | uint256 public deadline; //截止时间 16 | uint256 public price; //代币价格 17 | bool public fundingGoalReached = false; //达成众筹目标 18 | bool public crowdsaleClosed = false; //众筹关闭 19 | 20 | ISmartToken public token; // smart token 21 | 22 | mapping(address => uint256) public balance; //保存众筹地址 23 | 24 | //记录已接收的ether通知 25 | event GoalReached(address _beneficiary, uint _amountRaised); 26 | 27 | //转帐通知 28 | event FundTransfer(address _backer, uint _amount, bool _isContribution); 29 | 30 | /** 31 | * 初始化构造函数 32 | * 33 | * @param _beneficiary 受益人地址 34 | * @param _fundingGoalInEthers 众筹以太币总量 35 | * @param _durationInMinutes 众筹截止,单位是分钟 36 | * @param _token 众筹代币 37 | */ 38 | function Crowdsale( 39 | address _beneficiary, 40 | uint _fundingGoalInEthers, 41 | uint _durationInMinutes, 42 | ISmartToken _token 43 | ) 44 | public 45 | validAddress(_beneficiary) 46 | { 47 | token = _token; 48 | beneficiary = _beneficiary; 49 | fundingGoal = _fundingGoalInEthers * 1 ether; 50 | deadline = now + _durationInMinutes * 1 minutes; 51 | price = 500 finney; //1个以太币可以买 2 个代币 52 | } 53 | 54 | 55 | /** 56 | * 默认函数 57 | * 58 | * 默认函数,可以向合约直接打款 59 | */ 60 | function () payable public { 61 | 62 | //判断是否关闭众筹 63 | require(!crowdsaleClosed); 64 | uint amount = msg.value; 65 | 66 | //捐款人的金额累加 67 | balance[msg.sender] += amount; 68 | 69 | //捐款总额累加 70 | amountRaised += amount; 71 | 72 | //转帐操作,转多少代币给捐款人 73 | token.issue(msg.sender, amount / price); 74 | FundTransfer(msg.sender, amount, true); 75 | } 76 | 77 | /** 78 | * 判断是否已经过了众筹截止限期 79 | */ 80 | modifier afterDeadline() { if (now >= deadline) _; } 81 | 82 | /** 83 | * 检测众筹目标是否已经达到 84 | */ 85 | function checkGoalReached() public afterDeadline { 86 | if (amountRaised >= fundingGoal){ 87 | //达成众筹目标 88 | fundingGoalReached = true; 89 | GoalReached(beneficiary, amountRaised); 90 | } 91 | 92 | //关闭众筹 93 | crowdsaleClosed = true; 94 | } 95 | 96 | 97 | /** 98 | * 收回资金 99 | * 100 | * 检查是否达到了目标或时间限制,如果有,并且达到了资金目标, 101 | * 将全部金额发送给受益人。如果没有达到目标,每个贡献者都可以退出 102 | * 他们贡献的金额 103 | */ 104 | function safeWithdrawal() public afterDeadline { 105 | 106 | //如果没有达成众筹目标 107 | if (!fundingGoalReached) { 108 | //获取合约调用者已捐款余额 109 | uint amount = balance[msg.sender]; 110 | 111 | if (amount > 0) { 112 | //返回合约发起者所有余额 113 | msg.sender.transfer(amount); 114 | FundTransfer(msg.sender, amount, false); 115 | balance[msg.sender] = 0; 116 | } 117 | } 118 | 119 | //如果达成众筹目标,并且合约调用者是受益人 120 | if (fundingGoalReached && beneficiary == msg.sender) { 121 | 122 | //将所有捐款从合约中给受益人 123 | beneficiary.transfer(amountRaised); 124 | 125 | FundTransfer(beneficiary, amount, false); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /contracts/MyAdvancedToken.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | import './Token.sol'; 3 | import './Owned.sol'; 4 | import './interfaces/IMyAdvancedToken.sol'; 5 | 6 | /** 7 | * @title 高级版代币 8 | * 增加冻结用户、挖矿、根据指定汇率购买(售出)代币价格的功能 9 | */ 10 | contract MyAdvancedToken is IMyAdvancedToken, Owned, Token { 11 | 12 | //卖出的汇率,一个代币,可以卖出多少个以太币,单位是wei 13 | uint256 public sellPrice; 14 | 15 | //买入的汇率,1个以太币,可以买几个代币 16 | uint256 public buyPrice; 17 | 18 | //是否冻结帐户的列表 19 | mapping (address => bool) public frozenAccount; 20 | 21 | //定义一个事件,当有资产被冻结的时候,通知正在监听事件的客户端 22 | event FrozenFunds(address target, bool frozen); 23 | 24 | 25 | /*初始化合约,并且把初始的所有的令牌都给这合约的创建者 26 | */ 27 | function MyAdvancedToken() 28 | public 29 | Token ('mshk.top Advanced Token', 'MSHK-H', 2) 30 | { 31 | sellPrice = 2; //设置1个单位的代币(单位是wei),能够卖出2个以太币 32 | buyPrice = 4; //设置1个以太币,可以买0.25个代币 33 | } 34 | 35 | 36 | /** 37 | * 私有方法,从指定帐户转出余额 38 | * @param _from address 发送代币的地址 39 | * @param _to address 接受代币的地址 40 | * @param _value uint256 接受代币的数量 41 | */ 42 | function _transfer(address _from, address _to, uint _value) 43 | validAddress(_from) 44 | validAddress(_to) 45 | internal 46 | { 47 | //检查发送者是否拥有足够余额 48 | require (balanceOf[_from] > _value); 49 | 50 | //检查是否溢出 51 | require (balanceOf[_to] + _value > balanceOf[_to]); 52 | 53 | //检查 冻结帐户 54 | require(!frozenAccount[_from]); 55 | require(!frozenAccount[_to]); 56 | 57 | 58 | 59 | //从发送者减掉发送额 60 | balanceOf[_from] = safeSub(balanceOf[_from], _value); 61 | 62 | //给接收者加上相同的量 63 | balanceOf[_to] = safeAdd(balanceOf[_to], _value); 64 | 65 | //通知任何监听该交易的客户端 66 | Transfer(_from, _to, _value); 67 | 68 | } 69 | 70 | /** 71 | * 合约拥有者,可以为指定帐户创造一些代币 72 | * @param target address 帐户地址 73 | * @param mintedAmount uint256 增加的金额(单位是wei) 74 | */ 75 | function mintToken(address target, uint256 mintedAmount) 76 | validAddress(target) 77 | public 78 | onlyOwner 79 | { 80 | 81 | //给指定地址增加代币,同时总量也相加 82 | balanceOf[target] += mintedAmount; 83 | totalSupply += mintedAmount; 84 | 85 | 86 | Transfer(0, this, mintedAmount); 87 | Transfer(this, target, mintedAmount); 88 | } 89 | 90 | /** 91 | * 增加冻结帐户名称 92 | * 93 | * 你可能需要监管功能以便你能控制谁可以/谁不可以使用你创建的代币合约 94 | * 95 | * @param target address 帐户地址 96 | * @param freeze bool 是否冻结 97 | */ 98 | function freezeAccount(address target, bool freeze) 99 | validAddress(target) 100 | public 101 | onlyOwner 102 | { 103 | frozenAccount[target] = freeze; 104 | FrozenFunds(target, freeze); 105 | } 106 | 107 | /** 108 | * 设置买卖价格 109 | * 110 | * 如果你想让ether(或其他代币)为你的代币进行背书,以便可以市场价自动化买卖代币,我们可以这么做。如果要使用浮动的价格,也可以在这里设置 111 | * 112 | * @param newSellPrice 新的卖出价格 113 | * @param newBuyPrice 新的买入价格 114 | */ 115 | function setPrices(uint256 newSellPrice, uint256 newBuyPrice) public onlyOwner { 116 | sellPrice = newSellPrice; 117 | buyPrice = newBuyPrice; 118 | } 119 | 120 | /** 121 | * 使用以太币购买代币 122 | */ 123 | function buy() payable public { 124 | uint amount = msg.value / buyPrice; 125 | 126 | _transfer(this, msg.sender, amount); 127 | } 128 | 129 | /** 130 | * @dev 卖出代币 131 | * @return 要卖出的数量(单位是wei) 132 | */ 133 | function sell(uint256 amount) public { 134 | 135 | //检查合约的余额是否充足 136 | require(this.balance >= amount * sellPrice); 137 | 138 | _transfer(msg.sender, this, amount); 139 | 140 | msg.sender.transfer(amount * sellPrice); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /contracts/Token.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.4.17; 2 | import './Utils.sol'; 3 | import './interfaces/IToken.sol'; 4 | 5 | contract Token is IToken, Utils { 6 | /* 公共变量 */ 7 | string public standard = 'https://mshk.top'; 8 | string public name = ''; //代币名称 9 | string public symbol = ''; //代币符号比如'$' 10 | uint8 public decimals = 0; //代币单位 11 | uint256 public totalSupply = 0; //代币总量 12 | 13 | /*记录所有余额的映射*/ 14 | mapping (address => uint256) public balanceOf; 15 | mapping (address => mapping (address => uint256)) public allowance; 16 | 17 | /* 在区块链上创建一个事件,用以通知客户端*/ 18 | event Transfer(address indexed from, address indexed to, uint256 value); //转帐通知事件 19 | event Approval(address indexed _owner, address indexed _spender, uint256 _value); //设置允许用户支付最大金额通知 20 | 21 | /* 初始化合约,并且把初始的所有代币都给这合约的创建者 22 | * @param tokenName 代币名称 23 | * @param tokenSymbol 代币符号 24 | * @param decimalsUnits 代币后面的单位,小数点后面多少个0,以太币一样后面是是18个0 25 | */ 26 | function Token(string tokenName, string tokenSymbol, uint8 decimalsUnits) public { 27 | 28 | require(bytes(tokenName).length > 0 && bytes(tokenSymbol).length > 0); // validate input 29 | 30 | name = tokenName; 31 | symbol = tokenSymbol; 32 | decimals = decimalsUnits; 33 | 34 | } 35 | 36 | 37 | /** 38 | * 私有方法从一个帐户发送给另一个帐户代币 39 | * @param _from address 发送代币的地址 40 | * @param _to address 接受代币的地址 41 | * @param _value uint256 接受代币的数量 42 | */ 43 | function _transfer(address _from, address _to, uint256 _value) 44 | internal 45 | validAddress(_from) 46 | validAddress(_to) 47 | { 48 | 49 | 50 | //检查发送者是否拥有足够余额 51 | require(balanceOf[_from] >= _value); 52 | 53 | //检查是否溢出 54 | require(balanceOf[_to] + _value > balanceOf[_to]); 55 | 56 | //保存数据用于后面的判断 57 | uint previousBalances = safeAdd(balanceOf[_from], balanceOf[_to]); 58 | 59 | //从发送者减掉发送额 60 | balanceOf[_from] = safeSub(balanceOf[_from], _value); 61 | 62 | //给接收者加上相同的量 63 | balanceOf[_to] += safeAdd(balanceOf[_to], _value); 64 | 65 | //通知任何监听该交易的客户端 66 | Transfer(_from, _to, _value); 67 | 68 | //判断买、卖双方的数据是否和转换前一致 69 | assert(balanceOf[_from] + balanceOf[_to] == previousBalances); 70 | 71 | } 72 | 73 | /** 74 | * 从主帐户合约调用者发送给别人代币 75 | * @param _to address 接受代币的地址 76 | * @param _value uint256 接受代币的数量 77 | */ 78 | function transfer(address _to, uint256 _value) 79 | public 80 | validAddress(_to) 81 | returns (bool) 82 | { 83 | _transfer(msg.sender, _to, _value); 84 | return true; 85 | } 86 | 87 | /** 88 | * 从某个指定的帐户中,向另一个帐户发送代币 89 | * 90 | * 调用过程,会检查设置的允许最大交易额 91 | * 92 | * @param _from address 发送者地址 93 | * @param _to address 接受者地址 94 | * @param _value uint256 要转移的代币数量 95 | * @return 是否交易成功 96 | */ 97 | function transferFrom(address _from, address _to, uint256 _value) 98 | public 99 | validAddress(_from) 100 | validAddress(_to) 101 | returns (bool) 102 | { 103 | //检查发送者是否拥有足够余额支出的设置 104 | require(_value <= allowance[_from][msg.sender]); // Check allowance 105 | 106 | allowance[_from][msg.sender] -= safeSub(allowance[_from][msg.sender], _value); 107 | 108 | _transfer(_from, _to, _value); 109 | 110 | return true; 111 | } 112 | 113 | /** 114 | * 设置帐户允许支付的最大金额 115 | * 116 | * 一般在智能合约的时候,避免支付过多,造成风险 117 | * 118 | * @param _spender 帐户地址 119 | * @param _value 金额 120 | */ 121 | function approve(address _spender, uint256 _value) 122 | public 123 | validAddress(_spender) 124 | returns (bool success) 125 | { 126 | 127 | require(_value == 0 || allowance[msg.sender][_spender] == 0); 128 | 129 | allowance[msg.sender][_spender] = _value; 130 | Approval(msg.sender, _spender, _value); 131 | return true; 132 | } 133 | } 134 | --------------------------------------------------------------------------------