
Uniswap V3交易预计算技巧
Uniswap上做swap交易时,比如用usdt购买btc,会根据界面上输入的usdt数量,实时计算出可以swap到多少个btc,v2版本因为是应用了xy=k的公式,可以方便的计算出来。代码里通过getAmountOut和getAmountIn得到,这两个都是view函数,不需要消耗gas。而到了...
Meebits mint随机算法
先上代码function randomIndex() internal returns (uint) { uint totalSize = TOKEN_LIMIT - numTokens; uint index = uint(keccak256(abi.encodePacked(nonce, ms...

nftx闪电贷领取apecoin空投
已经是两个多月前的事件了,这几天才对这个tx进行了分析和fork重现,记录下来加深一下理解。apecoin的空投并没有限制调用方不能是合约地址,也不是用链下签名再到合约里验签的方式来领取空投,而是直接在合约里校验调用方的地址里有没有bayc/mayc,再加上apecoin当时的价格在8u左右,总体...
<100 subscribers

Uniswap V3交易预计算技巧
Uniswap上做swap交易时,比如用usdt购买btc,会根据界面上输入的usdt数量,实时计算出可以swap到多少个btc,v2版本因为是应用了xy=k的公式,可以方便的计算出来。代码里通过getAmountOut和getAmountIn得到,这两个都是view函数,不需要消耗gas。而到了...
Meebits mint随机算法
先上代码function randomIndex() internal returns (uint) { uint totalSize = TOKEN_LIMIT - numTokens; uint index = uint(keccak256(abi.encodePacked(nonce, ms...

nftx闪电贷领取apecoin空投
已经是两个多月前的事件了,这几天才对这个tx进行了分析和fork重现,记录下来加深一下理解。apecoin的空投并没有限制调用方不能是合约地址,也不是用链下签名再到合约里验签的方式来领取空投,而是直接在合约里校验调用方的地址里有没有bayc/mayc,再加上apecoin当时的价格在8u左右,总体...
Share Dialog
Share Dialog
多签钱包需要维护多个钱包所有者地址,满足一定数量的签名后,才可以发起交易。如果只用一个数组address[]去存储所有者地址,在检查某地址是否是所有者地址时需要遍历此数组,时间效率是O(n)。为了提高到O(1),通常做法可以是增加一个mapping(address=>bool)来存储某地址是否是所有者地址,但这样下来增加了storage的操作。Gnosis safe用了一个哨兵mapping来存储,可以改善此问题。
address internal constant SENTINEL_OWNERS = address(0x1); mapping(address => address) internal owners;
假设有A,B,C三个所有者地址,储存到owners后,变为
owners[address(0x1)] = A owners[A] = B owners[B] = C owners[C] = address(0x1)
这样,要判断某地址是否属于所有者地址时,只需O(1),且storage只用了一个mapping
function isOwner(address owner) public view returns (bool) { return owner != SENTINEL_OWNERS && owners[owner] != address(0); }
如果要增加一个D地址,则变为
owners[address(0x1)] = D owners[D] = A owners[A] = B owners[B] = C owners[C] = address(0x1)
时间效率也是O(1),相应代码是(此处只列出动态链表相关操作的代码)
function addOwner(address owner){ owners[owner] = owners[SENTINEL_OWNERS]; owners[SENTINEL_OWNERS] = owner; }
如果要删除B地址,则变为
owners[address(0x1)] = D owners[D] = A owners[A] = C owners[C] = address(0x1)
时间效率也是O(1),相应代码是(此处只列出动态链表相关操作的代码)
function removeOwner(address prevOwner,address owner){ owners[prevOwner] = owners[owner]; owners[owner] = address(0); }//这里需要先在链下查到要删除地址的前一个地址,再直接传参数到链上去删除,节省链上计算gas
总体来说,这种数据结构还是很实用的,在gas cost上也很有帮助。
多签钱包需要维护多个钱包所有者地址,满足一定数量的签名后,才可以发起交易。如果只用一个数组address[]去存储所有者地址,在检查某地址是否是所有者地址时需要遍历此数组,时间效率是O(n)。为了提高到O(1),通常做法可以是增加一个mapping(address=>bool)来存储某地址是否是所有者地址,但这样下来增加了storage的操作。Gnosis safe用了一个哨兵mapping来存储,可以改善此问题。
address internal constant SENTINEL_OWNERS = address(0x1); mapping(address => address) internal owners;
假设有A,B,C三个所有者地址,储存到owners后,变为
owners[address(0x1)] = A owners[A] = B owners[B] = C owners[C] = address(0x1)
这样,要判断某地址是否属于所有者地址时,只需O(1),且storage只用了一个mapping
function isOwner(address owner) public view returns (bool) { return owner != SENTINEL_OWNERS && owners[owner] != address(0); }
如果要增加一个D地址,则变为
owners[address(0x1)] = D owners[D] = A owners[A] = B owners[B] = C owners[C] = address(0x1)
时间效率也是O(1),相应代码是(此处只列出动态链表相关操作的代码)
function addOwner(address owner){ owners[owner] = owners[SENTINEL_OWNERS]; owners[SENTINEL_OWNERS] = owner; }
如果要删除B地址,则变为
owners[address(0x1)] = D owners[D] = A owners[A] = C owners[C] = address(0x1)
时间效率也是O(1),相应代码是(此处只列出动态链表相关操作的代码)
function removeOwner(address prevOwner,address owner){ owners[prevOwner] = owners[owner]; owners[owner] = address(0); }//这里需要先在链下查到要删除地址的前一个地址,再直接传参数到链上去删除,节省链上计算gas
总体来说,这种数据结构还是很实用的,在gas cost上也很有帮助。
No comments yet