如何调用重载方法

web3.js调用

call调用重载方法查数据

const web3 = new Web3('https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161')const contract = new web3.eth.Contract(ContractAbi,ContractAddress)const rewardsBalance = await contract.methods['f(uint256,address)'](1,"0x0000000000000000000000000000000000000000").call()console.log('rewardsBalance', rewardsBalance)

send调用重载方法写数据

const web3 = new Web3(library?.provider || 'https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161')const contract = new web3.eth.Contract(ContractAbi,ContractAddress)const rewardsBalance = await contract.methods['claimRewards(uint256)'](1).send({from: account})

ethers.js调用

const {library, account, chainId} = useWeb3React()const staticJsonRpcProvider = new ethers.providers.StaticJsonRpcProvider('https://mainnet.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161')let contract = new ethers.Contract(ContractAddress,ContractAbi,library?.getSigner() ?? staticJsonRpcProvider);console.log(contract)const rewardsBalance = await contract['f(uint256,address)'](1,"0x0000000000000000000000000000000000000000")console.log('rewardsBalance', rewardsBalance.toString())

@chainstarter/multicall-client.js调用

  • 这款是自主研发的支持高并发multicall库

查数据

import {config, Contract as ClientContract, multicallClientSend, multicallClient, ChainId, getWeb3} from "@chainstarter/multicall-client.js";const contract = new ClientContract(ContractAbi, ContractAddress, ChainId.ETH)const call = contract.getRewardsBalance('0x0000000000000000000000000000000000000000')const call2 = contract['getRewardsBalance(address,uint256)']('0x0000000000000000000000000000000000000000', 1)multicallClient([call,call2,contract.governor()]).then(res => {console.log('res', res)})

写数据

import {config, Contract as ClientContract, multicallClientSend, multicallClient, ChainId, getWeb3} from "@chainstarter/multicall-client.js";const contract = new ClientContract(ContractAbi, ContractAddress, ChainId.ETH)const send1 = contract['claimRewards(uint256)'](1)multicallClientSend([send1], window.ethereum).send({from: account}).on('transactionHash', (hash) => { }).on('receipt', (rec) => {}).on('error', (err) => {})

关于solidity函数重载

一个合约可以有多个同名但参数类型不同的函数。这个过程称为“重载”,也适用于继承的函数。下面的例子展示 f了合约范围内函数的重载A

pragma solidity >=0.4.16 <0.9.0;contract A {function f(uint value) public pure returns (uint out) {out = value;}function f(uint value, bool really) public pure returns (uint out) {if (really)out = value;}}

外部接口中也存在重载函数。如果两个外部可见函数的不同在于它们的 Solidity 类型而不是它们的外部类型,这是一个错误。

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;// This will not compilecontract A {function f(B value) public pure returns (B out) {out = value;}function f(address value) public pure returns (address out) {out = value;}}contract B {}

上面的两个f函数重载最终都接受了 ABI 的地址类型,尽管它们在 Solidity 中被认为是不同的。

重载解析和参数匹配

通过将当前作用域中的函数声明与函数调用中提供的参数匹配来选择重载函数。如果所有参数都可以隐式转换为预期类型,则选择函数作为重载候选者。如果不完全是一个候选人,则决议失败。

  • 重载解析不考虑返回参数。
// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;contract A {function f(uint8 val) public pure returns (uint8 out) {out = val;}function f(uint256 val) public pure returns (uint256 out) {out = val;}}

调用f(50)会产生类型错误,因为50可以隐式转换为uint8uint256类型。另一方面f(256)将解决f(uint256)重载,因为256不能隐式转换为uint8.

在 solidity 的 0.6.0 版本之后:

  • 重写函数或修饰符时,必须使用新关键字 override
    • 接口会自动作为 virtual,在接口外部没有实现的函数必须标记为 virtual 。
  • 仅当函数被标记为 virtual 或在接口中定义时,才可以重写。
  • private 的函数是不可以标记为 virtual 的。
  • 对于单继承,请在每个重写函数中添加 override 。
  • 对于多继承,添加 override(A, B, …),在括号中列出所有覆盖函数的合约。

关于函数重载,详见官方文档:https://docs.soliditylang.org/en/v0.8.14/contracts.html#function-overloading