从 Web.js 连接到 Solidity 合约时地址无效
Posted
技术标签:
【中文标题】从 Web.js 连接到 Solidity 合约时地址无效【英文标题】:invalid address when connecting to Solidity contract from Web.js 【发布时间】:2019-12-21 16:00:03 【问题描述】:** 根据评论更新
当与合约交互并直接使用'合约地址:'直接从松露迁移输出的输出调用函数时,错误也是无效地址。
-
Solidity 合约和 web3.js 的新手——(尽管我已经尝试让它工作好几个星期了!!)
我正在使用 react.js、truffle-contract 和 web3 创建一个 Dapp 并从 Ganache 连接到我的智能合约。我也在通过 webpack 管理我的应用程序。
我已经用 Solidity 编写了一个简单的合约(版本如下) - 并且可以从 truffle 控制台毫无问题地连接到合约。
当通过一个简单的(用于此演示的)enroll() 函数连接到合约时,我收到了一个 Error: invalid address
我现在已经以多种方式重写了代码,无论如何总是会收到相同的错误。
在这里查看了很多帖子后,我了解到这样做时一个相当常见的问题是我需要设置“默认值”——当我在 componentDidMount 函数中第一次连接到 web3 时,我已经这样做了通过 contract.defaults 函数连接到合约时也是如此。到目前为止,这也没有什么不同。
任何关于我在这里做错的想法将不胜感激!
相关版本如下
"web3": "^1.2.1", "webpack": "^4.20.2", “反应”:“^16.2.0”,
"truffle-contract": "^3.0.4",
"solc": "0.4.18",
下面是尝试连接合约的页面
componentDidMount = () =>
if(this.state.web3MetaON == false && this.state.accUnlock == false)
if (typeof web3 != 'undefined')
this.web3Provider = web3.currentProvider
web3 = new Web3(web3.currentProvider)
this.setState(web3MetaON: true)
const accountID = web3.eth.accounts[0];
web3.eth.defaultAccount = accountID;
console.log('Window opening in older browser')
// check if accountID is available
if(accountID !== null || accountID !== undefined)
this.setState(accUnlock: true)
this.setState(account: accountID)
this.loadDataContract(accountID)
else
console.log('Error on accessing account')
this.setState(accUnlock: false)
else
window.alert("Please connect to Metamask.")
this.setState(web3MetaON: false)
// ::TO-DO method to invoke retry after 2 seconds
// Below loads web3 and sets state if browser
// is and a modern ethereum browser
else if (window.ethereum && this.state.web3MetaON == false && this.state.accUnlock == false)
window.web3 = new Web3(ethereum)
try
// Request account access if needed
const accountID = ethereum.enable()
web3.eth.sendTransaction(/* ... */)
// setting state to accountID
this.setState(account: accountID)
this.setState(accUnlock: true)
console.log('Window opening in modern browser')
catch (error)
console.log(error, 'Modern Browser failed')
this.setState(web3MetaON: false)
console.log('Non-Ethereum browser detected. You should consider trying MetaMask!')
;
loadDataContract = () =>
const contract = TruffleContract(DataAccess)
contract.setProvider(this.web3Provider)
contract.defaults(from: this.web3Provider);
// deploy contract
contract.deployed().then((DataAccessInstance) =>
this.DataAccessInstance = DataAccessInstance;
DataAccessInstance.enroll()
).then(data =>
window.alert("contract loaded.", data)
).catch(err => console.log("data load data this is ", err))
;
下面是solidity合约的一部分
contract DataAccess
// This declares a new complex type which
// will be used for variables
// it represents a single usersData
struct DataLocation
string ownerName;
string ownerID;
string url;
string dateOfAccess;
string timeOfAccess;
uint accessCount;
uint index;
struct Index
uint indexLocation;
// store Data that has a location
mapping(address => DataLocation) private datastores;
mapping (address => uint) private balances;
// store datalocation Count
uint public datalocationsCount;
// userIndex stors location of pointers
address[] public userIndex;
// stored event
event storedEvent (
uint indexed _dataLocationId
);
// event for new data location
event LogNewData (
address indexed dataAddress,
string ownerName,
string url,
string ownerID,
string dateOfAccess,
string timeOfAccess,
// uint accessCount,
uint index);
// event for new updated data location
event LogUpdateData (
address indexed dataAddress,
string ownerName,
string url,
string ownerID,
string dateOfAccess,
string timeOfAccess,
// uint accessCount,
uint index);
function enroll() public returns (uint)
/* Set the sender's balance to 1000, return the sender's balance */
address user = msg.sender;
balances[user] = 1000;
return user.balance;
当尝试根据反馈重写合约时,结果仍然是无效地址的错误。
loadDataContract = () =>
const contract = TruffleContract(DataAccess)
contract.setProvider(this.web3Provider)
contract.defaults(from: this.web3Provider);
// initial function
contract.at('0x8a4A12479486A427109e964e90CaEB5798C13A01').enroll().then((Output) =>
this.setState(value: Output)
).catch(err => console.log("Enroll function error ", err))
;
【问题讨论】:
【参考方案1】:您应该使用contract.new()
来部署新合约。如果你想使用已经部署的合约,请使用contract.at(<address of deployed contract>)
。
contract.deployed()
用于例如测试,当您运行truffle test
命令时,它会返回部署在迁移脚本中的合约。
【讨论】:
谢谢@igor Sobolev。重写代码时,我仍然无法访问合约并且出现相同的错误。请参阅问题的更新代码 sn-p。任何其他想法将不胜感激contract.defaults
中的from
参数应该是发送交易的地址(this.web3Provider
是否返回地址?)另外,您可以尝试重写.then()
中的函数调用,如下所示:@ 987654329@
非常感谢您的建议!我现在要加载合同,但必须使用 this.web3Provider.selectedAddress contract.defaults(from: this.web3Provider.selectedAddress);
是否应该将用户地址传递给合同,因为我阅读的文档似乎没有使用它?您对如何在不编写contract.at('0x8a4A12479486A427109e964e90CaEB5798C13A01')
并传递变量而不是合同 ID 的情况下连接到合同有任何建议吗?再次感谢伊戈尔以上是关于从 Web.js 连接到 Solidity 合约时地址无效的主要内容,如果未能解决你的问题,请参考以下文章
第一行代码:以太坊-使用Solidity语言开发和测试智能合约
我们可以在智能合约中使用 Solidity 获取过去区块中记录的交易信息吗?