# 地址(Address)
地址: 以太坊地址的長度,大小20個字節,160位,所以可以用一個`uint160`編碼。地址是所有合約的基礎,所有的合約都會繼承地址對象,也可以隨時將一個地址串,得到對應的代碼進行調用。當然地址代表一個普通帳戶時,就沒有這么多豐富的功能啦。
## 支持的運算符
- `<=`,`<`,`==`,`!=`,`>=`和`>`
## 地址類型的成員
屬性:`balance`<br/>
函數:`send()`,`call()`,`delegatecall()`,`callcode()`。
## 地址字面量
十六進制的字符串,凡是能通過地址合法性檢查(address checksum test),就會被認為是地址,如`0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`。需要注意的是39到41位長的沒有通過地址合法性檢查的,會提示一個警告,但會被視為普通的有理數字面量。
## `balance`
通過它能得到一個地址的余額。
```
pragma solidity ^0.4.0;
contract addressTest{
function getBalance(address addr) returns (uint){
return addr.balance;
}
}
```
我們可以把上述代碼放入[remix](https://ethereum.github.io/browser-solidity)中,看看效果,參見下面的操作演示:

演示中的一個核心要點是,編譯后,我們能得到當前合約的地址,并將該地址復制到輸入框中,記得錄入地址項時要加英文的雙引號,否則會報`Error encoding arguments: SyntaxError: JSON Parse error: Expected ']'`。
## `this`
如果只是想得到當前合約的余額,其實可以這樣寫:
```
pragma solidity ^0.4.0;
contract addressTest{
function getBalance() returns (uint){
return this.balance;
}
}
```
原因是對于合約來說,地址代表的就是合約本身,合約對象默認繼承自地址對象,所以內部有地址的屬性。
## 地址的方法`send()`
用來向某個地址發送貨幣(貨幣單位是`wei`)。
```
pragma solidity ^0.4.0;
//請注意這個僅是Demo,請不要用到正式環境
contract PayTest {
//得到當前合約的余額
function getBalance() returns (uint) {
return this.balance;//0
}
//向當前合約存款
function deposit() payable returns(address addr, uint amount, bool success){
//msg.sender 全局變量,調用合約的發起方
//msg.value 全局變量,調用合約的發起方轉發的貨幣量,以wei為單位。
//send() 執行的結果
return (msg.sender, msg.value, this.send(msg.value));
}
}
```
這個合約實現的是充值。`this.send(msg.value)`意指向合約自身發送`msg.value`量的以太幣。`msg.value`是合約調用方附帶的以太幣。
下面是操作演示:

關于發送者的帳號,發送的以太幣數量設置,需切換到Remix的小飛機圖標的配置頁。要在調用`deposit`前在`Value`輸入項填入要發的以太幣數量。在`getBalance`時要記得將`value`項內填的值去掉,因為`getBalance`方法,并不是`payable`的,不支持貨幣。
`send()`方法執行時有一些風險
1. 調用遞歸深度不能超1024。
1. 如果`gas`不夠,執行會失敗。
1. 所以使用這個方法要檢查成功與否。或為保險起見,貨幣操作時要使用一些最佳實踐。
如果執行失敗,將會回撤所有交易,所以務必留意返回結果。
## `call()`,`callcode()`和`delegatecall()`
為了同一些不支持ABI協議的進行直接交互(一般的`web3.js`,`soldity`都是支持的)。可以使用`call()`函數,用來向另一個合約發送原始數據。參數支持任何類型任意數量。每個參數會按規則(規則是按ABI)打包成32字節并一一拼接到一起。
`call()`方法支持ABI協議[ABI]定義的函數選擇器。如果第一個參數恰好4個字節,在這種情況下,會被認為根據ABI協議定義的函數器指定的函數簽名[ABI]。所以如果你只是想發送消息體,需要避免第一個參數是4個字節。
`call`方法返回一個`bool`值,以表明執行成功還是失敗。正常結束返回`true`,異常終止返回`false`。我們無法解析返回結果,因為這樣我們得事前知道返回的數據的編碼和數據大小(這里的潛在假設是不知道對方使用的協議格式,所以也不會知道返回的結果如何解析,有點祼協議測試的感覺)。
同樣我們也可以使用`delegatecall()`,它與`call`方法的區別在于,僅僅是代碼會執行,而其它方面,如(存儲,余額等)都是用的當前的合約的數據。`delegatecall()`方法的目的是用來執行另一個合約中的工具庫。所以開發者需要保證兩個合約中的存儲變量能兼容,來保證`delegatecall()`能順利執行。
在homestead階段之前,僅有一個受限的多樣的`callcode()`方法可用,但并未提供對`msg.sender`,`msg.value`的訪問權限。
上面的這三個方法`call()`,`delegatecall()`,`callcode()`都是底層的消息傳遞調用,最好僅在萬不得已才進行使用,因為他們破壞了Solidity的類型安全。
關于`call()`函數究竟發的什么消息體,函數選擇器究竟怎么用,參見[這個文章](http://me.tryblockchain.org/Solidity-call-callcode-delegatecall.html)的挖掘。
> 上述的函數都是底層的函數,使用時要異常小心。當調用一個未知的,可能是惡意的合約時,當你把控制權交給它,它可能回調回你的合約,所以要準備好在調用返回時,應對你的狀態變量可能被惡意篡改的情況。
- Solidity語言
- 入門說明
- Solidity智能合約文件結構
- 智能合約源文件的基本要素概覽
- 值類型
- 類型
- 布爾
- 整型
- 地址
- 字節數組
- 小數
- 字符串
- 十六進制字面量
- 枚舉
- 函數
- 引用類型
- 引用類型
- 數據位置
- 數組
- 數據結構
- 雜項
- 映射
- 左值運算符
- 類型間的轉換
- 類型推斷
- 單位
- 貨幣單位
- 時間單位
- 語言內置特性
- 特殊變量及函數
- 數學和加密函數
- 地址相關
- 進階
- 入參和出參
- 控制結構
- 函數調用
- 創建合約實例
- 表達式的執行順序
- 賦值
- 作用范圍和聲明
- 異常
- 內聯匯編
- 合約詳解
- 合約
- 可見性或權限控制
- 訪問函數
- 函數修改器
- 常狀態變量
- 回退函數
- 事件
- 繼承
- 接口
- 其它
- 庫
- 狀態變量的存儲模型
- 內存變量的存局
- 調用數據的布局