如何使用ethers.js从智能合约功能中获取返回的数据?
我正在尝试使用ethers.js从智能合约中使用功能。该功能在登录之前(在其他功能的帮助下)检索用户的信息。这是功能片段。
function getUser(address _userAddress)
public
onlyAuthCaller
returns (
string memory name,
string memory info,
string memory role,
)
{
User memory tmpData = userDetails[_userAddress];
return (
tmpData.name,
tmpData.info,
tmpData.role
);
}
使用React,我正在渲染一个按钮以获取用户信息,如下所示:
const GetUser = () => {
const askUser = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const account = await window.ethereum.request({
method: "eth_requestAccounts",
});
const signer = provider.getSigner();
const erc20 = new ethers.Contract(
ContractAddress,
ContractABI.abi,
signer
);
try {
const user = await erc20.getUser(account[0]);
console.log(user);
} catch (error) {
console.log("ERROR AT GETTING USER: ", error);
}
};
return (
<div>
<Button type="submit" variant="contained" onClick={askUser}>
GET USER
</Button>
</div>
);
};
我想知道为什么我不获得智能合约的返回结果getuser
函数,我希望该信息在>等待功能后,const用户
。而是在const user
上,我的交易元数据如下:
{hash: '0x24818569ec29d328b66f58736750a420a5a3bd8e28a72a6a0f72fd8ba5e088d8', type: 2, accessList: null, blockHash: null, blockNumber: null, …}
accessList: null
blockHash: null
blockNumber: null
chainId: 0
confirmations: 0
creates: null
data: "0x6f77926b00000000000000000000000086b2b772014a87730928c7e54f4762d2c09ea4e5"
from: "0x86b2b772014A87730928c7e54F4762d2c09eA4e5"
gasLimit: BigNumber {_hex: '0xd15f', _isBigNumber: true}
gasPrice: BigNumber {_hex: '0x73a20d0c', _isBigNumber: true}
hash: "0x24818569ec29d328b66f58736750a420a5a3bd8e28a72a6a0f72fd8ba5e088d8"
maxFeePerGas: BigNumber {_hex: '0x73a20d0c', _isBigNumber: true}
maxPriorityFeePerGas: BigNumber {_hex: '0x73a20d00', _isBigNumber: true}
nonce: 5
r: "0x6a8fed76397e03a2fc564d18e1ec12abdf39a38fbe825df990f744bb50fc4a8b"
s: "0x66e9b4513047b65aac724dc6fb07d069967f6ca6fd8cd5fe85f6dbe495864765"
to: "0x9719E9dC77A7eDD3825844c77a68c896d4a7BB2b"
transactionIndex: null
type: 2
v: 0
value: BigNumber {_hex: '0x00', _isBigNumber: true}
wait: confirmations => {…}
length: 1
name: ""
arguments: (…)
caller: (…)
[[FunctionLocation]]: index.ts:336
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[4]
[[Prototype]]: Object
当我在混合iDE上尝试合同的功能时,所有这些功能都按预期工作。例如,在混音中,我得到了此答案,其中该函数检索到的数据是在解码的输出
上。
status true Transaction mined and execution succeed
transaction hash 0x206af46a0f8e6bcc04ae632c85da005c901d8fc82f650e8d40a445f6988adcc2
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to SupplychainUser.getUser(address) 0xD7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B
gas 61639 gas
transaction cost 53599 gas
execution cost 53599 gas
input 0x6f7...35cb2
decoded input {
"address _userAddress": "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2"
}
decoded output {
"0": "string: name Carl Bertz",
"1": "string: info 0987654321",
"2": "string: role processor",
}
logs []
val 0 wei
我也希望这样做,但是使用React,那么如何从合同Getuser
函数中获得返回的数据?
I'm trying to consume a function from a smart contract using ethers.js. The function retrieve the info of a user logged before (with the help of other function). This is the function snippet.
function getUser(address _userAddress)
public
onlyAuthCaller
returns (
string memory name,
string memory info,
string memory role,
)
{
User memory tmpData = userDetails[_userAddress];
return (
tmpData.name,
tmpData.info,
tmpData.role
);
}
With React, I'm rendering a button to get user info, as follow:
const GetUser = () => {
const askUser = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const account = await window.ethereum.request({
method: "eth_requestAccounts",
});
const signer = provider.getSigner();
const erc20 = new ethers.Contract(
ContractAddress,
ContractABI.abi,
signer
);
try {
const user = await erc20.getUser(account[0]);
console.log(user);
} catch (error) {
console.log("ERROR AT GETTING USER: ", error);
}
};
return (
<div>
<Button type="submit" variant="contained" onClick={askUser}>
GET USER
</Button>
</div>
);
};
I wonder why I'm not getting the return result of the smart contract getUser
function, I expected that info at const user
after awaiting the function. Instead on const user
, I'm having the transaction metadata, as follow:
{hash: '0x24818569ec29d328b66f58736750a420a5a3bd8e28a72a6a0f72fd8ba5e088d8', type: 2, accessList: null, blockHash: null, blockNumber: null, …}
accessList: null
blockHash: null
blockNumber: null
chainId: 0
confirmations: 0
creates: null
data: "0x6f77926b00000000000000000000000086b2b772014a87730928c7e54f4762d2c09ea4e5"
from: "0x86b2b772014A87730928c7e54F4762d2c09eA4e5"
gasLimit: BigNumber {_hex: '0xd15f', _isBigNumber: true}
gasPrice: BigNumber {_hex: '0x73a20d0c', _isBigNumber: true}
hash: "0x24818569ec29d328b66f58736750a420a5a3bd8e28a72a6a0f72fd8ba5e088d8"
maxFeePerGas: BigNumber {_hex: '0x73a20d0c', _isBigNumber: true}
maxPriorityFeePerGas: BigNumber {_hex: '0x73a20d00', _isBigNumber: true}
nonce: 5
r: "0x6a8fed76397e03a2fc564d18e1ec12abdf39a38fbe825df990f744bb50fc4a8b"
s: "0x66e9b4513047b65aac724dc6fb07d069967f6ca6fd8cd5fe85f6dbe495864765"
to: "0x9719E9dC77A7eDD3825844c77a68c896d4a7BB2b"
transactionIndex: null
type: 2
v: 0
value: BigNumber {_hex: '0x00', _isBigNumber: true}
wait: confirmations => {…}
length: 1
name: ""
arguments: (…)
caller: (…)
[[FunctionLocation]]: index.ts:336
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[4]
[[Prototype]]: Object
When I tried my contract's functions on Remix IDE, all worked as expected. For instance, at Remix I get this answer, in which the data retrieved by the function is on decoded output
.
status true Transaction mined and execution succeed
transaction hash 0x206af46a0f8e6bcc04ae632c85da005c901d8fc82f650e8d40a445f6988adcc2
from 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
to SupplychainUser.getUser(address) 0xD7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B
gas 61639 gas
transaction cost 53599 gas
execution cost 53599 gas
input 0x6f7...35cb2
decoded input {
"address _userAddress": "0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2"
}
decoded output {
"0": "string: name Carl Bertz",
"1": "string: info 0987654321",
"2": "string: role processor",
}
logs []
val 0 wei
I would like the same but with React, so how can I have the returned data from the contract getUser
function?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
调用
getuser
时,您要获得事务元数据的原因是因为getuser
函数不是view> view
函数。不是
view
函数会导致区块链为该特定功能调用创建交易,该函数必须由区块链验证,并且在执行GetUser
的那一刻不可用。功能。对于这种情况,推荐的方法是使用事件,即发出事件,其中包含您需要的信息,然后在React方面聆听该事件。
考虑使
getuser
函数<代码>视图函数,因为它不会更改合同的状态:The reason you are getting the transaction metadata when calling
getUser
is because thegetUser
function is not aview
function.Not being a
view
function causes the blockchain to create a transaction for that specific function call which has to be validated by the blockchain and is not available at the moment you execute yourgetUser
function.For that type of situation, the recommended approach is to use events i.e. emitting an event with the information you need and, on the react side, listen for the event.
Consider making the
getUser
function aview
function, as it does not change the state of the contract:您想在合同上使用呼叫线,类似于
您
call
该功能,而不是运行send
执行交易(成本化的气体)you want to be using callStatic on your contract, something like
so that you
call
the function, instead of running asend
which executes the transaction (costing gas)这是在其中一条评论中回答一个问题:EVM支持几种“呼叫”,您可以在此处的Yul文档中看到这些问题( https://docs.solitylanditylang.org/en/latest/yul.html.html#evm-dialect )。静态呼叫告诉EVM期望不会运行状态变化的说明(即,将呼叫强制为“视图”函数)。其他呼叫类型与其他类型的呼叫相关(例如,delegatecall()是支持代理的核心)。
This is to answer a question in one of the comments: The EVM supports several kinds of "calls", which you can see in the Yul documentation here (https://docs.soliditylang.org/en/latest/yul.html#evm-dialect). A static call tells the EVM to expect no state changing instructions will be run (i.e., to enforce a call into a "view" function). The other call types are relevant to other types of calls (e.g., delegatecall() is at the core of supporting proxies).