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