【官方連接】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); }