我在 Matic Mumbai 测试网上部署了一个智能合约,我正在尝试使用 Web3 从 React Web 应用程序与其交互。我的智能合约中有一个名为 buySucc
(多肉植物的缩写)的应付函数。当我使用 Web3 从我的 React Web 应用程序调用该函数时,MetaMask 会弹出我能够确认的交易。之后,我在元掩码中看到一个待处理的发送交易和一个排队的合约交互。几秒钟后,我在前端得到 Error: Receipt missing or blockHash null
,合约交互在 MetaMask 中永远排队。
我还使用 ganache-cli 将智能合约部署到了孟买测试网的本地分支。使用本质上相同的函数调用运行一个简单的 Node.js 脚本可以完美运行,这让我感到非常困惑。
在查看 https://ethereum.stackexchange.com/questions/43691/metamask-issue-with-payable-transactions-using-truffle-and-web3 后,我尝试将 gas 限制提高到 2000000,但这没有用。
这是我的代码:
智能合约:SuccOwnership.sol
...
function _createSucc(
uint256 _parent1Id,
uint256 _parent2Id,
uint256 _genes,
address _owner
) internal returns (uint256) {
uint256 watersNeededIndex = 0;
if (_parent1Id != 0) {
watersNeededIndex = succs[_parent1Id].watersNeededIndex / 2;
} else if (_parent2Id != 0) {
watersNeededIndex = succs[_parent2Id].watersNeededIndex / 2;
}
succs.push(
Succ(
_genes,
uint64(block.timestamp),
0,
0,
uint8(watersNeededIndex),
false
)
);
uint256 _newSuccIndex = succs.length - 1;
_safeMint(_owner, _newSuccIndex);
emit newSucc(_owner, _newSuccIndex, _parent1Id, _parent2Id, _genes);
return _newSuccIndex;
// return 0;
}
function buySucc(uint256 _genes, uint256 _price)
external
payable
returns (uint256)
{
require(msg.value == _price, "Wrong price paid for succulent");
return _createSucc(0, 0, _genes, msg.sender);
}
...
(作为旁注,我知道价格是外部 buySucc
函数的参数并不安全和奇怪,但我还没有开始实施价格确定:'))< br/>
App.js:
import {
getAccount,
getSuccContract,
buySucc,
getPotContract,
getPotAdmin,
getSuccIds,
} from './backend/backend.js'
/* more imports */
export default function App() {
const web3 = new Web3(Web3.givenProvider || "https://rpc-mumbai.matic.today/")
const default_plants = new Array(12).fill(null);
const [plants, setPlants] = useState(default_plants);
const [pots, setPots] = useState();
const [account, setAccount] = useState();
const [succContract, setSuccContract] = useState();
async function setupBlockchain() {
const account = await getAccount(web3)
setAccount(account);
const succContract = await getSuccContract(web3);
setSuccContract(succContract);
const potContract = await getPotContract(web3);
const admin = await getPotAdmin(potContract);
console.log(admin)
}
//Works
async function getPlants() {
if(!account || !succContract) {
console.log('connect account first')
}
const plantIds = await getSuccIds(web3, account, succContract);
console.log(plantIds)
}
//Doesn't work
async function buyPlant() {
if(!account || !succContract) {
console.log('connect account first')
}
buySucc(web3, succContract, account, 0, 0)
}
return (...);
后端.js:
import {
SUCC_OWNERSHIP_ADDRESS,
SUCC_OWNERSHIP_ABI,
POT_OWNERSHIP_ADDRESS,
POT_OWNERSHIP_ABI
} from "../config.js"
export async function getAccount(web3) {
const accounts = await web3.eth.getAccounts();
return accounts[0];
}
export async function getSuccContract(web3) {
return new web3.eth.Contract(SUCC_OWNERSHIP_ABI, SUCC_OWNERSHIP_ADDRESS);
}
//This works
export async function getSuccIds(web3, account, contract) {
const succIds = await contract.methods.succsOfOwner(account).call();
return succIds
}
//This doesn't work
export async function buySucc(web3, contract, account, dna, price) {
const newSucc = await contract.methods.buySucc(0, web3.utils.toWei('1')).send({
from: account,
value: web3.utils.toWei('1')
});
return newSucc
}
具有排队合约交互的 MetaMask 屏幕截图