Address是什么
通常情况下,地址代表一外部账户或合约账户,它们都可以在区块链上接收(目标地址)或发送(源地址)。 更具体地说,它是根据ECDSA算法,从公钥的Keccak-256哈希值的最后20个字节导出的标识符,一个十六进制数字。
账户类型
There are two types of accounts in the Ethereum Chain
(1). Externally Owned Accounts(EOA) [Person]
(2). Contracts Accounts [Contracts on Chain]
翻译过来就是:
以太坊链中有两种类型的账户
- 外部账户(个人持有)
- 合约账户(链上合约)
外部账户
外部帐户 (EOA) 是由控制帐户私钥的用户所管理的帐户,通常使用助记词生成。 外部帐户是没有任何关联代码的帐户。 通常,这些帐户与钱包
一起使用。
合约账户
一个包含代码的帐户,只要接收到来自其他帐户(外部帐户或合约)的交易,就会执行该代码。
代码示例
1、获取合约账户
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract AddressExample {
function getContractAddress() external view returns(address) {
return address(this);
// return this; // 报错
}
}
注意:合约账户需要使用address()进行显示转换为address类型。
如果直接返回this的话,则会抛出如下错误;
TypeError: Return argument type contract AddressExample is not implicitly convertible to expected type (type of first return variable) address. --> contract-demo/AddressExample.sol:15:16: | 15 | return this; | ^^^^
2、获取msg.sender
function getSenderAddress() external view returns(address) {
return msg.sender;
}
msg.sender
表示消息的发送者(当前通话)。它可以指代调用函数或创建交易的地址,可以是合约地址,或者是像你我这样的人的账户地址。
随着上面选取的地址切换而关联改变的。
但不少人(包括我)曾经一度认为msg.sender就是部署合约的外部账户,是唯一的。造成这种错觉的原因是忽略了一个细节。
address ownerAddress;
constructor() {
ownerAddress = msg.sender;
}
就是说合约创建者在构造函数已经初始化,将msg.sender定死为合约的拥有者(owner),所以之后的一系列对合约的操作,都可以借助ownerAddress这一凭证实现访问权限控制。
3、获取余额
function getBalance() external view returns(uint, uint, uint) {
uint contractBalance = address(this).balance; // 合约账户余额
uint senderBalance = msg.sender.balance; // 调用者账户余额
uint ownerBalance = ownerAddress.balance; // 合约拥有者余额
return (contractBalance, senderBalance, ownerBalance);
}
注意我切换到另一个账户,调用的getBalance方法,这样可以比较调用者和拥有者的余额。
参考: https://ethereum.org/zh/glossary/#address
blockchain - Solidity basics: what "msg.sender" stands for - Stack Overflow