
万字研报:Solana上MEV的格局演进与是非功过
原文链接:点击详情 前言 solana 已然五年,其中 Jito(solana 上 MEV 基础设施龙头)的发展不足 3 年,但市占率飞速从最初的 15% 发展到如今的 95% ,可以说,大多数的 Solana 上的 Meme 买卖交易,都得经过他! 全程无广,请读者摆好板凳,点上收藏**,让十四君深度底层原理,带你逐渐揭晓**:什么是 Jito-solana?为什么他可以2 年占满市场?Solana 对比以太坊的核心机制的差异。你的交易为什么总是被夹?Solana 未来的 MEV 格局会如何发展?1、什么是 Jito-solana?当然 Solana 上做 mev 基础设施的不只是 Jito-solana(95% 市占率的龙头),还有其他 Paladin、Deeznode、BlockRazor、BloxRoute、Galaxy、Nozomi 等等,不同切入点的厂商。本文会以核心龙头的发展历程和技术原理来展开,在后续再点评这几家的优缺和切入点。1.1、Jito 的发展时间线首先,让我们用时间线来看看他的市占发展速度的神奇之处,请关注其中的质押率以及相关伙伴。21 年底成立22 年...

Delve into the risks behind the small matter of EVM-contract classification
In the field of smart contracts, the "Ethereum Virtual Machine EVM" and its algorithms and data structures are first principles. This paper starts from why the contract should be classified, combined with what kind of malicious attacks each scenario may face, and finally gives a set of relatively secure contract classification analysis algorithm. Although the technical content is higher, it can also be used as a miscellaneous reading A look at the dark forest of games between decentralized sy...

Research report of ten thousand words: The pattern evolution and merits and demerits of MEV on Solan…
introduction solana has been five years, of which Jito (the leader of MEV infrastructure on solana) has developed less than three years, but its market share has rapidly grown from the initial 15% to 95% today. It can be said that most of the Meme trading transactions on Solana have to go through him! The whole process is not wide, please readers set up the bench, click on the collection,Let the 14 Jun depth of the underlying principle, with you gradually revealed:What is Jito-solana? Why can...



万字研报:Solana上MEV的格局演进与是非功过
原文链接:点击详情 前言 solana 已然五年,其中 Jito(solana 上 MEV 基础设施龙头)的发展不足 3 年,但市占率飞速从最初的 15% 发展到如今的 95% ,可以说,大多数的 Solana 上的 Meme 买卖交易,都得经过他! 全程无广,请读者摆好板凳,点上收藏**,让十四君深度底层原理,带你逐渐揭晓**:什么是 Jito-solana?为什么他可以2 年占满市场?Solana 对比以太坊的核心机制的差异。你的交易为什么总是被夹?Solana 未来的 MEV 格局会如何发展?1、什么是 Jito-solana?当然 Solana 上做 mev 基础设施的不只是 Jito-solana(95% 市占率的龙头),还有其他 Paladin、Deeznode、BlockRazor、BloxRoute、Galaxy、Nozomi 等等,不同切入点的厂商。本文会以核心龙头的发展历程和技术原理来展开,在后续再点评这几家的优缺和切入点。1.1、Jito 的发展时间线首先,让我们用时间线来看看他的市占发展速度的神奇之处,请关注其中的质押率以及相关伙伴。21 年底成立22 年...

Delve into the risks behind the small matter of EVM-contract classification
In the field of smart contracts, the "Ethereum Virtual Machine EVM" and its algorithms and data structures are first principles. This paper starts from why the contract should be classified, combined with what kind of malicious attacks each scenario may face, and finally gives a set of relatively secure contract classification analysis algorithm. Although the technical content is higher, it can also be used as a miscellaneous reading A look at the dark forest of games between decentralized sy...

Research report of ten thousand words: The pattern evolution and merits and demerits of MEV on Solan…
introduction solana has been five years, of which Jito (the leader of MEV infrastructure on solana) has developed less than three years, but its market share has rapidly grown from the initial 15% to 95% today. It can be said that most of the Meme trading transactions on Solana have to go through him! The whole process is not wide, please readers set up the bench, click on the collection,Let the 14 Jun depth of the underlying principle, with you gradually revealed:What is Jito-solana? Why can...
Share Dialog
Share Dialog

Subscribe to shisi.eth

Subscribe to shisi.eth
如果你是WEB3加密界的新手,面对众多概念无从入手,那么欢迎你,来对地方了!!
本文围绕标准 ERC721协议,描述了Mint、 safeMint、 transfer等是如何实现资产管理的,并通过解读代码来了解它的安全性设计和以太坊数据上链成本构成。
1.所谓NFT资产是什么?
2.Mint和safeMint的差别
3.交易时会发生什么?有哪些细节设计
4.NFT哪些数据也存储在链上?
5.以太坊上存储有多贵?
Web3新手,有无技术背景均可:
研发——可无障碍阅读,理解精美的合约设计
非研发——可能读不懂列举的代码,但能体会标准协议的设计思路
在opensea上,可看到每个NFT都有个唯一的编号。
比如azuki系列中第4132号,在页面的Details栏目可以看到其合约地址,ID编号,部署所在公链等信息,而Properties栏目则是其设定的具备各种属性,对应的稀有度(非azuki本身携带,而是opensea整合计算的)。

而咱们回顾到源代码(此处取ERC721标准库openzepplin代码),会发现程序记录了全局性的两个字典类型的变量,通过 _owners中用数字映射地址的方式记录每一个ID 当前对应的所有者,同时也附带用_balances 记录了当前所有者总计持有的NFT数量
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
并且由于ERC721创新性的赋予了一个ID对应地址的变量 _owners,从而与ERC20仅_balances 进行地址与余额的管理,区分出了FT(同质化)与NFT(非同质化)的差别。
Mint 意思为铸造,即每个NFT的创造过程,例如之前的:当奈飞的NFT忘记了web2的业务安全
Mint 获取到该NFT的资产证明。
从源代码中可以看到,Mint 主要是进行了安全判断:
判断1:确保转入的不是0x00地址(黑洞地址无法转出,转入则资产损失)
判断2:确保此交易所操作的NFTID是不存在的
最终代码执行的操作是:
操作1:将转入地址的_balances 所持有总数加1
操作2:将对应 NFTID 的所有者修改为转入的地址
操作3:完成交易则发出emit 事件,可以让链下监听到这次交易的数据
/**
* @dev Mints `tokenId` and transfers it to `to`.
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
中间有_beforeTokenTransfer和_afterTokenTransfer 属于虚函数,作为标准,是让项目方可以再不修改标准协议的情况下增加一些特定的逻辑代码用的。
safeMint 意为安全的铸造,从代码实现中可以看到他本身也是调用了MInt 但是他额外增加了_checkOnERC721Received 的判断,这点是属于ERC165的标准,相当于在完成转入操作后,则判断对方地址,是否是黑洞地址(即无法发起交易NFT操作的地址)是防止转入对象为合约地址时候,其合约没有预设置好转出的函数,导致资产在内无法被转走,从而造成永久损失。
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to,uint256 tokenId,bytes memory _data)
internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
设计初衷可见:https://eips.ethereum.org/EIPS/eip-165
是让合约接口标准化的提案,在编程语法中interface 是接口的意思,在其中定义的函数可以不实现仅仅放上函数名字相关参数,在程序复杂的时候,相当于目录一般告诉别人我都有什么功能。
但是接口的写法各有千秋,名字定义参数类型,甚至是否存在都有不同,
所以此提案最终形成了ERC165标准,规范了接口的识别规则。
interface ERC165 {
/// @notice 查询合约所实现的接口
/// @param interfaceID 参数:接口ID
/// @return true 如果函数实现了 interfaceID (interfaceID 不为 0xffffffff )返回true, 否则为 false
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
使用流程是:
STEP 1 判断是否存在 supportsInterface 函数,并且其符合165标准
STEP 2通过 supportsInterface 函数,判断是否具有转出NFT的函数
(PS:让合约具备NFT接收转出功能,可通过引入 IERC721Receiver.sol 拓展包来实现)
标准协议设计有两种转移方式,transfer 和 transferFrom,作用于两种场景:
transfer 转移:由用户调用,将本消息发送的钱包所持有的NFTID转移到指定地址
transferFrom 从转移:用某机构调用,需要用户先授权某地址,让其有权可转移。
类比一下:
transfer 就是现金交易,从自己口袋里拿钱支付
transferFrom 就是扫码扣款,由店家申请扣款,受制于用户是否开通小额代扣权限
接下来咱们从代码来看看,其中可能有会意想不到的细节。
他会检测当前交易的 from 方是否是此NFTID的持有者,并且限制该NFT转入0x00地址。其次进行 from 转出地址和 to 转入地址的余额刷新,修改 _balances全局变量并且重新设置_owners此NFTID的所有者地址修改为to。
这里有个防护的细节会先执行_approve(address(0), tokenId); 清空历史授权,如果没有这一步,则资产完成了转移,但是其NFTID的转移授权依旧在,细思极恐:
function _transfer(address from,address to,uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);// Clear approvals from the previous owner
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
这里的交易本质调用的是_safeTransfer 所以他的核心逻辑是require 部分,
这的一大细节是:_msgSender() 这是openzepplin的标准库Context.sol 中的方法。
其实就是获取当前交易的发送者地址,但这里使用了封装版本,而不是直接使用msg.sender
是考虑到,可能存在一种交易类型“元交易” ,即交易的付费gas方和交易发起方不相同的情况。
所以一些处于中间环节的,类似library的合约需要考虑这种特殊情况。其余部分判断是确定是否有授权记录,易于理解,不作赘述
function safeTransferFrom(address from,address to,uint256 tokenId,bytes memory _data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data);}
交易的环节也看完后,其实很多新同学也顿感奇怪,原来我买的NFT只有一个ID的归属地址指向了我,从而达成了唯一性。那就算如此,稀有度信息放在哪里?我的NFT图像本身在那里?
这就是涉及到ERC721的元数据拓展IERC721Metadata.sol
要放什么都可以,但是项目方往往在链上只存储最基础的ID+IPFS的地址。
咱们可以通过之前Etherscan教程方法来看看一些项目数据有什么?
Azuki上合约地址是:0xed5af388653567af2f388e6224dc7c4b3241c544
通过Read Contract可以查阅到,其元数据只存放了ipfs上的指向地址
而近期兴起的Metaverse项目元宇宙土地sandbox和Decentraland ,以及去年火热的Axie Infinity ,基本链上存储元数据也只是ID+网址。

像mirror那些是专门设计低费用可进行高存储,一个块常规都是30M起步,大约是以太坊的1000倍。
这里是本文稍难的地方。咱们从源码来分析链上存储的成本构成以及金额换算
成本产生将有2个方面,按执行流程来看
用户发起一笔交易,将要写链上数据作为参数传入,其大小是一笔成本
交易执行合约代码,依据修改和使用,EVM计算消耗的gas成本。
咱们可以核对下以太坊黄皮书,里对交易数据大小所消耗gas有清晰的定义

可以看到交易所附带的参数的价格:
每笔交易都有21000 GAS需要支付
为交易的每个非零字节数据或代码支付68 GAS
为交易的每个零字节数据或代码支付4 GAS
所以如果是再 Mint 的时候,登记上若干NFT属性信息,交易的data部分会将abc等字符转成2个十六进制表示,而每个字符为一个八位二进制,等于一个byte。所以可以约等于将data的长度除以2作为byte数。
而1kb的数据,如果都是非0的有信息量的文本信息,则等于增加是68*1000=6.8W 的gas消耗。按20gwei的gas价格和2000的eth兑换美元价格,可以估算出,每上链1kb数据在交易发起端就要:
20*(21000+68000)*1e9/1e18 * 2000 = 3.5美金
由于交易发起后,还有智能合约上存储的逻辑,咱们从以太坊go源代码中(EIP1283),来分析具体的消费量,代码具体在函数内,太长了不全粘来:
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64)(uint64, error)
历史上GAS消耗的估算有经过若干迭代,如果是Petersburg或者 Constantinople 未激活的话,则不按下面逻辑进行计算
gas消耗计算,依赖3个种数据的管理形式(增删改)
从零值地址到非零值(NEW VALUE),每个存储槽需消耗2Wgas
从非零值地址到零值地址(DELETE),每个存储槽需消耗5Kgas,但会有奖励1.5W gas退回
从非零到非零(CHANGE),每个存储槽需消耗 200 gas
注意,上述每一个存储槽算32byte,1kb存储则是32个存储槽。Mint 的过程是新增存储,所以如果新增1kb的数据存储在链上代价将是64Wgas,换算成金额则是:
20*(640000)*1e9/1e18 * 2000 = 25 美金
真可谓寸土寸金!
欢迎各位同学从后台提交有趣的合约或交易哈希。
关注十四,用技术的眼光发现价值。

如果你是WEB3加密界的新手,面对众多概念无从入手,那么欢迎你,来对地方了!!
本文围绕标准 ERC721协议,描述了Mint、 safeMint、 transfer等是如何实现资产管理的,并通过解读代码来了解它的安全性设计和以太坊数据上链成本构成。
1.所谓NFT资产是什么?
2.Mint和safeMint的差别
3.交易时会发生什么?有哪些细节设计
4.NFT哪些数据也存储在链上?
5.以太坊上存储有多贵?
Web3新手,有无技术背景均可:
研发——可无障碍阅读,理解精美的合约设计
非研发——可能读不懂列举的代码,但能体会标准协议的设计思路
在opensea上,可看到每个NFT都有个唯一的编号。
比如azuki系列中第4132号,在页面的Details栏目可以看到其合约地址,ID编号,部署所在公链等信息,而Properties栏目则是其设定的具备各种属性,对应的稀有度(非azuki本身携带,而是opensea整合计算的)。

而咱们回顾到源代码(此处取ERC721标准库openzepplin代码),会发现程序记录了全局性的两个字典类型的变量,通过 _owners中用数字映射地址的方式记录每一个ID 当前对应的所有者,同时也附带用_balances 记录了当前所有者总计持有的NFT数量
mapping(uint256 => address) private _owners;
mapping(address => uint256) private _balances;
并且由于ERC721创新性的赋予了一个ID对应地址的变量 _owners,从而与ERC20仅_balances 进行地址与余额的管理,区分出了FT(同质化)与NFT(非同质化)的差别。
Mint 意思为铸造,即每个NFT的创造过程,例如之前的:当奈飞的NFT忘记了web2的业务安全
Mint 获取到该NFT的资产证明。
从源代码中可以看到,Mint 主要是进行了安全判断:
判断1:确保转入的不是0x00地址(黑洞地址无法转出,转入则资产损失)
判断2:确保此交易所操作的NFTID是不存在的
最终代码执行的操作是:
操作1:将转入地址的_balances 所持有总数加1
操作2:将对应 NFTID 的所有者修改为转入的地址
操作3:完成交易则发出emit 事件,可以让链下监听到这次交易的数据
/**
* @dev Mints `tokenId` and transfers it to `to`.
* Emits a {Transfer} event.
*/
function _mint(address to, uint256 tokenId) internal virtual {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId);
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId);
}
中间有_beforeTokenTransfer和_afterTokenTransfer 属于虚函数,作为标准,是让项目方可以再不修改标准协议的情况下增加一些特定的逻辑代码用的。
safeMint 意为安全的铸造,从代码实现中可以看到他本身也是调用了MInt 但是他额外增加了_checkOnERC721Received 的判断,这点是属于ERC165的标准,相当于在完成转入操作后,则判断对方地址,是否是黑洞地址(即无法发起交易NFT操作的地址)是防止转入对象为合约地址时候,其合约没有预设置好转出的函数,导致资产在内无法被转走,从而造成永久损失。
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/
function _safeMint(address to,uint256 tokenId,bytes memory _data)
internal virtual {
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, _data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
设计初衷可见:https://eips.ethereum.org/EIPS/eip-165
是让合约接口标准化的提案,在编程语法中interface 是接口的意思,在其中定义的函数可以不实现仅仅放上函数名字相关参数,在程序复杂的时候,相当于目录一般告诉别人我都有什么功能。
但是接口的写法各有千秋,名字定义参数类型,甚至是否存在都有不同,
所以此提案最终形成了ERC165标准,规范了接口的识别规则。
interface ERC165 {
/// @notice 查询合约所实现的接口
/// @param interfaceID 参数:接口ID
/// @return true 如果函数实现了 interfaceID (interfaceID 不为 0xffffffff )返回true, 否则为 false
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
使用流程是:
STEP 1 判断是否存在 supportsInterface 函数,并且其符合165标准
STEP 2通过 supportsInterface 函数,判断是否具有转出NFT的函数
(PS:让合约具备NFT接收转出功能,可通过引入 IERC721Receiver.sol 拓展包来实现)
标准协议设计有两种转移方式,transfer 和 transferFrom,作用于两种场景:
transfer 转移:由用户调用,将本消息发送的钱包所持有的NFTID转移到指定地址
transferFrom 从转移:用某机构调用,需要用户先授权某地址,让其有权可转移。
类比一下:
transfer 就是现金交易,从自己口袋里拿钱支付
transferFrom 就是扫码扣款,由店家申请扣款,受制于用户是否开通小额代扣权限
接下来咱们从代码来看看,其中可能有会意想不到的细节。
他会检测当前交易的 from 方是否是此NFTID的持有者,并且限制该NFT转入0x00地址。其次进行 from 转出地址和 to 转入地址的余额刷新,修改 _balances全局变量并且重新设置_owners此NFTID的所有者地址修改为to。
这里有个防护的细节会先执行_approve(address(0), tokenId); 清空历史授权,如果没有这一步,则资产完成了转移,但是其NFTID的转移授权依旧在,细思极恐:
function _transfer(address from,address to,uint256 tokenId) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId);
_approve(address(0), tokenId);// Clear approvals from the previous owner
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId);
}
这里的交易本质调用的是_safeTransfer 所以他的核心逻辑是require 部分,
这的一大细节是:_msgSender() 这是openzepplin的标准库Context.sol 中的方法。
其实就是获取当前交易的发送者地址,但这里使用了封装版本,而不是直接使用msg.sender
是考虑到,可能存在一种交易类型“元交易” ,即交易的付费gas方和交易发起方不相同的情况。
所以一些处于中间环节的,类似library的合约需要考虑这种特殊情况。其余部分判断是确定是否有授权记录,易于理解,不作赘述
function safeTransferFrom(address from,address to,uint256 tokenId,bytes memory _data) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransfer(from, to, tokenId, _data);}
交易的环节也看完后,其实很多新同学也顿感奇怪,原来我买的NFT只有一个ID的归属地址指向了我,从而达成了唯一性。那就算如此,稀有度信息放在哪里?我的NFT图像本身在那里?
这就是涉及到ERC721的元数据拓展IERC721Metadata.sol
要放什么都可以,但是项目方往往在链上只存储最基础的ID+IPFS的地址。
咱们可以通过之前Etherscan教程方法来看看一些项目数据有什么?
Azuki上合约地址是:0xed5af388653567af2f388e6224dc7c4b3241c544
通过Read Contract可以查阅到,其元数据只存放了ipfs上的指向地址
而近期兴起的Metaverse项目元宇宙土地sandbox和Decentraland ,以及去年火热的Axie Infinity ,基本链上存储元数据也只是ID+网址。

像mirror那些是专门设计低费用可进行高存储,一个块常规都是30M起步,大约是以太坊的1000倍。
这里是本文稍难的地方。咱们从源码来分析链上存储的成本构成以及金额换算
成本产生将有2个方面,按执行流程来看
用户发起一笔交易,将要写链上数据作为参数传入,其大小是一笔成本
交易执行合约代码,依据修改和使用,EVM计算消耗的gas成本。
咱们可以核对下以太坊黄皮书,里对交易数据大小所消耗gas有清晰的定义

可以看到交易所附带的参数的价格:
每笔交易都有21000 GAS需要支付
为交易的每个非零字节数据或代码支付68 GAS
为交易的每个零字节数据或代码支付4 GAS
所以如果是再 Mint 的时候,登记上若干NFT属性信息,交易的data部分会将abc等字符转成2个十六进制表示,而每个字符为一个八位二进制,等于一个byte。所以可以约等于将data的长度除以2作为byte数。
而1kb的数据,如果都是非0的有信息量的文本信息,则等于增加是68*1000=6.8W 的gas消耗。按20gwei的gas价格和2000的eth兑换美元价格,可以估算出,每上链1kb数据在交易发起端就要:
20*(21000+68000)*1e9/1e18 * 2000 = 3.5美金
由于交易发起后,还有智能合约上存储的逻辑,咱们从以太坊go源代码中(EIP1283),来分析具体的消费量,代码具体在函数内,太长了不全粘来:
func gasSStore(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64)(uint64, error)
历史上GAS消耗的估算有经过若干迭代,如果是Petersburg或者 Constantinople 未激活的话,则不按下面逻辑进行计算
gas消耗计算,依赖3个种数据的管理形式(增删改)
从零值地址到非零值(NEW VALUE),每个存储槽需消耗2Wgas
从非零值地址到零值地址(DELETE),每个存储槽需消耗5Kgas,但会有奖励1.5W gas退回
从非零到非零(CHANGE),每个存储槽需消耗 200 gas
注意,上述每一个存储槽算32byte,1kb存储则是32个存储槽。Mint 的过程是新增存储,所以如果新增1kb的数据存储在链上代价将是64Wgas,换算成金额则是:
20*(640000)*1e9/1e18 * 2000 = 25 美金
真可谓寸土寸金!
欢迎各位同学从后台提交有趣的合约或交易哈希。
关注十四,用技术的眼光发现价值。

<100 subscribers
<100 subscribers
No activity yet