自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(145)
  • 资源 (2)
  • 收藏
  • 关注

原创 Solidity&Foundry BitMap

写合约的时候,记录某个账户的bool状态很常见,例如是否领取空投等,传统的写法mapping(uint256=>bool)中一个slot只能存储一个账户的信息,在其他语言中,我们经常会用到bitmap来表示标志位,如果我们可以将bitmap应用到合约中,可以节约很多gas;今天我们就开发一种适合solidity的bitmap;!!

2024-08-26 16:08:03 947

原创 Solidity&Foundry Merkle Airdrop

最下面的叶节点包含存储数据或其哈希值,每个中间节点是它的两个孩子节点内容的哈希值,根节点也是由它的两个子节点内容的哈希值组成。由于链上已经保存了一份roothash,只要在链上使用用户提供的信息生成的roothash与之前保存的一致,就可以证明该用户享有领取空投的权利。用户想要领取空投的时候,需要提供自己proof——其实就是mekle的验证路径,这个一般都是由项目方保存就行了,保存在链下就可以了。验证的时候,需要提供用户的proof,address,amount,就可以了;如果数据有误,或者给的。

2024-08-22 15:30:53 907

原创 Solidity&Foundry 荷兰拍卖

荷兰式拍卖,也称为公开降序拍卖,是一种拍卖类型,卖方首先设置起始价格、持续时间和折扣率。随着时间的推移,物品的价格会不断下降,直到预设的持续时间结束。然后使用approve给dauction赋予id为1的NFT的转移权限,这样方便拍卖成功的时候,dauction帮忙转移NFT;拍卖函数,获取当前的价格,判断拍卖人是否有足够的余额支付nft;获取当前的nft价格,如果还没有开始拍卖,就返回最大值;初始化函数,dropStep是需要计算出来的,其实就是用起始价格差除以总共的时间段数;:被拍卖nft的id;

2024-08-15 16:18:54 884

原创 Solidity&Foundry ERC4626

ERC4626简介ERC4626 协议是一种用于代币化保险库的标准。我们经常说 DeFi 是货币乐高,可以通过组合多个协议来创造新的协议;ERC4626 扩展了 ERC20 代币标准,旨在推动收益金库的标准化,它是 DeFi 乐高中的基础,它允许你把底层资产质押到金库合约中,从而获取一定比例的金库代币;你存入的底层资产存储在金库中的这段时间,会产生一定的收益——例如被用于借贷平台、收益聚合、流动资金池等;你可以在任何时间拿着金库代币赎回本金以及一定收益。ERC4626 主要逻辑。

2024-08-06 22:25:02 1055

原创 智能合约语言(eDSL)—— 并行化方案——调度算法

就是验证一个已经执行完交易的读写集,因为我们并发的而执行多个交易的时候,会导致id靠后的交易先于id考前的交易执行完,这样id靠后的交易,依赖的数据,可能会出现问题;这个时候,我们就需要验证tx7,因为存在这样的情况,tx7读了key1的值,虽然tx5写了key1的值,但是tx5执行的慢,导致tx7读取key1的时候,tx5还没有写入,如果按照我们之前的标准,并行执行完整个块与串行执行的结果要一致,那么这种情况下,tx7就需要重新执行,这就是验证任务的意义所在。就是一个交易的正常执行;

2024-07-18 10:21:28 1178

原创 Solidity&Foundry 安全审计测试 脏字节

将bytes数组从memory或calldata复制到storage,是以32字节为单位进行复制的,当长度不是32的倍数,额外字节会从calldata或memory复制到storage中。存储中的脏值只有在bytes数组中进行空的.push()时才可见。部署Dirtybytes合约,在合约初始化的时候,创建一个memory变量,将值赋给一个storage变量,然后使用空的push,就可以看到storage的非空值了;foundry 合约:测试版本是0.8.0,修改为0.8.15,就不会有问题了;

2024-07-11 15:35:40 189

原创 Solidity&Foundry 安全审计测试 绕过isContract()校验

鉴于Attack仍在其部署过程中,在isContract()方法中检查的Attack地址的extcodesize为零。依赖于extcodesize方法来实现检查存储代码的大小,我们可以确定给定地址是已部署的智能合约还是账户(EOA),但是这存在漏洞,很容易被攻击者绕过。如果目的是防止来自其他合约的调用,(tx.Origin == msg.sender)可以使用,尽管它也有缺点和潜在的漏洞。出于安全原因,某些智能合约方法被定义为只接受来自外部自有账户(EOA)的调用,而不接受来自其他智能合约的调用。

2024-07-04 15:12:13 509

原创 Solidity&Foundry 安全审计测试 memory滥用

函数updaterewardDebt的功能是,更新UserInfo结构体的rewardDebt值。为了节约gas,我们将变量用关键字memory声明了,这样会导致的问题是,在函数执行结束之后,rewardDebt的值并不会保存下来。因为一旦函数完成执行,内存就会被清除,所做的更改也会丢失。memory是一个关键字,用于临时存储执行合约所需的数据。它保存函数的参数数据,并在执行后清除。storage可以看作是默认的数据存储。它持久地保存数据,消耗更多的gas。在合约函数中滥用storage和memory。

2024-06-28 14:22:30 321

原创 Solidity&Foundry 安全审计测试 Delegatecall漏洞2

然后我们再次调用Proxy.pwn() 函数,现在相当于是调用Attack.pwn()函数,此时我们再来观察 Attack 合约的写法,发现其变量的存储位置故意和 Proxy合约保持一致,并且不难发现 Attack.pwn() 函数的内容也被攻击者写为 owner = msg.sender,这个操作修改了合约中存储位置为 slot1 的变量。这里需要一点小技巧,大家可以思考一下。2、攻击者 bob调用 Attack的attack函数,成功将 Proxy合约中的 owner 改成attack的地址。

2024-06-19 17:15:37 1055

原创 Solidity&Foundry 安全审计测试 Delegatecall漏洞

代理合约所有者操纵漏洞,是智能合约设计中的一个缺陷,允许攻击者操纵代理合约所有者。delegatecall 允许攻击者在代理合约的上下文中调用代理合约的 pwn() 函数,从而更改代理合约的所有者状态变量的值。合约中恰好有名为 pwn 的函数,该函数的作用是将合约中的 owner 修改为 msg.sender。delegatecall 函数的执行环境是调用者的环境,并且对于 storage 变量的修改是根据被调用的合约的插槽位置来修改的。在较为复杂的合约环境下需要注意变量的声明顺序以及存储位置。

2024-06-06 16:56:25 728 2

原创 Solidity&Foundry 安全审计测试 tx.origin 漏洞

在 Attack.attack() 中,它要求将 Alice 钱包中的所有资金转移到 Eve 的地址。由于 Wallet.transfer() 中的 tx.origin 等于 Alice 的地址、就授权了转账。钱包是一个简单的合约,只有所有者才能将以太币转移到另一个地址。由于tx.origin可能存在安全隐患,因此建议始终使用msg.sender进行授权或检查调用智能合约的地址。指调用智能合约功能的账户地址,只有账户地址可以是tx.origin。指直接调用智能合约功能的帐户或智能合约的地址。

2024-05-28 16:43:25 461

原创 智能合约语言(eDSL)—— 并行化方案——缓存&VM

这个并行算法最初其实是在aptos上实现的,aptos上使用的是move虚拟机,后来我把它移植到我们链上了,但是wasm虚拟机。还是费了不少事情。目前evm并行也比较火,像monad,sei等。经过调研发现,其实evm的并行,还是occ的路子,和aptos的方案也差不多,都是在这之上进行各种优化,比较链结果和vm都不一样。

2024-05-24 16:56:59 508

原创 Solidity&Foundry 安全审计测试 空循环

withdraw函数中for循环,是用来校验参数sigs的,但是如果有人传入一个空数组,那么就会直接跳过for循环的校验。检查签名数量 require(sigs.length > 0, “No signatures provided”);由于验证不充分,攻击者只需传递一个空数组即可绕过循环和签名验证。

2024-05-22 15:31:48 269

原创 Solidity&Foundry 安全审计测试 自毁漏洞

自毁漏洞是智能合约代码中的一个漏洞,允许攻击者通过攻击合约自毁来破坏其他的合约。实例中,漏洞产生的原因是攻击合约中的 dos 函数在收到大量eth后,执行自毁操作。自毁后,eth转入EtherGame 合约,导致EtherGame 合约的功能将永久失效,任何人都无法存入或领取奖励。不要依赖 this.balance 来跟踪存入的eth,而是使用一个状态变量来跟踪存入的总金额。需要注意的是攻击者的5个eth不是调用deposit函数存入的,所以winner并没有被设置。现在,没有人可以存款,也无法设定胜负。

2024-05-17 16:52:26 288

原创 智能合约语言(eDSL)—— 并行化方案

Block-STM:一个智能合约并行执行引擎,围绕着软件事务性内存的原则建立的(Software Transactional Memory)。Transaction组成block,每个block在不同的节点执行后都需要具有相同的结果。Block-STM的输入是一个区块(Block),其中包含n个预设了顺序的交易,tx1,tx2…,txn,然后并发执行区块并产生最终状态,但是最终状态与,按顺序执行tx1,tx2,…,txn——每个txj在txj+1开始前执行完成的状态——的状态保持一致。

2024-05-16 16:27:56 835

原创 智能合约语言(eDSL)—— 并行化概述

到目前为止,一个简单的合约语言与合约虚拟机已经完成了;接下来,我们让我们的整个系统可以并行化;

2024-04-25 14:07:27 787

原创 智能合约语言(eDSL)—— 测试

init_xq这个函数可以看一下合约里,虽然没有这个名字的函数,但是却可以正常调用,这是因为我们用宏修改了名字,让每个合约的初始化函数,都统一为init_xxx.大部分参数没有什么特别的,这里需要注意的是,合约的参数,是json格式,需要提前转换好;如何写合约,与编译之前的文章已经写过了,准备好.wasm文件。预编译需要借助wasmtime,生成一个engine的实例。参数依次是,函数名,上下文,合约字节码,token;2.3准备链的上下文。

2024-04-24 14:49:00 807 1

原创 智能合约语言(eDSL)—— wasmtime实现合约引擎补充

就是我们定义链上下文,这样用户在调用合约中的获取合约地址的接口,就会调用到wasmtime中linker中定义的get_owner,而get_owner中,又会从context中获取到context中的合约地址,返回将他作为返回值返回给用户,其实是写入内存中的,这样合约在运行的过程中,就可以获取到合约地址了。我们在创建wasmtime的时候,可以创建一个监控线程,如果wasmtime执行时间超过了我们设定的时间,就会停止wasmitme,然后返回错误。当我们再次使用的时候,需要调用如下函数解码,

2024-04-24 10:30:01 950 1

原创 智能合约语言(eDSL)—— 如何使用wasmtime运行合约

在我们使用高级语言生成了智能合约——WASM之后,接下来就是对智能合约——WASM的使用。首先,我们需要引入wasmtime库,使用wasmtime运行我们的合约。

2024-04-23 15:13:15 994

原创 Solidity Uniswap V2 Flash loans

Flash loans是一种非常强大的金融工具,在传统金融中没有类似的工具。它是一种无限制、无抵押的贷款,必须在接受贷款的同一交易中偿还。Uniswap 就是能提供闪电贷款的平台之一。让我们把它们添加到合同中,看看它们是如何工作的。关于闪电贷款的实现,你需要知道的第一件事就是它们只能由智能合约使用。下面是闪贷的借款和还款方式:1一个智能合约从另一个合约借入闪贷。2出借合约向借款合约发送代币,并调用该合约中的一个特殊函数。

2024-03-28 10:29:13 797

原创 Solidity Uniswap V2 Router swapTokensForExactTokens

在计算输入金额时,我们希望保证计算出的金额能达到要求的输出金额。我们不会实现所有的方式,但我想向大家展示如何实现倒置交换:用未知量的输入Token交换精确量的输出代币。由于我们知道输出金额,并希望找到输入金额,因此我们从路径的末尾开始,以相反的顺序将输入金额填入金额数组。同样有趣的是,即使金额是输入的,我们也可以使用相同的 _swap 函数。现在,我们要找到的不是 Δy,而是 Δx:我们知道想要得到的输出Token的确切数量,但不知道需要提供多少输入Token。同样,在应用基本的代数运算后,我们可以得到。

2024-03-28 10:25:52 586

原创 Solidity Uniswap V2 Router swapExactTokensForTokens

如果我们想直接用Token A 交换Token B,路径将只包含Token A 和Token B 的地址。如果我们想通过Token B 将Token A 换成Token C,路径将包含Token A 地址、Token B 地址、Token C 地址;之所以需要排序,是因为在pair合约中,Token地址是按升序存储的,但在路径中,它们是按逻辑排序的:输入Token在前,然后是 0 个或多个中间输出Token,最后是最终输出Token。这样可以节省gas。算出金额后,我们需要找到最终Token的地址。

2024-03-21 15:46:41 446

原创 智能合约语言(eDSL)—— 使用rust实现eDSL的原理

宏在 Rust 语言中是一种功能,能够在编译实际代码之前按照自定义的规则展开原始代码,从而能够达到修改原始代码的目的。通过 Rust 语言的宏系统,不仅能够实现 C语言的宏系统所提供的模式替换功能,甚至还能够控制编译器的行为、设计自己的语法从而实现 eDSL,所以我们正是基于 Rust 语言的宏系统实现的 eDSL。在编译器的广义定义中,编译器是一种能够将以某种编程语言(原始语言)书写的源代码转换成另一种编程语言(目标语言)的计算机程序,因此我们的eDSL在一定程度上扮演了编译器的角色。

2024-03-19 14:40:53 1896 1

原创 Solidity Uniswap V2 Output amount calculation

在恒定产品交换中,价格只是储备之间的一种关系--我们已经在 ZuniswapV2Library 的报价功能中实现了价格计算。然而,在实际进行交换时,这个价格是不正确的,因为它只代表了某一时刻储备之间的关系。但在进行互换时,储备量会发生变化,我们实际上期望的是价格随着储备量的变化而下降。这是一个非常简洁明了的公式,它表明swap后储备金的乘积必须等于swap前储备金的乘积,这就是恒等乘积公式的定义。在交易中,价格在某种意义上是一个中间实体:重要的是你拥有的token数量和你换取的token数量。

2024-03-19 14:23:21 306

原创 Solidity Uniswap V2 router contract Liquidity removal

因此,它的函数可以执行多个操作,而 pair 合约中的函数只能执行一个核心操作。除此之外,Router 的函数是通用的--它们可以用于与任何pair进行交互。3、amountAMin、amountBMin 是我们在销毁 LP-token时希望获得的token A 和token B 的最小数量。1、tokenA 和 tokenB 是pair的两个地址。2、将用户的 LP-token转移到pair合约中。1、抽象pair--用户操作token而非pair。3、从pair中移除用户的流动性。

2024-03-18 15:41:01 332

原创 Solidity Uniswap V2 library contract

在 Solidity 中,库是一种无状态合约(即它没有可变状态),它实现了一组可被其他合约使用的函数--这是库的主要目的。函数的第一步是token地址排序--当我们想通过token地址查找pair地址时,总是要这样做。这就是我们下一步要做的事情:有了factory地址和排序过的token地址,我们就能获得pair地址--我们接下来会看看 pairFor 函数。在交换中,使用的是基于恒积公式的公式。Uniswap 使用的是更先进的方法,我们可以从 CREATE2 操作码的确定性地址生成中获的启发。

2024-03-15 15:29:28 555

原创 Solidity Uniswap V2 Router contract addLiquidity

在这个函数中,我们要找到满足我们所需和最低金额的流动性金额。由于从我们在用户界面选择流动性金额到我们的交易被处理之间存在延迟,实际reserve比率可能会发生变化,这将导致我们损失一些 LP-token(作为对存入不平衡流动性的惩罚)。报价是库合约中的另一个函数:通过输入金额和配对储备金,计算输出金额,即tokenA 的价格乘以token B 的输入金额。如果储备金是空的,那么这是一对新的货币对,这意味着我们的流动性将决定储备金比率,这意味着我们不会因为提供不平衡的流动性而受到惩罚。

2024-03-14 10:27:31 996

原创 RUST 每日一省:rust logo收集

rust的logo集合,看看有没有你喜欢的,挑一个吧;下边只是挑选了几个,更多的还是看github吧。

2024-03-13 15:24:16 786

原创 RUST 每日一省:迭代器2

例如,HashSet、BTreeSet 和BinaryHeap 就没有对可修改引用实现 IntoIterator,因为修改它们的元素可能违背类型的不变性,比如被修改的值变成不同的散列值或者相对周边元素做了不同排序,导致修改后把元素放到错误的位置上。不过,由于所有的迭代器都是惰性的,必须使用一个消费器来获取迭代器适配器的调用结果。通过iter方法将数组转换为迭代器,再使用map方法对原迭代器中的每个元素调用闭包执行加1操作并生成一个新迭代器,最后调用collect方法将新迭代器中的元素收集到动态数组中。

2024-03-13 10:21:13 406

原创 智能合约语言(eDSL)—— 实现合约语言中调用链上数据

写合约的时候,我们需要获取链上的数据,但是在你编译合约的时候,合约没有这个能力,所以,我们把它做成一个接口,等到真正在链上执行的时候,wasm就可以帮你把它链接到对应的数据上,wasm的这部分,我们下次介绍wasm虚拟机部分的时候,在介绍。wasm_import_module则是定义wasm的input模块的名字,后边有机会,可以用rust实现版wasm,详细说一下,wasm的构造;实际上他是由contractcontex实现的,它的定义是空,因为我们需要的数据,都在链上,所以这里定义一个空的;

2024-03-13 10:20:55 643

原创 Solidity Uniswap V2 factory contract

新地址是根据部署者合约的 nonce 计算出来的,这与手动部署合约时确定合约地址的方式相同。你不需要知道 nonce,只需要知道已部署的合约字节码(它是静态的)和盐(它是由你选择的字节序列)。我们通过散列一对token的地址来创建salt,这意味着每一对独一无二的token都会产生一个独一无二的salt,每一对令牌都会有独一无二的salt和地址。工厂合约是所有已部署pair合约的注册表。factory合约还简化了pair合约的部署:无需手动部署pair合约,只需调用factory合约中的方法即可。

2024-03-12 11:00:40 1009

原创 RUST 每日一省:迭代器1

这个into_iter() 方法的receiver是self, 而不是&self, 执行的是move语义。这个语法的原理其实就是调用<container>.into_iter() 方法来获得迭代器, 然后不断循环调用迭代器的next() 方法, 将返回值解包,赋值给<item>, 然后调用<body>语句块。Item 是迭代器产生值的类型。IntoIter 是迭代器值本身的类型,而 Item 是它产生值的类型。这两个例子中的iter必须是可变的,因为调用next方法改变了迭代器内部用来记录序列位置的状态。

2024-03-12 10:48:50 480

原创 Solidity Uniswap V2 优化

原因是每个状态变量对应一个特定的存储槽,而 EVM 使用 32 字节的存储槽(每个存储槽正好是 32 字节)。当然,我们无法检查代币合约的执行情况,也无法确定代币是否真的进行了转移,但我们至少可以检查转移结果。EVM 的每个操作都会消耗一定量的gas。简单的运算,如算术运算,消耗的gas很少,但有些运算消耗的gas很多。这里的调用是address的一个方法,这是一个底层函数,可以让我们对合约调用进行更精细的控制。整数溢出是指增加整数变量的值,使其大于最大值,这将导致溢出:该值从0,重新开始计数。

2024-03-11 10:17:07 811

原创 Solidity Uniswap V2 价格预言机

套利者使 Uniswap 的价格尽可能接近中心化交易所的价格,这也可以看作是将中心化交易所的价格反馈到区块链上。另一方面,reserve存储为 UQ112.112 数字的整数部分,这就是为什么在计算价格前要乘以 2**112 的原因。为了做到这一点,合约存储了累计价格:在每次交换之前,它都会计算当前的边际价格(不包括费用),然后乘以上次交换后的秒数,再把这个数字加到前一个数字上。对于价格oracle功能,Uniswap V2 使用边际价格,它不包括滑点和交换费,也不取决于交换量。让我们来实现价格累积。

2024-03-09 20:50:33 556

原创 智能合约语言(eDSL)—— proc_macro实现合约init函数

我们通过属性宏来实现合约的init函数,call函数其实和init是类似的;构建属性宏,要在cargo.toml里面设置一些参数,这是必须的。一般来说,过程宏必须是一个库,或者作为工程的子库,不能单独作为一个源文件存在。,这个是用来解析语法树(AST)的。各种语法构成,解析语法树,生成rust代码,从而实现你想要的新功能。和。

2024-03-08 17:16:45 900

原创 Solidity Uniswap V2 Pair中交换Token

有趣的是,我们可以提前做这件事,反而是未了更安全,后边我们会介绍原因,也许你现在就知道了原因。同样,由于整除的原因,我们必须将余额乘以 1000,金额乘以 3,以 "模拟 "输入金额乘以 0.003(0.3%)。我们预计这个合约token的余额与其reserve不同,我们需要确保它们的乘积等于或大于当前储备的乘积。接下来,我们要为调整后的余额计算一个新的 K,并将其与当前的 K 进行比较。因此,在这几行中,我们发现了新的余额:它们不包括输出金额,但包括输入金额。2.保证所有的交易都是在正确的汇率下进行的。

2024-03-08 10:44:57 1346

原创 RUST 每日一省:发布到crates.io

github是开源代码分享的地方,rust的开源项目除了github,我们还可以将其发布到上,然后其它用户就可以使用cargo进行安装使用了。其实步骤很简单,只有三条命令了,我们一次来看一下。

2024-03-07 16:39:46 862

原创 Solidity Uniswap V2 Pair中移除流动性

我们在这里看到的是,我们损失了 500 wei的Token 0!如果我们向另一个用户初始化的池提供了不平衡的流动性,会怎么样呢?让用户向合约发送一定数量的 LP-token,在合约中计算出用户可以获取的token后,销毁 LP-token。简而言之,返回的Token数量,与持有的LP-Token数量与LP-Token总供应量成正比。你的LP-Token份额越大,你在burn后从reserve获得的份额就越大。我们可以看到,除了发送到零地址的最低流动性外,Pool又回到了未初始化的状态。

2024-03-07 14:54:53 490

原创 Solidity Uniswap V2 Pair中添加流动性

添加流动性的功能的用户入口,UniswapV2在UniswapV2Router中实现,它用来计算新的流动性并发行LP-Token,流动性管理简单地视为LP-Token管理。当你为一个pair增加流动性时,合约会创造LP Token;当你移除流动性时,LP-Token就会被销毁。pair合约中的添加流动性函数,是只执行核心操作的低级函数。

2024-03-06 17:08:45 1375

原创 Solidity Uniswap V2 核心框架

Uniswap V2的核心架构思想是池化:流动性提供者可以将其流动性抵押在合约中;这种抵押流动性允许任何人以去中心化的方式进行交易。交易者支付少量手续费,会累积在合约中,然后由所有流动性提供者共享。

2024-03-06 16:49:04 466

GmSSL-master.zip

gmssl的安装包,gmssl是国密版本的openssl,适用于软件开发中想要使用的国密openssl的需求;gmssl支持国密非常好;

2020-05-23

Cadence_virtuoso部分快捷键

Cadence_virtuoso部分快捷键

2011-03-21

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除