【官方连接】git
contract ERC20 { //**********9个函数******* //1.代币的名字,如:"黑马币" function name() constant public returns (string name); //2.代币的简称,例如:HMB function symbol() public constant returns (string symbol); //3.代币的最小分割量 token使用的小数点后几位。好比若是设置为3,就是支持0.001表示 function decimals() public constant returns (uint8 decimals); //4.token的总量 function totalSupply() public constant returns (uint totalSupply); //5.余额 返回某个地址(帐户)的帐户余额 function balanceOf(address _owner) public constant returns (uint balance); /*6.转帐 交易代币 从消息发送者帐户中往_to帐户转数量为_value的token, 从代币合约的调用者地址上转移 _value的数量token到的地址 _to 【注意:而且必须触发Transfer事件】*/ function transfer(address _to, uint _value) public returns (bool success); /*7.两个地址转帐 从帐户_from中往帐户_to转数量为_value的token,与approve方法配合使用 从地址 _from发送数量为 _value的token到地址 _to 【注意:而且必须触发Transfer事件】 transferFrom方法用于容许合约代理某人转移token。条件是from帐户必须通过了approve。*/ function transferFrom(address _from, address _to, uint _value) public returns (bool success); //8.批准_spender能从合约调用帐户中转出数量为_value的token function approve(address _spender, uint _value) public returns (bool success); //9.获取_spender能够从帐户_owner中转出token的剩余数量 function allowance(address _owner, address _spender) public constant returns (uint remaining); //**********2个事件******* //1.发生转帐时必需要触发的事件,transfer 和 transferFrom 成功执行时必须触发的事件 event Transfer(address indexed _from, address indexed _to, uint _value); //2.当函数 approve(address _spender, uint256 _value)成功执行时必须触发的事件 event Approval(address indexed _owner, address indexed _spender, uint _value); }
// 此合约实现不记得是哪看到后复制保存的......和官网案例相似 pragma solidity ^0.4.25; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } contract TokenERC20 { string public name; // ERC20标准 string public symbol; // ERC20标准 uint8 public decimals = 2; // ERC20标准,decimals 能够有的小数点个数,最小的代币单位。18 是建议的默认值 uint256 public totalSupply; // ERC20标准 总供应量 // 用mapping保存每一个地址对应的余额 ERC20标准 mapping (address => uint256) public balanceOf; // 存储对帐号的控制 ERC20标准 mapping (address => mapping (address => uint256)) public allowance; // 事件,用来通知客户端交易发生 ERC20标准 event Transfer(address indexed from, address indexed to, uint256 value); // 事件,用来通知客户端代币被消费 ERC20标准 event Burn(address indexed from, uint256 value); /** * 初始化构造 */ function TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) public { totalSupply = initialSupply * 10 ** uint256(decimals); // 供应的份额,份额跟最小的代币单位有关,份额 = 币数 * 10 ** decimals。 balanceOf[msg.sender] = totalSupply; // 建立者拥有全部的代币 name = tokenName; // 代币名称 symbol = tokenSymbol; // 代币符号 } /** * 代币交易转移的内部实现 */ function _transfer(address _from, address _to, uint _value) internal { // 确保目标地址不为0x0,由于0x0地址表明销毁 require(_to != 0x0); // 检查发送者余额 require(balanceOf[_from] >= _value); // 确保转移为正数个 require(balanceOf[_to] + _value > balanceOf[_to]); // 如下用来检查交易, uint previousBalances = balanceOf[_from] + balanceOf[_to]; // Subtract from the sender balanceOf[_from] -= _value; // Add the same to the recipient balanceOf[_to] += _value; Transfer(_from, _to, _value); // 用assert来检查代码逻辑。 assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } /** * 代币交易转移 * 从本身(建立交易者)帐号发送`_value`个代币到 `_to`帐号 * ERC20标准 * @param _to 接收者地址 * @param _value 转移数额 */ function transfer(address _to, uint256 _value) public { _transfer(msg.sender, _to, _value); } /** * 帐号之间代币交易转移 * ERC20标准 * @param _from 发送者地址 * @param _to 接收者地址 * @param _value 转移数额 */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } /** * 设置某个地址(合约)能够建立交易者名义花费的代币数。 * * 容许发送者`_spender` 花费很少于 `_value` 个代币 * ERC20标准 * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } /** * 设置容许一个地址(合约)以我(建立交易者)的名义可最多花费的代币数。 *-非ERC20标准 * @param _spender 被受权的地址(合约) * @param _value 最大可花费代币数 * @param _extraData 发送给合约的附加数据 */ function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { // 通知合约 spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } /** * 销毁我(建立交易者)帐户中指定个代币 *-非ERC20标准 */ function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); // Check if the sender has enough balanceOf[msg.sender] -= _value; // Subtract from the sender totalSupply -= _value; // Updates totalSupply Burn(msg.sender, _value); return true; } /** * 销毁用户帐户中指定个代币 *-非ERC20标准 * Remove `_value` tokens from the system irreversibly on behalf of `_from`. * * @param _from the address of the sender * @param _value the amount of money to burn */ function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); // Check if the targeted balance is enough require(_value <= allowance[_from][msg.sender]); // Check allowance balanceOf[_from] -= _value; // Subtract from the targeted balance allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance totalSupply -= _value; // Update totalSupply Burn(_from, _value); return true; } }
const solc = require('solc'); const path = require('path'); const fs = require('fs'); //1.1 合约代码文件路径 const sourceFilePath = path.resolve(__dirname,'./TokenERC20.sol'); //1.2 合约编译后的文件路径 const bytecodeFilePath = path.resolve(__dirname,'./TokenERC20.bytecode'); //2.读取文件 const source = fs.readFileSync(sourceFilePath,'utf-8'); //3.编译 const result = solc.compile(source,1); //console.log(result); console.log('1.编译完成:'+sourceFilePath); fs.writeFileSync(bytecodeFilePath,JSON.stringify(result.contracts[':TokenERC20']),'utf-8'); console.log('2.字节文件写入完成:'+bytecodeFilePath); //4.暴露给外部访问 //module.exports=result.contracts[':TokenERC20'];
//1.1 导入 编译好的 合约的 字节代码 和 abi const path = require('path'); const fs = require('fs'); //1.2 合约编译后的文件路径 const bytecodeFilePath = path.resolve(__dirname,'./TokenERC20.bytecode'); const bytecodeJsonStr = fs.readFileSync(bytecodeFilePath,'utf-8'); const byteCodeJsonObj = JSON.parse(bytecodeJsonStr); //const {bytecode,interface} = require('./compilCaiPiao'); const bytecode = byteCodeJsonObj.bytecode; const interface = byteCodeJsonObj.interface; //2.导入 hd钱包provider const HDWalletProvider = require("truffle-hdwallet-provider"); //3.助记词(至关因而咱们的私钥) const mnemonic = "jar ... cat beef"; // 12 word mnemonic //4.建立 provider,能够用来访问 以太坊真实网络节点 const provider = new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/v3/3a60f2b160....",1);//最后的0 是获取 助记词 的第1个地址 //5.建立web对象 const Web3 = require('web3'); const web3= new Web3(provider); async function main(){ console.log('开始与以太网交互......'); const usrAdr = await web3.eth.getAccounts();//0x6c57CD10B4384C605aC748937b6cC1dF6C8eddA9 web3.eth.defaultAccount = usrAdr[0]; console.log('当前调用者的地址:' + web3.eth.defaultAccount); //6.部署合约到 以太网节点 //let contractObj =await deployContract(); //7.调用合约 //7.0 建立 远程智能合约 const contractObj = await new web3.eth.Contract(JSON.parse(interface),'0x46495b091cd3Fcb789cC336c3B5e9041E28555b0'); console.log('获取【合约】对象成功!'); // // 7.1 获取指定地址余额 await getBalanceAt(contractObj,'0x85BCc0F34718e80c332d41C513B72f8640B05249'); //await transferTo(contractObj,'0x83E9e99B7f5018680930baE0C7801555C850D9C5',10000000); //await approveTo(contractObj,'0x83E9e99B7f5018680930baE0C7801555C850D9C5',1000000000); await allowanceAt(contractObj,'0x85BCc0F34718e80c332d41C513B72f8640B05249','0x83E9e99B7f5018680930baE0C7801555C850D9C5'); await transferFrom(contractObj,'0x85BCc0F34718e80c332d41C513B72f8640B05249','0x737Df786f6e86625258960970c6752Fd7926F752',1); await allowanceAt(contractObj,'0x85BCc0F34718e80c332d41C513B72f8640B05249','0x83E9e99B7f5018680930baE0C7801555C850D9C5'); //await getBalanceAt(contractObj,'0x737Df786f6e86625258960970c6752Fd7926F752'); // //7.2 显示合约帐户余额 // await showContracMoney(contractObj); // //查看调用者购买的号码 // await showInvokerLuckNum(contractObj); // 7.3 开奖+ // await withdrawLottery(contractObj); // 7.4 显示买家帐户列表 // await showUsrList(contractObj); // await showContracMoney(contractObj); // 7.5 重置数据 //await resetContract(contractObj); //await showManageAddress(contractObj); //await killContract(contractObj); console.log('结束!'); } //启动 main(); // 1.部署合约 async function deployContract() { console.log('开始部署合约......'); let contractObj = await new web3.eth.Contract(JSON.parse(interface)) .deploy({ data: bytecode,//TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) arguments: ['1000000000','梦想零钱','DreamCoin'] }).send({ from:web3.eth.defaultAccount, gas:'1000000' }); console.log('部署成功,合约地址:【'+contractObj.options.address+'】'); return contractObj; } // 2.查询余额 async function getBalanceAt(contractObj,usrAdr) { let usrMoney = await contractObj.methods.balanceOf(usrAdr).call(); console.log('地址【'+usrAdr+'】余额:'+usrMoney); } //3.将当前调用者的钱 转 money 金额给 usrAdrTo async function transferTo(contractObj,usrAdrTo, money) { let result = await contractObj.methods.transfer(usrAdrTo,money).send({ from:web3.eth.defaultAccount, gas:'1000000' }); console.log('【'+web3.eth.defaultAccount+'】向【'+usrAdrTo+'】转帐【'+money+'】完毕'); console.log('转帐完毕~记录以下:') console.log(result); } //4.受权(当前调用者受权给 spenderAdr 操做数额为 money 的代币) async function approveTo(contractObj,spenderAdr, money){ let result = await contractObj.methods.approve(spenderAdr,money).send({ from:web3.eth.defaultAccount, gas:'1000000' }); console.log('【'+web3.eth.defaultAccount+'】向【'+spenderAdr+'】受权【'+money+'】完毕!'); //console.log(result); } //5.查询受权 async function allowanceAt(contractObj,ownerAdr,spenderAdr) { let result = await contractObj.methods.allowance(ownerAdr,spenderAdr).call(); console.log('查询:【'+ownerAdr+'】给【'+spenderAdr+'】剩余受权余额为:'+result); } //6.转帐(汇款人地址,收款人地址,金额) async function transferFrom(contractObj,usrAdrFrom, usrAdrTo, money) { let result = await contractObj.methods.transferFrom(usrAdrFrom,usrAdrTo,money).send({ from:web3.eth.defaultAccount, gas:'1000000' }); console.log('【'+usrAdrFrom+'】向【'+usrAdrTo+'】转帐【'+money+'】完毕'); //console.log(result); }