Why does uint8 cost more gas than uint256?

文章详细解释了在以太坊虚拟机(EVM)中,由于字长限制和数据转换操作,不同数据类型(如uint8a,uint128,uint256)执行特定操作(如存储、计算、比较)时的交易成本和执行成本。举例展示了字节码操作和成本差异。
摘要由CSDN通过智能技术生成

//uint8 a=2;

//transaction cost:89426 execution cost:34630

//uint64 a = 2;

//transaction cost:89650 execution cost:34630

这是因为以太坊虚拟机(EVM)的字长为256位/32字节,每个操作都是基于这些基本单位的。如果你的数据比256位小,那么需要进一步的操作来将256位缩小到8位,因此你会看到增加的成本

具体看字节码:

//uint8 a = 2;

// PUSH1 0x80:将字节码中的0x80(十进制128)推送到栈顶。

// PUSH1 0x40:将字节码中的0x40(十进制64)推送到栈顶。

// MSTORE:将栈顶值存储到栈顶位置指定的内存位置。

// PUSH1 0x2:将字节码中的0x2(十进制2)推送到栈顶。

// PUSH0:将字节码中的0x0(十进制0)推送到栈顶。

// DUP1:复制栈顶元素。

// PUSH2 0x100:将字节码中的0x100(十进制256)推送到栈顶。

// EXP:将栈顶两个元素相乘,并将结果推送到栈顶。

// DUP2:复制第二个栈顶元素。

// SLOAD:从存储中加载数据到栈顶。

// DUP2:复制第二个栈顶元素。

// PUSH1 0xFF:将字节码中的0xFF(十进制255)推送到栈顶。

// MUL:将栈顶两个元素相乘。

// NOT:将栈顶元素取反。

// AND:对栈顶两个元素进行按位与操作。

// SWAP1:交换栈顶两个元素。

// DUP4:复制第四个栈顶元素。

// PUSH1 0xFF:将字节码中的0xFF(十进制255)推送到栈顶。

// AND:对栈顶两个元素进行按位与操作。

// MUL:将栈顶两个元素相乘。

// OR:对栈顶两个元素进行按位或操作。

// SWAP1:交换栈顶两个元素。

// SSTORE:将栈顶元素存储到存储位置。

// POP:从栈中弹出元素。

// CALLVALUE:将调用值(发送的以太币数量)压入栈顶。

// DUP1:复制栈顶元素。

// ISZERO:判断栈顶元素是否为0。

// PUSH1 0x28:将字节码中的0x28(十进制40)推送到栈顶。

// JUMPI:如果栈顶元素为零,则根据给定的偏移量跳转。

// PUSH0:将字节码中的0x0(十进制0)推送到栈顶。

// DUP1:复制栈顶元素。

// REVERT:回滚到先前的状态并停止执行合约。

// JUMPDEST:跳转目标。

// POP:从栈中弹出元素。

// PUSH1 0x3E:将字节码中的0x3E(十进制62)推送到栈顶。

// DUP1:复制栈顶元素。

// PUSH1 0x34:将字节码中的0x34(十进制52)推送到栈顶。

// PUSH0:将字节码中的0x0(十进制0)推送到栈顶。

// CODECOPY:将代码复制到内存中的指定位置。

// PUSH0:将字节码中的0x0(十进制0)推送到栈顶。

// RETURN:停止执行合约并将结果返回给调用者。

// INVALID:无效操作码,终止合约执行。

// PUSH1 0x80:将字节码中的0x80(十进制128)推送到栈顶。

// PUSH1 0x40:将字节码中的0x40(十进制64)推送到栈顶。

// MSTORE:将栈顶值存储到栈顶位置指定的内存位置。

// PUSH0:将字节码中的0x0(十进制0)推送到栈顶。

// DUP1:复制栈顶元素。

// REVERT:回滚到先前的状态并停止执行合约。

// INVALID:无效操作码,终止合约执行。

// LOG2:将栈顶两个元素的对数值推送到栈顶。

// PUSH5 0x6970667358:将字节码中的0x6970667358推送到栈顶。

// PUSH1 0x22:将字节码中的0x22(十进制34)推送到栈顶。

// SLT:如果第二个栈顶元素小于栈顶元素,则将1推送到栈顶;否则将0推送到栈顶。

// KECCAK256:将栈顶元素进行Keccak-256哈希运算。

// INVALID:无效操作码,终止合约执行。

// PUSH1 0x25:将字节码中的0x25(十进制37)推送到栈顶。

// MSTORE8:将栈顶元素的低8位存储到栈顶位置指定的内存位置。

// PUSH17 0x23C37BB780D303F1FB9B8C54DF281B06AC:将字节码中的0x23C37BB780D303F1FB9B8C54DF281B06AC推送到栈顶。

// CODECOPY:将代码复制到内存中的指定位置。

// MOD:计算栈顶两个元素相除的余数,并将结果推送到栈顶。

// PUSH2 0x9F42:将字节码中的0x9F42(十进制40770)推送到栈顶。

// PUSH1 0x23:将字节码中的0x23(十进制35)推送到栈顶。

// PUSH1 0x22:将字节码中的0x22(十进制34)推送到栈顶。

// CDIV:计算栈顶两个元素相除的商,并将结果推送到栈顶。

// PUSH5 0x736F6C6343:将字节码中的0x736F6C6343推送到栈顶。

// STOP:停止执行合约。

// ADDMOD:计算栈顶三个元素相加然后取模的结果,并将结果推送到栈顶。

// EQ:如果栈顶两个元素相等,则将1推送到栈顶;否则将0推送到栈顶。

// STOP:停止执行合约。

// CALLER:将调用合约的地址(调用者地址)推送到栈顶。

//uint256 b = 2;

// PUSH1 0x80:将十进制值128(0x80)推送到栈顶。

// PUSH1 0x40:将十进制值64(0x40)推送到栈顶。

// MSTORE:将栈顶的数值存储到栈顶位置指定的内存位置。

// PUSH1 0x2:将十进制值2(0x2)推送到栈顶。

// PUSH0:将十进制值0(0x0)推送到栈顶。

// SSTORE:将栈顶的数值存储到存储位置。

// CALLVALUE:将调用合约时发送的以太币数量推送到栈顶。

// DUP1:复制栈顶元素。

// ISZERO:判断栈顶元素是否为零。

// PUSH1 0x12:将十进制值18(0x12)推送到栈顶。

// JUMPI:如果栈顶元素为零,则根据给定的偏移量跳转。

// PUSH0:将十进制值0(0x0)推送到栈顶。

// DUP1:复制栈顶元素。

// REVERT:回滚到先前的状态并停止执行合约。

// JUMPDEST:跳转目标。

// POP:从栈中弹出元素。

// PUSH1 0x3E:将十进制值62(0x3E)推送到栈顶。

// DUP1:复制栈顶元素。

// PUSH1 0x1E:将十进制值30(0x1E)推送到栈顶。

// PUSH0:将十进制值0(0x0)推送到栈顶。

// CODECOPY:将代码复制到内存中的指定位置。

// PUSH0:将十进制值0(0x0)推送到栈顶。

// RETURN:停止执行合约并将结果返回给调用者。

// INVALID:无效操作码,终止合约执行。

// PUSH1 0x80:将十进制值128(0x80)推送到栈顶。

// PUSH1 0x40:将十进制值64(0x40)推送到栈顶。

// MSTORE:将栈顶的数值存储到栈顶位置指定的内存位置。

// PUSH0:将十进制值0(0x0)推送到栈顶。

// DUP1:复制栈顶元素。

// REVERT:回滚到先前的状态并停止执行合约。

// INVALID:无效操作码,终止合约执行。

// LOG2:将栈顶两个元素的对数值推送到栈顶。

// PUSH5 0x6970667358:将十进制值711931355112(0x6970667358)推送到栈顶。

// PUSH1 0x22:将十进制值34(0x22)推送到栈顶。

// SLT:如果第二个栈顶元素小于栈顶元素,则将1推送到栈顶;否则将0推送到栈顶。

// KECCAK256:将栈顶元素进行Keccak-256哈希运算。

// EXP:将栈顶两个元素相乘,并将结果推送到栈顶。

// PUSH1 0xFC:将十进制值252(0xFC)推送到栈顶。

// PUSH1 0xBB:将十进制值187(0xBB)推送到栈顶。

// PUSH1 0x2F:将十进制值47(0x2F)推送到栈顶。

// SWAP7:交换栈顶元素和第七个栈元素的位置。

// MSIZE:将当前内存大小推送到栈顶。

// MSTORE:将栈顶的数值存储到栈顶位置指定的内存位置。

// 0xB5:无效操作码。

// 0xC7:无效操作码。

// RETURNDATASIZE:将返回数据的大小推送到栈顶。

// 0xC6:无效操作码。

// PUSH18 0x7B124BD490A4EBA0F5F94C4192873ECC38C6:将十六进制值0x7B124BD490A4EBA0F5F94C4192873ECC38C6推送到栈顶。

// SUB:将栈顶两个元素相减,并将结果推送到栈顶。

// JUMPI:如果栈顶元素为零,则根据给定的偏移量跳转。

// PUSH5 0x736F6C6343:将十进制值79354843331(0x736F6C6343)推送到栈顶。

// STOP:停止执行合约。

// ADDMOD:将栈顶两个元素相加,然后对第三个栈顶元素取模,并将结果推送到栈顶。

// EQ:如果第二个栈顶元素等于栈顶元素,则将1推送到栈顶;否则将0推送到栈顶。

// STOP:停止执行合约。

// CALLER:将调用合约的地址推送到栈顶。

当时如果有两个变量就不同了:

// uint128 internal a = 1640784985;

// uint128 internal b = 1640784985;

//transaction cost:91224 execution cost:34946

// uint256 internal a = 1640784985;

// uint256 internal b = 1640784985;

//transaction cost:111307 execution cost:56675

留个疑问?有知道的吗,哈哈

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值