msg.sender (address):訊息傳送方(當前呼叫)
tx.origin (address):交易傳送方(完整呼叫鏈上的原始傳送方)由於是直接呼叫者,所以當處於 使用者A->合約1->合約2 呼叫鏈下,若在合約2內使用msg.sender,得到的會是合約1的地址。如果想獲取使用者A,可以用tx.origin:交易的」始作俑者」,整個呼叫鏈的起點。
在下面的2個合約中,T4中去呼叫T3中的函數,當處於 使用者A->合約1->合約2 呼叫鏈下,若在合約2內使用msg.sender,得到的會是合約1的地址。如果想獲取使用者A,可以用tx.origin:交易的」始作俑者」,整個呼叫鏈的起點。
把官方的解釋帶入實際的案例如下:
使用者A:小米
合約1:T4
合約2:T3
pragma solidity >=0.4.0
contract T3 {
// 為了演示去掉view,方便傳入使用者的address
function select() public returns(address){
return tx.origin;
}
// 為了演示去掉view方便傳入使用者的address
function select2() public returns(address){
return msg.sender;
}
}
pragma solidity >=0.4.0
import "./T3.sol";
contract T4 {
// 為了演示去掉view,方便傳入使用者的address
function select() public returns(address){
T3 t3=new T3();
return t3.select();
}
// 為了演示去掉view,方便傳入使用者的address
function select2() public returns(address){
T3 t3=new T3();
return t3.select2();
}
}
先呼叫T4的select函數(tx.origin),如下圖所示:
得到的是小米使用者的公鑰地址資訊
先呼叫T4的select2函數(msg.sender),如下圖所示:
得到是T4的合約的地址
所以在有使用者A->合約1->合約2 這種類似的呼叫鏈場景下做許可權判斷的時候一定要注意合理的選擇使用tx.origin還是msg.sender。以防對合約的業務的邏輯造成影響。