Prefacio
Como se mencionó la última vez, Remix
es inconveniente depurar en línea. En este artículo, configuraremos una implementación de entorno localizado, utilizaremos el contrato inteligente y los escenarios de uso del artículo anterior y configuraremos el entorno de desarrollo a partir de Truffle
y .Ganache
Trufa
tuffle
Es un entorno de desarrollo de contratos inteligentes localizado, un marco de pruebas y una herramienta en cadena basado en la máquina virtual Ethereum (EVM).
https://trufflesuite.com/truffle/
Para que sea aplicable tanto a linux
los sistemas operativos Windows
como mac
a, aquí usamos el modo de línea de comando para compilarlo.
Primero instale el entorno nodejs
, descargue el paquete de instalación del sitio web oficial (u obtenga todos los paquetes de instalación sin conexión mencionados al final del artículo) y elija la versión estable.16.12.2 LTS
# https://nodejs.org/en/
node -v # 确认node安装完毕
Instalación globalTruffle
npm install truffle -g
Inicializar hilo
Sería más conveniente utilizarlo yarn
para gestionar proyectos.npm
npm install yarn -g
construir proyecto
yarn init
Inicializartrufa
Cree un directorio, por ejemplo main_contract
,
truffle init
Instalar openzeppelin
yarn add @openzeppelin/contracts
Código VS
Primero copie el contrato inteligente escrito en el artículo anterior en contracts
el directorio, vscode
ábralo con y verá la estructura de directorio de un proyecto de contrato inteligente típico.
contracts
El directorio contiene el solidity
contrato inteligente, migrations
el directorio contiene archivos de implementación, node_modules
el directorio contiene archivos de biblioteca dependientes y test
el directorio contiene archivos de prueba.
ganache
Truffle
Su función principal es solidity
compilar el código fuente en EVM
un archivo ejecutable que se puede ejecutar en él, mientras Ganache
simula la cadena de prueba y proporciona un entorno blockchain localizado para implementar contratos.
InstalarGanache
Aquí puede elegir la versión 6.12 o la última versión 7.0. La nueva versión ha agregado algunas características nuevas. Puede ver las diferencias específicas aquí.
https://trufflesuite.com/blog/introducing-ganache-7/
npm install ganache-cli -g # 6.12
npm install ganache -g # 7.0
Cadena de bloques localizada
Este uso allowUnlimitedContractSize
ignora el tamaño del contrato implementado requerido y continúa ganache
ejecutándose en segundo plano.
ganache-cli -d --allowUnlimitedContractSize
Se generaron 10 billeteras de prueba y el servicio se ejecutó en el puerto 8545. Aquí puede hacer una copia de seguridad de la dirección de la billetera, la clave privada y la frase mnemotécnica.
Vincularse a la billetera Metamask
Primero agregue Ganache
la red, complete RPC URL
como http://127.0.0.1:8545
, 链ID
para1337
Luego importe las 10 billeteras generadas previamente (con copia de seguridad previa) a través de la clave privada.
Si todo va bien, podrás ver los 100 ETH en cada cuenta. (Recuerde encender la red Ganache
)
Contrato de implementación
Archivo de configuración
Modifique el archivo de configuración truffle-config.js
, la configuración de red y confirme ip
que el número de puerto sea consistente con el anterior ganache
.
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},
Compilar la configuración, agregar src
directorio, habilitar el optimizador, agregarcontracts_build_directory
// Configure your compilers
contracts_build_directory: "./src/contracts/",
compilers: {
solc: {
version: "0.8.11", // Fetch exact version from solc-bin (default: truffle's version)
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
settings: { // See the solidity docs for advice about optimization and evmVersion
optimizer: {
enabled: true,
runs: 200
},
// evmVersion: "byzantium"
}
}
},
compilar contrato
truffle
contracts
Los contratos en el directorio se compilarán automáticamente y se enviarán al src/contracts/
directorio de acuerdo con la configuración.
truffle compile
Implementar el contrato principal
En migrations
el directorio, haga referencia 1_initial_migration.js
, cree 2_initial_maintoken.js
.
Pase 3 parámetros de inicialización y la emisión total se fija en 21 millones.
const MainToken = artifacts.require("MainToken");
const SubToken = artifacts.require("SubToken");
module.exports = function (deployer) {
deployer.deploy(MainToken, "Bluishfish", "BLF", 21000000).then(() =>{
deployer.deploy(SubToken, MainToken.address)
});
};
Ejecute todas las migraciones desde cero y ejecute los archivos de migración para implementar el contrato.
truffle migrate --reset
Primero use la billetera con el número 0 para MainToken
implementar el contrato principal en la red y luego implementar el subcontrato una vez completado SubToken
.
En consecuencia, Ganache
se puede ver información interactiva en.
Registre la dirección principal del contrato contract address
como 0x9561c133dd8580860b6b7e504bc5aa500f0f06a7
.
Implementar subcontrato
Al implementar el contrato principal antes, puede implementar los subcontratos juntos (lo que puede ahorrar costos de gas). Sin embargo, en la mayoría de los casos, a medida que se desarrolla el negocio, los subcontratos se implementarán más tarde que el contrato principal. En este caso , debe implementar los subcontratos por separado.
Crear 3_initial_subtoken.js
, completar la dirección principal del contrato con parámetros
const SubToken = artifacts.require("SubToken");
module.exports = function (deployer) {
deployer.deploy(SubToken, "0x9561c133dd8580860b6b7e504bc5aa500f0f06a7");
};
Especificar el despliegue del contrato No. 3 (subcontrato)
truffle migrate --f 3
Contrato de prueba
Introducir contrato
Crea un nuevo archivo en test
el directorio.Token.test.js
const MainToken = artifacts.require("./MainToken");
const SubToken = artifacts.require("./SubToken");
Escribir contrato de prueba
Los parámetros predeterminados se pasarán a Ganache
las 10 cuentas de prueba creadas. Generalmente, la primera cuenta se utiliza como implementador del contrato. Si se requieren varias cuentas para interactuar, se pueden nombrar propietario1, propietario2...
contract("TestToken", ([deployer, owner1, owner2]) => {
console.log('deployer: ', deployer);
console.log('owner1: ', owner1);
console.log('owner2: ', owner2);
...
}
El entorno de prueba está completamente aislado del entorno de implementación, por lo que cada caso de prueba necesita volver a implementar el contrato, lo que beforeEach
se puede lograr fácilmente con .
beforeEach(async () => {
main_instance = await MainToken.new("Bluishfish","BLF", 21000000);
sub_instance = await SubToken.new(main_instance.address);
})
Probar la implementación del contrato principal
Se utiliza parait
escribir casos de prueba para probar el alias del contrato principal y la cantidad total del token.
it("测试主合约初始化", async()=>{
// console.log('主合约地址: ', main_instance.address)
const name = await main_instance.name();
assert.equal(name, "Bluishfish");
const symbol = await main_instance.symbol();
assert.equal(symbol, "BLF");
const totalSupply = await main_instance.totalSupply();
assert.equal(totalSupply, web3.utils.toWei('21000000', 'ether'));
})
Implementación de subcontrato de prueba
_mainAddress
Aquí cambiamos el subcontrato public
para que sea más fácil verificar la propiedad del contrato.
it("测试子合约初始化", async()=>{
// console.log('子合约地址: ', sub_instance.address)
const main_address = await sub_instance._mainAddress();
assert.equal(main_instance.address, main_address);
})
Función de transferencia de prueba
La función de transferencia sigue el diagrama de flujo anterior:
Primero, se encuentra una cantidad total fija de tokens en el contrato principal, y se extraen previamente 21 millones de tokens para la billetera principal (billetera del propietario del contrato);
La billetera principal asigna una cantidad inicial de fondos al subcontrato;
El subcontrato utiliza el token del contrato principal para realizar negocios específicos;
Una vez que el subcontrato complete su actividad, los tokens restantes se devolverán al contrato principal;
El contrato principal se retira a la billetera principal.
Transferir dinero de la billetera principal al subcontrato
Transfiera 10,000 tokens de la billetera principal al subcontrato. Esto se utiliza toWei
para calcular la precisión y evitar demasiados ceros en el código.
beforeEach(async () => {
// 主钱包转账给子合约
const result = await main_instance.transfer(
sub_instance.address,
web3.utils.toWei('10000', 'ether'),
{ from: deployer });
assert.equal(result.receipt.status, true);
})
it("测试主钱包转账给子合约", async()=>{
// 查询子合约是否到账 10000 代币
const balance = await main_instance.balanceOf(sub_instance.address);
assert.equal(balance.toString(), web3.utils.toWei('10000', 'ether'));
});
El subcontrato devuelve los tokens al contrato principal.
Transfiera 5000 tokens del subcontrato, devuélvalos al contrato principal y luego verifique el saldo de la cuenta.
it("测试子合约归还代币给主合约", async()=>{
// 子合约转 5000 代币到主合约
const result = await sub_instance.transferWithToken(
web3.utils.toWei('5000', 'ether'), { from: deployer });
assert.equal(result.receipt.status, true);
// 查询子合约余额
const balance = await main_instance.balanceOf(sub_instance.address);
assert.equal(balance.toString(), web3.utils.toWei('5000', 'ether'));
});
Retirar del contrato principal a la billetera principal
Primero transfiera 10,000 tokens del subcontrato al contrato principal, luego retire dinero del contrato principal a la billetera principal y verifique si el saldo en cada cuenta es correcto.
it("测试主合约提现到主钱包", async()=>{
// 转子合约 10000 代币到主合约
const result = await sub_instance.transferWithToken(
web3.utils.toWei('10000', 'ether'), { from: deployer });
assert.equal(result.receipt.status, true);
// 查询子合约余额是否为 0
var balance = await main_instance.balanceOf(sub_instance.address);
assert.equal(balance.toString(), '0');
// 提现到主钱包
await main_instance.withdraw({ from: deployer });
// 查询主合约余额是否为 0
balance = await main_instance.balanceOf(main_instance.address);
assert.equal(balance.toString(), '0');
// 查询主钱包余额是否为 2100万
balance = await main_instance.balanceOf(deployer);
assert.equal(balance.toString(), web3.utils.toWei('21000000', 'ether'));
});
prueba completa
Después de que todo esté listo, ingrese en la línea de comando
truffle test
Aquí solo se muestran algunos casos de prueba para funciones normales. En proyectos reales, es necesario agregar más casos de error para lograr una cobertura completa de la ruta y verificar completamente varias situaciones inesperadas. Afortunadamente, un caso de uso se puede utilizar varias veces y las llamadas simples posteriores truffle test
pueden completar la prueba, lo cual es particularmente útil al actualizar y actualizar nuevos contratos.
geth
También podemos geth
usarlo construir un nodo Ethereum completo. Dado que el libro de contabilidad histórico debe sincronizarse, la cantidad de datos a descargar es relativamente grande. Si está interesado, puede configurarlo según el siguiente enlace.
https://github.com/ethereum/go-ethereum
gordo
Para implementar en la cadena principal, además de geth
construirla usted mismo, también puede utilizar un método más simple infura
.
Infura
La suite proporciona acceso instantáneo API
a Ethereum y IPFS
a la red Ethereum . Al usarlo , puede conectarse fácilmente sin tener que iniciar y mantener su propia infraestructura. Su servicio principal es gratuito y puede crear 3 proyectos con hasta 100.000 solicitudes por día.HTTPS
WebSocket
Infura
Web 3.0
https://infura.io/
Registrar una cuenta
Primero debe registrar una cuenta en el sitio web oficial, crear un nuevo proyecto, seleccionar la cadena Ethereum y dar un nombre al proyecto.
Autentíquese utilizando su PROJECT ID
clave y copie de forma segura su clave y elija la adecuada .ROJECT SECRET
ENDPOINTS
Instalar HDWalletProvider
Por razones de seguridad, Infura
sus claves privadas no se administran, lo que significa que Infura
las transacciones no se pueden firmar en su nombre. Sin embargo, las firmas de transacciones y las conexiones a la red Ethereum Truffle
se pueden manejar mediante el uso .HDWalletProvider
yarn add @truffle/hdwallet-provider
Windows
Si la instalación falla, puede intentar instalar las herramientas de compilación a continuación npm install -g windows-build-tools
.
Configurar el proyecto Truffle
Editar truffle-config.js
e importar archivos de biblioteca
const HDWalletProvider = require("@truffle/hdwallet-provider");
Configure la frase mnemotécnica, recuerde usar una pequeña cantidad de billetera de desarrollador y ¡no la filtre! Se recomienda almacenarlo en un archivo y configurarlo gitignore
para excluir archivos clave.
// const mnemonic = "在metamask/设置/安全与隐私/显示账户助记词";
const fs = require('fs');
const mnemonic = fs.readFileSync(".secret").toString().trim();
Agregue una Ropsten
definición de red y completeINFURA_PROJECT_ID
module.exports = {
networks: {
ropsten: {
provider: function() {
return new HDWalletProvider(mnemonic, "https://ropsten.infura.io/v3/<INFURA_PROJECT_ID>")
},
network_id: 3
}
}
};
Contrato de implementación
Seleccione la red de prueba, que de forma predeterminada es la primera cuenta de la billetera. Solo asegúrese de que haya monedas de prueba en ella.
truffle migrate --network ropsten
Ganache 7.0
Si es el caso anterior, también se puede fork.url
utilizar para infura
.
ganache --fork.url wss://ropsten.infura.io/ws/v3/<INFURA_PROJECT_ID>
Comparando la diferencia de velocidad Ganache CLI v6.12.2
entre y ganache v7.0.1
, aunque no llega a 30 veces, sí es mucho más rápida.
Descarga del código fuente
Puede encontrar información y documentos relevantes para este problema en la cuenta pública "Deep Awakening" y responda: "chain02" en segundo plano para obtener el enlace de descarga.
Vista previa del artículo siguiente
Este artículo presenta principalmente el desarrollo local de aplicaciones blockchain, las herramientas de soporte utilizadas en el backend y los métodos de prueba. A continuación, configuraremos react
para escribir el front-end y usaremos web3
la conexión metamask
para acceder al contrato inteligente implementado.