{"content":{"title":"区块链开发必备（2）——IDE，编写测试代码及调试","body":"入门福利：5分钟基于以太坊发一个属于自己的代币，仅需4步。\r\n需要准备：\r\n1. 钱包：推荐使用MetaMask\r\n2. 原生代币：ETH。测试建议使用测试网：[ropsten](https://faucet.ropsten.be/)，[kovan](https://faucet.kovan.network/)，[rinkeby](https://faucet.rinkeby.io/)\r\n3. 合约代码：open source, 本文最下面也有合约代码\r\n4. 编译及发布工具：推荐remix\r\n\r\n\r\n正文开始：\r\n\r\n## 1. IDE:\r\n  ○ web 网页客户端：[remix](https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.4.26+commit.4563c3fc.js)\r\n    ■ 简单的代码测试，debug都可以\r\n    \r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/RBUhPAmD636cde7198479.png)\r\n  ○ 桌面客户端：任何你熟悉的ide:vscode,sublime,webstorm\r\n    ■ 编译器：[truffle](https://www.trufflesuite.com/)，[hardhat](https://hardhat.org/getting-started/)\r\n    ■ 以太坊本地区块链节点:ganache-cli\r\n## 2. Demo: https://gitee.com/klg-blockchain/smart_contract_demo\r\n\r\n  ○ 项目结构：\r\n    ■ \r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/4Dd6jBt9636cde7e8ed1c.png)\r\n  ○ 简答合约验证\r\n\r\n\r\n```js\r\ntruffle console\r\nHello.deployed().then((instance)=>{app = instance})\r\napp.setGreeting('Hello world')\r\napp.greet()\r\n```\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/OCZVLKHu636cdead7ab85.png)\r\n  ○ 单元测试\r\n  \r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/2wL2VWUF636cded6d54bc.png)\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/3ByjfAJ3636cdee7574f5.png)\r\n  \r\n   \r\n## 3. 调试\r\n  ○ web 网页客户端：[remix](https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.4.26+commit.4563c3fc.js)\r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/9O5DgEV0636cdef4e1866.png)\r\n   \r\n  ○ VScode 客户端\r\n    ■ 安装solidity debugger 插件\r\n    ■[ 安装dotnet sdk ](https://dotnet.microsoft.com/download)\r\n    \r\n![image.png](https://img.learnblockchain.cn/attachments/2022/11/b6ioU3Rx636cdf0a3d1d0.png)\r\n    \r\n[solidity 学习文档](https://solidity-cn.readthedocs.io/zh/develop/solidity-by-example.html)\r\n\r\nsmart contract erc20 token demo:\r\n\r\n\r\n```js\r\n\r\npragma solidity ^0.4.22;\r\n\r\ncontract Token {\r\n    // token总量，默认会为public变量生成一个getter函数接口，名称为totalSupply().\r\n    uint256 public totalSupply;\r\n    /// 获取账户_owner拥有token的数量\r\n    function balanceOf(address _owner) public view returns (uint256 balance);\r\n    //从消息发送者账户中往_to账户转数量为_value的token\r\n    function transfer(address _to, uint256 _value) returns (bool success);\r\n    //从账户_from中往账户_to转数量为_value的token，与approve方法配合使用\r\n    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);\r\n    //消息发送账户设置账户_spender能从发送账户中转出数量为_value的token\r\n    function approve(address _spender, uint256 _value) returns (bool success);\r\n    //获取账户_spender可以从账户_owner中转出token的数量\r\n    function allowance(address _owner, address _spender) public view returns (uint256 remaining);\r\n    //发生转账时必须要触发的事件\r\n    event Transfer(address indexed _from, address indexed _to, uint256 _value);\r\n    //当函数approve(address _spender, uint256 _value)成功执行时必须触发的事件\r\n    event Approval(address indexed _owner, address indexed _spender, uint256 _value);\r\n}\r\n\r\ncontract StandardToken is Token {\r\n    mapping (address => uint256) balances;\r\n    mapping (address => mapping (address => uint256)) allowed;\r\n    function transfer(address _to, uint256 _value) returns(bool success) {\r\n        //默认totalSupply 不会超过最大值 (2^256 - 1).\r\n        //如果随着时间的推移将会有新的token生成，则可以用下面这句避免溢出的异常\r\n        //require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);\r\n        require(balances[msg.sender] >= _value);\r\n        balances[msg.sender] -= _value; //从消息发送者账户中减去token数量_value\r\n        balances[_to] += _value; //往接收账户增加token数量_value\r\n        Transfer(msg.sender, _to, _value); //触发转币交易事件\r\n        return true;\r\n    }\r\n    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {\r\n        require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);\r\n        balances[_to] += _value; //接收账户增加token数量_value\r\n        balances[_from] -= _value; //支出账户_from减去token数量_value\r\n        allowed[_from][msg.sender] -= _value; //消息发送者可以从账户_from中转出的数量减少_value\r\n        Transfer(_from, _to, _value); //触发转币交易事件\r\n        return true;\r\n    }\r\n    function balanceOf(address _owner) public view returns (uint256 balance) {\r\n        return balances[_owner];\r\n    }\r\n    function approve(address _spender, uint256 _value) returns (bool success) {\r\n        allowed[msg.sender][_spender] = _value;\r\n        Approval(msg.sender, _spender, _value);\r\n        return true;\r\n    }\r\n    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {\r\n        return allowed[_owner][_spender]; //允许_spender从_owner中转出的token数\r\n    }\r\n}\r\n\r\ncontract HumanStandardToken is StandardToken {\r\n    /* Public variables of the token */\r\n    string public name; //名称: eg Simon Bucks\r\n    uint256 public decimals; //最多的小数位数，How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX =980 base units. It's like comparing 1 wei to 1 ether.\r\n    string public symbol; //token简称: eg SBX\r\n    string public version = \"V8\";    //版本\r\n    \r\n    // 转换\r\n    function formatDecimals(uint256 _value) internal returns (uint256 ) {\r\n        return _value * 10 ** decimals;\r\n    }\r\n    \r\n    constructor(uint256 _initialAmount, string _tokenName, uint256 _decimalUnits, string _tokenSymbol) public {\r\n        name = _tokenName; // token名称\r\n        decimals = _decimalUnits; // 小数位数\r\n        symbol = _tokenSymbol; // token简称\r\n        totalSupply = formatDecimals(_initialAmount); //设置初始总量\r\n        balances[msg.sender] = totalSupply; //初始token数量给予消息发送者\r\n    }\r\n    /* Approves and then calls the receiving contract */\r\n    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {\r\n        allowed[msg.sender][_spender] = _value;\r\n        Approval(msg.sender, _spender, _value);\r\n        require(_spender.call(bytes4(bytes32(sha3(\"receiveApproval(address,uint256,address,bytes)\"))), msg.sender, _value, this, _extraData));\r\n        return true;\r\n    }\r\n}\r\n\r\n```"},"author":{"user":"https://learnblockchain.cn/people/12541","address":null},"history":"QmNpNDcBKnrHEd49n1LSFPh9729HQFLjAyo2hz1LQD62iu","timestamp":1668127709,"version":1}