您现在的位置是:首页 >技术杂谈 >【区块链】走进web3的世界-合约交互中的异常/边界处理网站首页技术杂谈

【区块链】走进web3的世界-合约交互中的异常/边界处理

兵腾傲宇 2023-05-14 00:00:02
简介【区块链】走进web3的世界-合约交互中的异常/边界处理

在以太坊智能合约中,异常处理是一个非常重要的问题,因为任何一个函数调用都有可能导致异常。常见的异常包括函数调用失败、无效参数、内部错误等。

        在 Solidity 中,可以使用 require、assert 和 revert 等关键字来处理异常。这些关键字可以用于检查输入参数、状态变量和函数调用的返回值,并在发生异常时抛出异常。

        今天我们主要从前端的角度来进行异常处理,这样可以保证我们交互的正常进行。

1、工程目录划分,更好的管理我们web3脚本

    

让我们的代码更加清晰明了

  • web3中与智能合约交互使用的是ABI,他是我们和智能合约交互的通道,可以将ABI通过命名统一管理,方便后续维护;
  • 在与智能合约交互的过程中,需要调用ABI的接口,以及通过web3.js/ethers.js等web3的一些库进行钱包连接,获取地址等操作,可以将其放入web3的文件夹中进行统一管理。

ABI(Application Binary Interface)是一种接口规范,用于描述不同模块之间的通信方式和数据格式。在以太坊智能合约中,ABI 用于描述智能合约的接口,包括合约地址、函数名、函数参数和返回值等。

2、前端在合约交互中的异常处理

在web3的脚本中,我们需要通过try{} catch {}将异常抛出,常见的异常情况包含:

  • 钱包连接异常;
  • 区块链交互付费过程中拒绝支付;
  • rpc不对,交互异常;
  • 调用合约报错(不存在方法、传参不对等);
  • 还有很多很多......

3、以下是一些常见的异常处理方式

3.1、try{} catch {}捕获抛出异常


/**
  * 域名是否可注册
  * @param domainName domainName without .bnb
  * @returns boolean, if no error
  */
 static async isDomainAvailable(domainName: String): Promise<any> {
    try {
        const isAvailable = await BnbDomainUtils.registrarControllerContractReadOnly.available(domainName)
        return isAvailable
    } catch (error) {
        console.log(error);
        return false
    }
}

3.2、检查交易是否成功

        在向智能合约发送交易时,需要检查交易是否成功。可以使用 Web3.js 提供的 send 方法,该方法会返回一个 Promise 对象,可以在 then 方法中获取交易的哈希值,并在 catch 方法中处理异常。


myContract.methods.myFunction().send({ from: myAddress })
  .then((receipt) => {
    // 处理交易成功的情况
  })
  .catch((error) => {
    // 处理交易失败的情况
  });

3.3、捕获智能合约函数调用异常

        在调用智能合约的函数时,可能会出现异常,例如传入的参数无效、状态不满足要求等。可以使用 Web3.js 提供的 call 方法,该方法会返回一个 Promise 对象,可以在 then 方法中获取函数的返回值,并在 catch 方法中处理异常。


myContract.methods.myFunction(myArg).call()
  .then((result) => {
    // 处理函数调用成功的情况
  })
  .catch((error) => {
    // 处理函数调用失败的情况
  });

3.4、处理 MetaMask 异常

        在使用 MetaMask 与智能合约交互时,可能会出现用户未授权、交易被拒绝等异常。可以使用 MetaMask 提供的 ethereum 对象,该对象包含了与钱包交互的 API。


if (window.ethereum) {
  try {
    await window.ethereum.enable();
    // 处理用户已授权的情况
  } catch (error) {
    // 处理用户未授权的情况
  }
} else {
  // 处理用户未安装 MetaMask 的情况
}

3.5、使用事件监听器

        在智能合约中,可以使用事件来通知前端某些状态的变化。可以在智能合约中定义事件,然后在前端使用 Web3.js 监听事件的触发。

        通过使用事件监听器,前端可以实时获取智能合约的状态变化,从而更加及时地处理异常情况。


// Solidity 中定义事件
event Transfer(address indexed from, address indexed to, uint256 value);

// 前端中监听事件
myContract.events.Transfer()
  .on('data', (event) => {
    // 处理事件触发的情况
  })
  .on('error', (error) => {
    // 处理事件监听失败的情况
  });

3.6、限制交易的 gas 量

        在向智能合约发送交易时,可以指定交易的 gas 量。如果 gas 不足,交易会失败,并回滚交易。可以在前端限制交易的 gas 量,从而确保交易能够成功执行。

        通过限制交易的 gas 量,前端可以避免交易失败的情况。


const gasLimit = 250000;
myContract.methods.myFunction().send({ from: myAddress, gas: gasLimit })
  .then((receipt) => {
    // 处理交易成功的情况
  })
  .catch((error) => {
    // 处理交易失败的情况
  });

3.7、处理网络异常

        在与智能合约交互时,可能会遇到网络异常,例如网络延迟、断开等。可以在前端使用 Web3.js 提供的 setProvider 方法设置网络 provider,从而确保交互的稳定性。

        通过设置网络 provider,前端可以避免网络异常的情况。


// 1、使用web3
const provider = new Web3.providers.HttpProvider('https://ropsten.infura.io/v3/YOUR-PROJECT-ID');
const web3 = new Web3(provider);

// 2、使用ethers
const provider = new ethers.providers.JsonRpcProvider(process.env.READ_ONLY_RPC)
new ethers.Contract(
    contractAddress,
    Abi,
    provider
)

总之,在与智能合约交互时,需要仔细处理异常,以保证交易的正确性和可靠性。可以使用 Web3.js 和 MetaMask 提供的 API 来处理异常。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。