Cover photo

solidity智能合约在moonbeam上测试(mac os)

大致先归纳下几个步骤和目标

目标:在polkatdot的moonbeam链上发布智能合约solidity,使用web3.js连接测试

步骤:

  • 安装moonbeam节点

  • 账号工具脚本

  • 发布solidity脚本

需要安装和工具:

  • node

  • rust

  • cargo

  • 连接外部网络工具

步骤:

1.安装moonbeam节点

1.1获取moonbeam的node docker

docker pull purestake/moonbeam:v0.23.0

1.2用docker启动node

docker run --rm --name moonbeam_development -p 9944:9944 -p 9933:9933 \
purestake/moonbeam:v0.23.0 \
--dev --ws-external --rpc-external

如果启动成功,输出

post image

有了moonbeam链, 接下来需要提供一个后台服务,生产环境建议OnFinality或是Blast,我们这里就直接使用127.0.0.1:9944做后台服务。

2接下来会写两个脚本,第一个检查账号,第二个发动交易。

  • 创建node工程

  • 创建脚本

2.1创建工程

mkdir web3-examples && cd web3-examples
npm install web3 solc@0.8.0

2.2 账户脚本(balances.js)

检查两个账号:0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac 和 0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0,这里是随机选择的,也可以别的账号,账号查看打开

https://polkadot.js.org/apps/#/accounts

// 1. Add the Web3 provider logic here:
// {...}
const Web3 = require('web3');

//Create web3 instance
const web3 = new Web3('http://127.0.0.1:9933');



// 2. Create address variables
const addressFrom = '0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac';
const addressTo   = '0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0';

// 3. Create balances function
const balances = async () => {
  // 4. Fetch balance info
  const balanceFrom = web3.utils.fromWei(await web3.eth.getBalance(addressFrom), 'ether');
  const balanceTo = web3.utils.fromWei(await web3.eth.getBalance(addressTo), 'ether');

  console.log(`The balance of ${addressFrom} is: ${balanceFrom} ETH`);
  console.log(`The balance of ${addressTo} is: ${balanceTo} ETH`);
};

// 5. Call balances function
balances();

执行

node balances.js

输出

The balance of 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac is: 1207825.819614629174706176 ETH
The balance of 0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0 is: 1208925.819614629174706176 ETH

看到上面的输出就代表脚本正确执行了。

2.3交易脚本(transaction.js)

从一个账户转移eth到另外一个账号

// 1. Add the Web3 provider logic here:
// {...}

// 2. Create account variables
const accountFrom = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
  address: 'PUBLIC-ADDRESS-OF-PK-HERE',
};
const addressTo = 'ADDRESS-TO-HERE'; // Change addressTo

// 3. Create send function
const send = async () => {
  console.log(`Attempting to send transaction from ${accountFrom.address} to ${addressTo}`);

  // 4. Sign tx with PK
  const createTransaction = await web3.eth.accounts.signTransaction(
    {
      gas: 21000,
      to: addressTo,
      value: web3.utils.toWei('1', 'ether'),
    },
    accountFrom.privateKey
  );

  // 5. Send tx and wait for receipt
  const createReceipt = await web3.eth.sendSignedTransaction(createTransaction.rawTransaction);
  console.log(`Transaction successful with hash: ${createReceipt.transactionHash}`);
};

// 6. Call send function
send();

执行

node transaction.js

输出

Attempting to send transaction from 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac to 0x3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0
Transaction successful with hash: 0xb1f3e505fbb1540d8eba2ea574824608878de839cbd29c27f9a0ef6cec146b00

ok ,成功。这个时候你可以再次查询balance脚本查看是否有变化。

接下来步入主要的内容了,发布solidity智能合约了。

3发布智能合约solidity

3.1智能合约(Incrementer.sol)

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Incrementer {
    uint256 public number;

    constructor(uint256 _initialNumber) {
        number = _initialNumber;
    }

    function increment(uint256 _value) public {
        number = number + _value;
    }

    function reset() public {
        number = 0;
    }
}

3.2编译脚本(compile.js)

// 1. Import packages
const fs = require('fs');
const solc = require('solc');

// 2. Get path and load contract
const source = fs.readFileSync('Incrementer.sol', 'utf8');

// 3. Create input object
const input = {
   language: 'Solidity',
   sources: {
      'Incrementer.sol': {
         content: source,
      },
   },
   settings: {
      outputSelection: {
         '*': {
            '*': ['*'],
         },
      },
   },
};
// 4. Compile the contract
const tempFile = JSON.parse(solc.compile(JSON.stringify(input)));
const contractFile = tempFile.contracts['Incrementer.sol']['Incrementer'];

// 5. Export contract data
module.exports = contractFile;

3.3发布脚本(deploy.js)

// 1. Import the contract file
const contractFile = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Create address variables
const accountFrom = {
  privateKey: 'YOUR-PRIVATE-KEY-HERE',
  address: 'PUBLIC-ADDRESS-OF-PK-HERE',
};

// 4. Get the bytecode and API
const bytecode = contractFile.evm.bytecode.object;
const abi = contractFile.abi;

// 5. Create deploy function
const deploy = async () => {
  console.log(`Attempting to deploy from account ${accountFrom.address}`);

  // 6. Create contract instance
  const incrementer = new web3.eth.Contract(abi);

  // 7. Create constructor tx
  const incrementerTx = incrementer.deploy({
    data: bytecode,
    arguments: [5],
  });

  // 8. Sign transacation and send
  const createTransaction = await web3.eth.accounts.signTransaction(
    {
      data: incrementerTx.encodeABI(),
      gas: await incrementerTx.estimateGas(),
    },
    accountFrom.privateKey
  );

  // 9. Send tx and wait for receipt
  const createReceipt = await web3.eth.sendSignedTransaction(createTransaction.rawTransaction);
  console.log(`Contract deployed at address: ${createReceipt.contractAddress}`);
};

// 10. Call deploy function
deploy();

上面的私钥和地址替换下

执行

node deploy.js

输出

Attempting to deploy from account 0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac
Contract deployed at address: 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3

ok,成功。

3.4查看智能合约脚本(get.js)

// 1. Import the contract abi
const { abi } = require('./compile');

// 2. Add the Ethers provider logic here:
// {...}

// 3. Create address variables
const contractAddress = 'CONTRACT-ADDRESS-HERE';

// 4. Create contract instance
const incrementer = new web3.eth.Contract(abi, contractAddress);

// 5. Create get function
const get = async () => {
  console.log(`Making a call to contract at address: ${contractAddress}`);

  // 6. Call contract
  const data = await incrementer.methods.number().call();

  console.log(`The current number stored is: ${data}`);
};

// 7. Call get function
get();

输出

Making a call to contract at address: 0xc01Ee7f10EA4aF4673cFff62710E1D7792aBa8f3
The current number stored is: 5

这里我们看到number stored是5,那是因为我们在发布智能合约的时候,输入的初始化就是5。看deploy.js

  // 7. Create constructor tx
  const incrementerTx = incrementer.deploy({
    data: bytecode,
    arguments: [5],
  });

上面的各种账号/交易/合约的查询也可以在页面中查看,基本的可以使用

https://moonbeam-explorer.netlify.app/

里面配置本地连接的 node.

参考:

1.本文整体参考

https://docs.moonbeam.network/builders/build/eth-api/libraries/web3js/#setup-web3-with-moonbeam

2.如何获取moonbeam dev node中的公私钥,参考下面链接

https://docs.moonbeam.network/builders/get-started/networks/moonbeam-dev/