昨天跟申总学了下怎么看EVM指令,然后就一撸到底,很爽,哈哈。。。
stateOject中有两个Storage类型的变量,是用来缓存智能合约中所有变量的值的。这个Storage类型的定义如下:
type Storage map[common.Hash]common.Hash
就是一个map,key跟value都是common.Hash类型,其实就是[]byte。这个map只有在EVM执行SSTORE指令时候会赋值,用于记录变量的值。那么这里面的key跟value具体是什么内容呢?经研究,结果如下:
- 对于基本数据类型,key = 合约中的变量声明位置(从0开始)
- 对于map类型,key = SHA3(map中的关键字,变量声明位置),也就是把map中的关键字和变量声明位置拼在一起成为一个64字节的[]byte,然后计算hash值
- value不管在哪种情况下都存储变量的实际值
可以使用browser-solidity查看编译出来的EVM指令:
https://ethereum.github.io/browser-solidity
在编辑器中写测试代码:
pragma solidity ^0.4.0;
contract Demo {
int a;
int x;
mapping(address => int) b;
function myfunc() public {
a = 8;
x = 9;
b[123] = 1;
}
}
点击右边的“Start to compile”,然后点击“Details”就可以查看编译出来的EVM指令。以map为例,逐条分析指令就可以看出SSTORE具体存储的key和value是如何生成的:
// 压栈返回值
PUSH 1 1
stack [1]
// 压栈变量position
PUSH 2 b
stack [2 1]
// 压栈内存存储起点
PUSH 0 b[123]
stack [0 2 1]
// 压栈map索引值(即123)
PUSH 7B 123
stack [7B 0 2 1]
// 压栈mask
PUSH FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF b[123]
stack [FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 7B 0 2 1]
// 索引值 & mask,弹出2个值,压栈与的结果
AND b[123]
stack [7B 0 2 1]
// 复制第二个值并压栈
DUP2 b[123]
stack [0 7B 0 2 1]
// 在内存0位置存储7B(即map索引值),弹出2个值
MSTORE b[123]
stack [0 2 1]
store {7B}
// 压栈内存偏移,0x20 = 32字节
PUSH 20 b[123]
stack [20 0 2 1]
store {7B}
// 计算内存偏移,弹出2个值,压栈相加的结果
ADD b[123]
stack [20 2 1]
store {7B}
// 交换栈顶2个值
SWAP1 b[123]
stack [2 20 1]
store {7B}
// 复制第二个值并压栈
DUP2 b[123]
stack [20 2 20 1]
store {7B}
// 在内存0x20位置存储2(即变量position)
MSTORE b[123]
stack [20 1]
store {7B 2}
// 压栈内存偏移,0x20 = 32字节
PUSH 20 b[123]
stack [20 20 1]
store {7B 2}
// 计算内存偏移,弹出2个值,压栈相加的结果
ADD b[123]
stack [40 1]
store {7B 2}
// 压栈数据读取offset
PUSH 0 b[123]
stack [0 40 1]
store {7B 2}
// offset=0, size=0x40,也就是从store中读取2个32字节的值,
// 然后计算SHA3,结果压栈
KECCAK256 b[123]
stack [sha3(0x0000007B00000002) 1]
store {7B 2}
// 复制第二个值(即要赋的值)并压栈
DUP2 b[123] = 1
stack [1 sha3 1]
store {7B 2}
// 交换栈顶2个值
SWAP1 b[123] = 1
stack [sha3 1 1]
store {7B 2}
// 以sha3为key,1为value,存入StateDB,同时弹栈
SSTORE b[123] = 1
stack [1]
store {7B 2}
// 弹出返回值
POP b[123] = 1
stack []
store {7B 2}
思考题:如果是struct或者array类型,是怎么存储的呢? :-)
更多文章欢迎关注“鑫鑫点灯”专栏:https://blog.csdn.net/turkeycock/article/category/7669858