智能合约的地址通常来讲来自有三个地址,一个是创建合约的地址,一个能与合约交互的地址,另一个部署合约时会产生一个地址【即合约就是这个地址】
初识以太坊,这三个地址似乎会有点绕,以一个简单的例子来深刻理解这三个地址
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.28;
contract Own {
// 申明了一个owner地址
address public owner;
constructor() {
// 部署Own这个合约时所属钱包的地址
owner = msg.sender;
}
// 获取由哪个钱包部署智能合约的钱包地址
function getOwner() public view returns (address) {
return owner;
}
// 获取部署这个智能合约的地址
function getContractAddress() public view returns (address) {
return address(this);
}
// 获取钱包与智能合约交互的那个地址
function getSenderAddress() public view returns(address) {
return msg.sender;
}
}
从以上代码来分析,我们发现,创建合约的地址,owner也不会发生变化contructor这是msg.sender当前钱包地址赋值给了owner,注意,如果这个合约代码没有任何变化,一旦部署合约,合约地址就不会发上变化,当前部署的owner不会发生变化
address(this)这是这个Own智能合约的地址,当我们部署智能合约成功时,返回这个智能合约地址就是这个地址
msg.sender这个 msg 是个全局变量,是返回当前钱包与合约交互的这个钱包地址
具体我们可以使用在 remix 在线编辑器中测试这个合约

首先我选择的钱包地址是0x5B38Da6a701c568545dCfcB03FcB875f56beddC4这个虚拟钱包地址

当我们部署完成后,我们会发现
与合约交互的地址与当前部署钱包的地址可以是同一个地址,当我们部署合约完成时,当你修改当前钱包地址地址时,owner地址不会发生改变,如果合约代码不变,那么合约地址就是唯一的
我们获取一下这三个地址的余额
...
// 获取当前交互的钱包地址
function getSenderAddressBalance() public view returns(uint) {
return msg.sender.balance;
}
// 获取Sender钱包地址的余额【与智能合约交互的钱包地址,或者部署当前智能合约的钱包地址】
function getSenderAddressBalance(address _address) public view returns(uint) {
return _address.balance;
}
// 查询智能合约的余额地址
function getContractAddressBalance() public view returns(uint) {
return address(this).balance;
}
// 根据输入地址查询余额
function getAddressBalance(address _address) public view returns(uint) {
return _address.balance;
}
通过balance就可以查询这个三个地址的余额,并且我们从中可以知道查询余额是公开的 api 方法,并不会产生gas费用转账
我们在合约内部可以一个钱包地址给另一个钱包地址转账,也可以给合约地址转账,那么这是怎么实现的呢,首先我们先来看钱包与钱包地址的转账。
...
function send(address payable _address) public payable {
// bool send = _address.send(msg.value);
// require(send, "sender error");
(bool succeess,) = _address.call{value: msg.value}("");
是另一个钱包地址, 我们想另一个钱包进行转账操作 首先 1 是我们当前钱包部署的钱包地址,2 是两外一个钱包地址,我们可以从 1 钱包转到 2 钱包一个 wei 的钱(succeess, "Failed to send Ether");
}
代码非常简单,首先我们尝试使用send方法,在官方已经不推荐使用 send 方法转账而是推荐使用call或者transfer,但是官方最终推荐 call 方法进行转账
我们发现_address是另一个钱包地址, 我们可以进行想另一个钱包进行转账操作 首先 1 是我们当前钱包部署的钱包地址,2 是两外一个钱包地址,我们可以从 1 钱包转到 2 钱包一个 wei 的钱
我们由这前后两张图比较知道 2 地址已经加了 1wei

但是如果这个_address修改成合约地址,那会怎么样?

如果_address 是一个转账合约地址那么这个合约必需要满足有receive或者fallback,否则转账到合约地址里一定会失败
event Received(uint amount);
receive() external payable {
// 空函数或 emit event 一般不会超过 2300 gas
}
我们会发现已经向合约地址转账成功,并且能查询到合约地址账户的余额

ownAddress,一个又当前钱包部署的合约地址contractAddress,还有一个与合约交互的钱包地址senderAddress【与合约交互的钱包地址可以是当前部署合约的钱包地址】owenAddress不会发生变化,因为在 constructor 中,当部署合约成功后,会执行 constructor,msg.sender 地址就已经唯一赋值了,所以不管如何切换交互钱包地址这个 ownerAddress 不会发生变化,即初始钱包的地址合约地址并不会发生变化call转账,注意这个合约方法必需payable, 且地址_address也必须时 address 类型payable允许发送ethown必需要有receive() external payable { }否则就会被拒绝,转账报错参考资料
[1]
code example: https://github.com/maicFir/SolidityLesson/blob/master/18-test/contracts/Own.sol