众所周知,有许多因素决定了一个好的明智的合同,例如:
在这个问题上,我想把重点放在智能合同的成本上。
问题1:如何制定符合成本效益的智能合同?
问题2:如何避免使用一些昂贵的功能?换句话说,有什么功能是众所周知的比其他操作更昂贵,我们能用更好的吗?
问题3:一般来说,以最低的成本写一份聪明的合同有什么好的做法?
简而言之:我们怎样才能节省汽油:以太:钱?
发布于 2017-10-19 22:51:39
在以太,交易成本的天然气,因此乙醚。事务的气体消耗取决于EVM必须执行的操作码。每个Opcode的气体成本可以在这个问题中找到。很少有普通的操作码和气体,
Operation Gas Description
ADD/SUB 3 Arithmetic operation
MUL/DIV 5 Arithmetic operation
ADDMOD/MULMOD 8 Arithmetic operation
AND/OR/XOR 3 Bitwise logic operation
LT/GT/SLT/SGT/EQ 3 Comparison operation
POP 2 Stack operation
PUSH/DUP/SWAP 3 Stack operation
MLOAD/MSTORE 3 Memory operation
JUMP 8 Unconditional jump
JUMPI 10 Conditional jump
SLOAD 200 Storage operation
SSTORE 5,000/20,000 Storage operation
BALANCE 400 Get balance of an account
CREATE 32,000 Create a new account using CREATE
CALL 25,000 Create a new account using CALL当涉及到智能合同时,这是一个值得关注的问题,因为交易也涉及到,在设计合同时必须考虑天然气的成本。
减少合同消耗的气体在两种情况下都很重要,
的成本
为此,大多数优化都是在编译时完成的,如文件-常见问题中所述,
在已部署的合同中是否包括了评论,是否增加了部署气体?不,在编译过程中,不需要执行的所有内容都会被删除。其中包括注释、变量名和类型名称。
优化器的详细信息可以找到这里。
另一种缩小大小的方法是删除无用的代码。例如:
1 function p1 ( uint x ){
2 if ( x > 5)
3 if ( x*x < 20)
4 XXX }在上面的代码中,第3行和第4行将永远不会被执行,这些类型的无用代码可以通过仔细地遍历契约逻辑来避免,这将减少智能契约的大小。
调用合同函数的
当合同的函数被调用时,为了执行功能,它要花费天然气。因此,优化函数以减少气体的使用是非常重要的。当考虑到个人合同时,可以有许多不同的方法。在执行过程中可以节省汽油的有几个,
昂贵的操作是具有更多气体值(如SSTORE )的操作码。下面是一些降低昂贵操作的方法。
( A) 短路规则的使用
操作符\和&&应用常见的短路规则。这意味着,在表达式f(x)中,如果f(x)计算为true,则即使有副作用,g(y)也不会被计算。
因此,如果逻辑操作包括昂贵的操作和低成本的操作,以一种使昂贵的操作可以短路的方式安排,将减少一些执行时的气体。
如果f(x)低成本,g(y)昂贵,则安排逻辑操作
f(x) || g(y)f(x) && g(y)如果短路,会节省更多的汽油。
如果f(x)与g(y)相比返回false的概率要高得多,那么像f(x) && g(y)那样安排和操作可能会通过短路来节省执行过程中的更多气体。
如果f(x)返回true的概率比g(y)高得多,那么将OR操作安排为f(x) || g(y)可能会通过短路来节省执行过程中的更多气体。
( B)循环中昂贵的操作
例:
uint sum = 0;
function p3 ( uint x ){
for ( uint i = 0 ; i < x ; i++)
sum += i; }在上面的代码中,由于每次在循环中读取和写入sum存储变量,所以每次迭代时都会执行代价高昂的存储操作。可以通过引入如下的局部变量来避免这种情况,以节省气体。
uint sum = 0;
function p3 ( uint x ){
uint temp = 0;
for ( uint i = 0 ; i < x ; i++)
temp += i; }
sum += temp;环路组合
function p5 ( uint x ){
uint m = 0;
uint v = 0;
for ( uint i = 0 ; i < x ; i++) //loop-1
m += i;
for ( uint j = 0 ; j < x ; j++) //loop-2
v -= j; }环路-1和循环-2可以结合起来,节省气体,
function p5 ( uint x ){
uint m = 0;
uint v = 0;
for ( uint i = 0 ; i < x ; i++) //loop-1
m += i;
v -= j; }还可以找到一些更多的循环模式,这里。
来自文档,
可以使用一个字节数组作为byte[],但是当传入调用时,它浪费了大量的空间,每个元素都浪费了31个字节。最好使用字节。
和
根据经验,对任意长度的原始字节数据使用字节,对任意长度的字符串(UTF-8)使用字符串。如果可以将长度限制为一定数量的字节,请始终使用bytes1中的一个到bytes32,因为它们要便宜得多。
固定长度总能节省汽油。也可以参考这个问题。
为了简单的使用调用库可能会花费很大。如果该功能简单可行,可以在契约内部实现,因为它避免了调用库的步骤。对于这两种功能,仅执行成本仍然是相同的。
external只能强制使用calldata作为参数位置,这在函数执行时节省了一些气体。memory变量可以节省访问storage的气体。这是一些节省气体的方法,而且可能有许多其他的方法,取决于需求。
发布于 2018-09-01 14:44:46
我相信使用内联组装函数在智能合同中编写函数可以比您试图在合同中进行的任何更改更具有成本效益。一个简单的循环函数,在固体取x的魏氏。在同一功能中写入的实体的内嵌装配所占的比例低到0.7(x) %。
https://ethereum.stackexchange.com/questions/28813
复制相似问题