Solidity
如何在映射中持久分配對結構的分配?
以下是我面臨的問題的簡化;
pragma solidity 0.4.18; contract ValueSetter { struct BasicValue { uint256 value; } address my_address; // Just for the require later BasicValue fixed_value; mapping(address => BasicValue) fixed_values; function ValueSetter(address init_address) public { my_address = init_address; fixed_values[init_address] = fixed_value; } function set_value(uint256 my_value) external { // Just to prove that the bug isn't in my calling params require(msg.sender == my_address && my_value != 0); fixed_values[msg.sender].value = my_value; assert(fixed_value.value != 0); } }
當我
set_value
用非零值呼叫時,我點擊了斷言。看起來問題是在這一行中,fixed_values[msg.sender].value = my_value;
我嘗試分配給映射內的結構並沒有分配給儲存在
fixed_value
. 我也嘗試了以下方法;BasicValue storage basic_val = fixed_values[msg.sender]; basic_val.value = my_value;
但這不會改變結果。我在solidity文件中讀到,
儲存和記憶體之間以及狀態變數(甚至來自其他狀態變數)之間的分配總是創建一個獨立的副本
如果是這種情況,那麼我怎樣才能讓結構“脫離”映射,以便在本地使用它?
(注意;上面的合約看起來比它需要的複雜得多,因為真正的合約有更多的要求。例如,結構中有多個屬性,初始化時聲明的結構不止一個,還有超過映射中的一個結構,我需要執行涉及多個其中一個的邏輯。)
這些行是不必要的
BasicValue fixed_value; fixed_values[my_address] = fixed_value;
但真正的問題是這條線
assert(fixed_values[msg.sender].value != 0);
因為您想要該索引處的結構。
pragma solidity 0.4.18; contract ValueSetter { struct ValueStruct { uint256 value; } address public my_address; // Just for the require later mapping(address => ValueStruct) public valueStructs; function ValueSetter() public { my_address = msg.sender; } function set_value(uint256 my_value) external { // this shows the function is called by the deployer account require(msg.sender == my_address && my_value != 0); // this stores a uint in the .value element of the ValueStruct // stored in the mapping at the index which is the sender valueStructs[msg.sender].value = my_value; // this just gets confirms the value is where we put it assert(valueStructs[msg.sender].value != 0); } }
希望能幫助到你。
是的,所有狀態變數都在婚前儲存在區塊鏈中。但是來到你的 qus 為什麼:
function ValueSetter(address init_address) public { my_address = init_address; fixed_values[init_address] = fixed_value; }
在上面的程式碼中,您的初始化
fixed_values[init_address] = fixed_value;
意味著在內部fixed_value = BasicValue(0)
,這將被分配給fixed_values[init_address] = fixed_value;
在內部,您的程式碼如下所示:
function ValueSetter(address init_address) public { fixed_value = BasicValue(0); my_address = init_address; fixed_values[init_address] = fixed_value; }
來到你那裡有一個邏輯錯誤:
function set_value(uint256 my_value) external { // Just to prove that the bug isn't in my calling params require(msg.sender == my_address && my_value != 0); fixed_values[msg.sender].value = my_value; assert(fixed_value.value != 0); }
根據我的解釋,fixed_value.value 為零。斷言將失敗。您的交易將恢復到以前的狀態。它不會將目前值保存到區塊鏈。但交易將作為失敗記錄到鏈上。
於是修改程式碼:pragma solidity 0.4.18;
contract ValueSetter { struct BasicValue { uint256 value; } address my_address; // Just for the require later BasicValue fixed_value; mapping(address => BasicValue) fixed_values; function ValueSetter(address init_address) public { my_address = init_address; fixed_values[init_address] = BasicValue(1000); } function set_value(uint256 my_value) external { // Just to prove that the bug isn't in my calling params require(msg.sender == my_address && my_value != 0); fixed_values[msg.sender].value = my_value; //assert(fixed_value.value != 0); } }