用地址數組構造合約
如果我錯了,請糾正我,但我知道您不能用字元串數組初始化契約,因為它是動態類型,但我可以用固定類型初始化契約嗎?特別是地址數組。
另外,如果我嘗試通過字節碼進行部署,這將如何序列化?
這是 Whitehats 使用的一種解決方案,將檢索到的 ETC 分發給乙太坊經典鏈上的 DAO 代幣持有者。
來自https://github.com/BitySA/whetcwithdraw/blob/master/daobalance/dao_balance_snapshot.sol:
// This contract publishes the balances of the DAO at the moment of the hardfork // After the deployment of the contract the function fill is called many times // in order to fill the balance of each account. contract DAOBalanceSnapShot { uint constant D160 = 0x10000000000000000000000000000000000000000; mapping (address => uint) public balanceOf; address public owner; function DAOBalanceSnapShot() { owner = msg.sender; } uint public totalSupply; uint public totalAccounts; bool public sealed; // The 160 LSB is the address of the balance // The 96 MSB is the balance of that address. function fill(uint[] data) { if ((msg.sender != owner)||(sealed)) throw; for (uint i=0; i<data.length; i++) { address a = address( data[i] & (D160-1) ); uint amount = data[i] / D160; if (balanceOf[a] == 0) { // In case it's filled two times, it only increments once totalAccounts ++; balanceOf[a] = amount; totalSupply += amount; } } } function seal() { if ((msg.sender != owner)||(sealed)) throw; sealed= true; } }
您可以看到地址和余額被編碼為數據數組
uint256
。在此解決方案中,建構子不用於初始化地址(和余額)數組。但是在構造之後,該
fill(...)
函式被反複呼叫以構造balanceOf
地址到餘額的映射。在所有必需的餘額都被填滿後,seal()
呼叫該函式以指示余額已全部被填滿。當超過 11,000 項地址和余額需要填充必要的數據時,這種“填充”數據的方法是解決方案,因為數據不會適合單個建構子呼叫。
參考:如何將我的 The DAO 代幣轉換為 Ethereum Classic 鏈上的乙太幣?
用一個例子更新
這是一個例子:
pragma solidity ^0.4.4; contract AddressArray { address[] addresses; function AddressArray(address[] addresses_) { for (uint i = 0; i < addresses_.length; i++) { addresses.push(addresses_[i]); } } function getNumberOfAddresses() constant returns (uint) { return addresses.length; } function getAddress(uint i) constant returns (address) { return addresses[i]; } }
我將使用 Browser Solidity 建構合約,並使用以下地址作為參數:
$$ “0x000d1009bd8f0b1301cc5edc28ed1222a3ce671e”, “0x0014060ff383c9b21c6840a3b14aab06741e5c49”, “0x0020017ba4c67f76c76b1af8c41821ee54f37171”, “0x0036f6addb6d64684390f55a92f0f4988266901b”, “0x004e64833635cd1056b948b57286b7c91e62731c” $$
這是 Browser Solidity 螢幕,顯示使用地址參數數組成功部署合約:
這是來自 Browser Solidity 的字節碼數據:
606060405234610000576040516101f83803806101f8833981016040528080518201919060200150505b6000600090505b81518110156100f357600080548060010182818154818355818115116100825781836000526020600020918201910161008191905b8082111561007d576000816000905550600101610065565b5090565b5b505050916000526020600020900160005b848481518110156100005790602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c01000000000000000000000000908102040217905550505b8080600101915050610030565b5b50505b60f4806101046000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e61319d146040578063b93f9b0a146060575b6000565b34600057604a60a4565b6040518082815260200191505060405180910390f35b346000576078600480803590602001909190505060b2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060008054905090505b90565b60006000828154811015600057906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1650505b919050
在將合約部署到我的開發區塊鏈之前,我打開
debug.verbosity(5)
以查看原始格式的交易。這是數據:I0110 15:40:29.061385 core/tx_pool.go:542] 促進排隊交易:TX(4856cf602e31c38000279f3fb1bdf3f13c475fac4e35f9cc67811e34ef0ceda4) 契約:false 來自:000d1009718f0b2301cc5
$$ contract creation $$ Nonce:17 GasPrice:20000000000 GasLimit 281531 值:0 數據:0x606060405234610000576040516101f83803806101f8833981016040528080518201919060200150505b6000600090505b81518110156100f357600080548060010182818154818355818115116100825781836000526020600020918201910161008191905b8082111561007d576000816000905550600101610065565b5090565b5b505050916000526020600020900160005b848481518110156100005790602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c01000000000000000000000000908102040217905550505b8080600101915050610030565b5b50505b60f4806101046000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e61319d146040578063b93f9b0a146060575b6000565b34600057604a60a4565b6040518082815260200191505060405180910390f35b346000576078600480803590602001909190505060b2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060008054905090505b90565b60006000828154811015600057906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffff10560505b91000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000d1009bd8f0b1301cc5edc28ed1222a3ce671e0000000000000000000000000014060ff383c9b21c6840a3b14aab06741e5c490000000000000000000000000020017ba4c67f76c76b1af8c41821ee54f371710000000000000000000000000036f6addb6d64684390f55a92f0f4988266901b000000000000000000000000004e64833635cd1056b948b57286b7c91e62731c
在上面的數據中,我用粗體突出了表示合約部署期間參數的附加字節碼。
如果您打算通過字節碼進行部署,現在讓我們對您需要建構的字節碼進行逆向工程。
這是已部署字節碼中的粗體數據,分離出來:
0000000000000000000000000000000000000000000000000000000000000020 // 0x20 = 32. This is probably the offset to the start of the array data 0000000000000000000000000000000000000000000000000000000000000005 // There are five items in the array 000000000000000000000000000d1009bd8f0b1301cc5edc28ed1222a3ce671e // 1st address 0000000000000000000000000014060ff383c9b21c6840a3b14aab06741e5c49 // 2nd address 0000000000000000000000000020017ba4c67f76c76b1af8c41821ee54f37171 // 3rd address 0000000000000000000000000036f6addb6d64684390f55a92f0f4988266901b // 4th address 000000000000000000000000004e64833635cd1056b948b57286b7c91e62731c // 5th address
請參閱下面的第二個連結以嘗試對參數格式進行逆向工程,包括偏移量。
讓我們嘗試另一種參數組合
這是另一個帶有額外建構子參數的契約:
pragma solidity ^0.4.4; contract AddressArray { address[] addresses; function AddressArray(uint dummy1, address[] addresses_, uint dummy2) { for (uint i = 0; i < addresses_.length; i++) { addresses.push(addresses_[i]); } } function getNumberOfAddresses() constant returns (uint) { return addresses.length; } function getAddress(uint i) constant returns (address) { return addresses[i]; } }
我使用 Browser Solidity 的以下參數部署了合約:
123,
$$ “0x000d1009bd8f0b1301cc5edc28ed1222a3ce671e”, “0x0014060ff383c9b21c6840a3b14aab06741e5c49” $$, 456
這是來自 Browser Solidity 的字節碼:
6060604052346100005760405161020c38038061020c833981016040528080519060200190919080518201919060200180519060200190919050505b6000600090505b825181101561010557600080548060010182818154818355818115116100945781836000526020600020918201910161009391905b8082111561008f576000816000905550600101610077565b5090565b5b505050916000526020600020900160005b858481518110156100005790602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c01000000000000000000000000908102040217905550505b8080600101915050610042565b5b505050505b60f4806101186000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e61319d146040578063b93f9b0a146060575b6000565b34600057604a60a4565b6040518082815260200191505060405180910390f35b346000576078600480803590602001909190505060b2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060008054905090505b90565b60006000828154811015600057906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b91905056
這是
geth
事務跟踪數據,再次以粗體顯示附加參數字節碼數據:0x6060604052346100005760405161020c38038061020c833981016040528080519060200190919080518201919060200180519060200190919050505b6000600090505b825181101561010557600080548060010182818154818355818115116100945781836000526020600020918201910161009391905b8082111561008f576000816000905550600101610077565b5090565b5b505050916000526020600020900160005b858481518110156100005790602001906020020151909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690836c01000000000000000000000000908102040217905550505b8080600101915050610042565b5b505050505b60f4806101186000396000f360606040526000357c0100000000000000000000000000000000000000000000000000000000900480632e61319d146040578063b93f9b0a146060575b6000565b34600057604a60a4565b6040518082815260200191505060405180910390f35b346000576078600480803590602001909190505060b2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600060008054905090505b90565b60006000828154811015600057906000526020600020900160005b9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690505b91905056000000000000000000000000000000000000000000000000000000000000007b000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000001c8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d1009bd8f0b1301cc5edc28ed1222a3ce671e0000000000000000000000000014060ff383c9b21c68406741a
這是參數數據,已解碼:
000000000000000000000000000000000000000000000000000000000000007b // new BigNumber("7b",16) = 123 0000000000000000000000000000000000000000000000000000000000000060 // new BigNumber("60",16) = 96 or 3 x 32. This is the offset of the second parameter. 00000000000000000000000000000000000000000000000000000000000001c8 // new BigNumber("1c8",16) = 456 0000000000000000000000000000000000000000000000000000000000000002 // 2 array items 000000000000000000000000000d1009bd8f0b1301cc5edc28ed1222a3ce671e // 1st address 0000000000000000000000000014060ff383c9b21c6840a3b14aab06741e5c49 // 2nd address
也可以看看: