Solidity合约B如何获取合约A实例的contract_A_address(非新部署地址)
如何让合约B获取已部署合约A的地址而非创建新实例?
你的问题出在合约B中的A first = new A();这行代码——它会在合约B部署时自动生成一个全新的A合约实例,所以这个新实例的地址和你之前单独部署的A合约地址自然不一样。要让Get_Contract_A_Address()返回你已部署的那个A合约的contract_A_address,我们需要让合约B引用外部已部署的A合约地址,而不是在内部新建。
下面是两种可行的实现方案:
方案1:部署合约B时通过构造函数传入已部署A的地址(推荐,适合固定引用的场景)
这种方式是在部署合约B的时候,直接把已经部署好的A合约地址传给B,B会把这个地址存储起来,后续就可以直接调用A合约的方法或者获取它的地址。
修改后的代码如下:
pragma solidity ^0.5.0; contract A { address public contract_A_address = address(this); address public owner_A = msg.sender; } contract B { address public contract_B_address = address(this); address public owner_B = msg.sender; // 存储已部署的A合约实例 A public deployedA; // 构造函数:部署B时传入已部署的A合约地址 constructor(address _aAddress) public { deployedA = A(_aAddress); } function Get_first_Address() public view returns(address){ // 注意:这个返回的还是B内部创建的新A实例地址,如果你不需要可以删掉这部分 A first = new A(); return address(first); } function Get_Contract_A_Address() public view returns(address){ // 返回已部署A合约的contract_A_address return deployedA.contract_A_address(); } }
使用步骤:
- 先部署合约A,获取它的部署地址(比如通过区块链浏览器或者部署工具拿到)
- 部署合约B时,把步骤1拿到的A合约地址作为参数传入构造函数
- 调用B的
Get_Contract_A_Address(),就能返回和A合约中contract_A_address一致的值了
方案2:通过函数动态设置A合约地址(适合需要后续修改引用的场景)
如果你的业务需要后续修改合约B引用的A合约地址,可以用这种方式,通过一个函数来更新存储的A合约地址:
pragma solidity ^0.5.0; contract A { address public contract_A_address = address(this); address public owner_A = msg.sender; } contract B { address public contract_B_address = address(this); address public owner_B = msg.sender; A public deployedA; // 用于设置已部署的A合约地址,这里可以加上权限控制(比如只有owner能调用) function setDeployedA(address _aAddress) public { // 可选:添加权限验证,比如只有合约部署者能修改 require(msg.sender == owner_B, "Only owner can set A address"); deployedA = A(_aAddress); } function Get_first_Address() public view returns(address){ A first = new A(); return address(first); } function Get_Contract_A_Address() public view returns(address){ require(address(deployedA) != address(0), "A address not set yet"); return deployedA.contract_A_address(); } }
使用步骤:
- 部署合约A,获取它的地址
- 部署合约B
- 调用B的
setDeployedA()函数,传入A合约的地址 - 之后调用
Get_Contract_A_Address()就能得到正确的地址了
注意事项
- 如果你不需要合约B内部创建新的A实例,建议删掉
Get_first_Address()里的new A()逻辑,避免不必要的Gas消耗和混淆 - 对于方案2,一定要加上权限控制(比如只有合约所有者能修改A的地址),防止恶意用户篡改引用的合约地址
内容的提问来源于stack exchange,提问作者Omar EL KHAL
相关产品推荐
相关产品推荐

