gas优化之用 struct 减少参数数量

  • iszzm123
  • 发布于 2 小时前
  • 阅读 18

当把多个参数打包成struct,传递给函数的就只有一个引用(栈上的一个指针),而不是多个独立的值。如果struct在memory中:函数接收到的是一个memory指针(通常占用一个栈槽)。如果struct在calldata中:函数接收到的是一个calldata偏移量

当把多个参数打包成 struct,传递给函数的就只有一个引用(栈上的一个指针),而不是多个独立的值。

  • 如果 structmemory 中:函数接收到的是一个 memory 指针(通常占用一个栈槽)。
  • 如果 structcalldata 中:函数接收到的是一个 calldata 偏移量(同样一个栈槽)。
  • 如果 structstorage 中:传递的是 storage 引用(一个栈槽)。

函数内部访问字段时,通过指针 + 偏移量读取,这比逐个读取栈变量更紧凑、操作码更少。尤其是结合 calldata,完全避免了 ABI 解码的开销,因为你可以直接从 calldata 里按需 load,编译器不会生成一长串解码逻辑。

struct Order {
	address user;
	uint128 amount;
	uint64 deadline;
	bool active;
}

function process(Order calldata order) external pure returns (uint256) {
	// 只有 1 个 calldata 引用传进来,无繁重解码
	return _internalProcess(order);
}

function _internalProcess(Order calldata order) internal pure returns (uint256) {
	if (order.active && order.deadline > uint64(block.timestamp)) {
		return uint256(uint160(order.user)) + order.amount;
	}
	return 0;
}

Gas 变化

  • process 入口的 ABI 解码几乎为空:它只从 calldata 读取一个偏移量,赋给 order 指针。原本 4 个参数需要的 4 次 CALLDATALOAD + 可能的 AND 掩码操作全部取消。
  • 内部函数 _internalProcess 只接收一个指针,栈操作从 4 个值缩减为 1 个,字节码体积明显缩小。
  • 字段访问通过 CALLDATALOAD 按偏移读取,按需加载,不需要的字段甚至完全不读取。

实测中,这种优化能节省 数百到数千 gas,字段越多越明显。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
iszzm123
iszzm123
最近有应聘的意向