DEV Community

Ayden
Ayden

Posted on

Solidity Assembly的基础用法

什么是Assembly

Image description
在编写Solidity代码时,我们可以使用assembly{}关键字开始编写Yul代码,它是一种简化且扩展了的汇编语言。通过使用assembly,我们可以直接访问堆栈,并优化代码以提高内存效率,从而减少执行交易所需的燃气量。这最终降低了用户的交易成本。

然而,在可读性方面存在一些妥协。许多前端开发人员可以阅读Solidity智能合约并理解正在执行的功能以及如何将其应用到他们的web3查询中。相比之下,汇编可能会让人感到有些困惑,如果你不熟悉低级编程,可能很难理解其逻辑和流程。

操作码列表

操作码 描述
add(x, y) 将栈中的前两个值相加,并用结果替换它们
sub(x, y) 减法操作
mul(x, y) 乘法操作
div(x, y) 除法操作
mod(x, y) 取模操作
lt(x, y) 小于。如果 x 小于 y,则返回 1
gt(x, y) 大于
eq(x, y) 等于。如果 x 等于 y,则返回 1
not(x) 按位取反 (1010 > 0101)
and(x, y) 按位与 (1000 AND 1100 > 1000)
or(x, y) 按位或 (1000 AND 1100 > 1100)
xor(x, y) 按位异或 (1000 XOR 1100 > 0100)
byte(n, x) X 的第 N 个字节
keccak256(pos, n) 本地哈希算法
pop(x) 从栈中弹出 X
mload(pos) 加载存储在位置 pos 的内存数据
mstore(pos, value) 在位置 pos 的memory中存储值 value
sload(pos) 加载存储在位置 pos 的存储数据
sstore(pos, value) 在位置 pos 的storage中存储值 value
balance(address) 以 wei 为单位返回地址的以太币余额
call(gas, address, value, in, insize, out, outsize) 调用外部合约,也可用于发送资金,成功时返回 1
delegatecall(gas, address, value, in, insize, out, outsize) 与上述相同,但由用户而不是合约进行调用
revert(p, s) 撤销事务和任何状态更改
return(p, s) 结束执行并返回数据

这里需要注意的是mstoresstore的区别,主要存储的位置的不一致,一种是存储在memory中,另一种是存储在storage中。

使用案例

读写

下面我们通过一个例子展示下如何使用Assembly把数据存储到storage中,然后通过函数读取的方式读出来。

    function testAssembly() public {
        //定义一个存储的值方便测试.
        uint256 x = 123;
        bool res;

        //将x存储到storage中。
        assembly {
            sstore(0, x)
        }

        //在storage中读取x的值,其中0是pos
        assembly {
            let readX := sload(0)
            //将readX的值存储到memory,pos == 0x80的位置。
            mstore(0x80, readX)
        }

        //将0x80中的值取出来.
        assembly {
            let v := mload(0x80)
            if eq(v, x) {
                res := true
            }
        }

        //判断最终取出来的v == x?
        assert(res);
    }
Enter fullscreen mode Exit fullscreen mode

上诉的例子在实际项目中不太可能出现,只是为了展示读写的过程。

基础运算

    function testAssembly() public {
        //定义一个存储的值方便测试.
        uint256 x = 123;
        uint256 r = 345;

        //将x存储到storage中。
        assembly {
            x := add(x, 300)
            x := sub(x, 78)
        }

        //判断最终取出来的r == x?
        assert(r == x);
    }
Enter fullscreen mode Exit fullscreen mode

Follow我的推进行交流学习:https://twitter.com/nifty12111
TG:@coffiasd

Top comments (0)