自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 Solidity Uniswap V2 Flash loans

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

2024-03-28 10:29:13 521

原创 Solidity Uniswap V2 Router swapTokensForExactTokens

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

2024-03-28 10:25:52 484

原创 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 280

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

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

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

原创 Solidity Uniswap V2 Output amount calculation

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

2024-03-19 14:23:21 232

原创 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 255

原创 Solidity Uniswap V2 library contract

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

2024-03-15 15:29:28 489

原创 Solidity Uniswap V2 Router contract addLiquidity

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

2024-03-14 10:27:31 727

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

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

2024-03-13 15:24:16 622

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

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

2024-03-13 10:21:13 359

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

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

2024-03-13 10:20:55 531

原创 Solidity Uniswap V2 factory contract

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

2024-03-12 11:00:40 868

原创 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 435

原创 Solidity Uniswap V2 优化

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

2024-03-11 10:17:07 740

原创 Solidity Uniswap V2 价格预言机

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

2024-03-09 20:50:33 426

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

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

2024-03-08 17:16:45 792

原创 Solidity Uniswap V2 Pair中交换Token

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

2024-03-08 10:44:57 1092

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

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

2024-03-07 16:39:46 711

原创 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 371

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

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

2024-03-06 17:08:45 766

原创 Solidity Uniswap V2 核心框架

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

2024-03-06 16:49:04 397

原创 solidity Foundry开发工具

Foundry是一个用Rust语言编写的以太坊部署环境,能够帮助开发者管理依赖项、编译项目、运行测试、部署合约以及从命令行与区块链交互。由于最近开发公链使用了和foundry一样的evm crate,就安装了一下看看,后边可能需要对foundry进行二次开发;这次就简单的测试一下;安装这里我只写一下,我实践过方法;

2023-09-21 17:50:13 472

原创 RUST 每日一省:闭包

代码如下所示,先使用i32类型的值作为闭包参数,编译器会推断参数和闭包返回值的类型都为i32,这样i32类型会被锁定在闭包中。闭包的参数类型可以省略。, 表示闭包通过转移所有权来捕获环境中的自由变量, 同时意味着该闭包没有改变环境的能力, 只能调用一次, 因为该闭包会消耗自身。, 表示闭包以不可变借用的方式来捕获环境中的自由变量, 同时也表示该闭包没有改变环境的能力, 并且可以多次调用。, 表示闭包以可变借用的方式来捕获环境中的自由变量,同时意味着该闭包有改变环境的能力, 也可以多次调用。

2023-09-21 16:08:50 289

原创 RUST 每日一省:全局变量

Rust中允许存在全局变量。它们一般有两种:常数和静态值。

2023-09-14 15:10:14 874

原创 RUST 每日一省:模式匹配

我们经常使用let 语句创建新的变量绑定——但是 let 的功能并不仅限于此。事实上, let 语句是一个模式匹配语句。它允许我们根据内部结构对值进行操作和判断,或者可以用于从代数数据类型中提取值。如上所示,通过第二句,把一个组合数据结构,拆解开来, 分成了三个不同的变量。在let语句中, =号左边的内容就是模式, =号右边的内容就是需要匹配的内容。相当于从tuple变量中,提取了三个新的变量head、 center、 tail, 它们分别对应tuple的三个成员。

2023-09-06 12:36:29 585

原创 RUST 每日一省:关联类型

Trait中不仅可以包含方法、常量,还可以包含关联类型。关联类型(associated type)是trait中的类型占位符,它可以被用于trait的方法签名中。trait的实现者需要根据特定的场景来为关联类型指定具体的类型。通过这一技术,我们可以定义出包含某些类型的trait,而无须在实现前确定它们的具体类型是什么。Rust标准库中的Iterator就是一个带有关联类型的trait示例.type Item是一个关联类型,使用该类型来替代迭代中出现的值类型。

2023-05-15 14:06:44 677

原创 RUST 每日一省:解引用Deref

自动解引用虽然是编译器来做的, 但是自动解引用的行为可以由开发者来定义。通过实现 std::ops::Deref 和 std::ops::DerefMut trait,可以修改解引用操作符 * 和 . 在自定义类型上的行为。Deref的定义如下所示。DerefMut的唯一区别是返回的是&mut型引用。Sized;比如, 标准库中实现了Box的解引用:impl

2023-05-10 10:17:13 909

原创 solidity dapp ERC-165

用户可以通过调用此方法,输入相应查询的接口ID,查询该合约是否实现了对应的接口ID;接口ID(interface identifier)定义为接口中所有函数选择器的异或(XOR),下例中,通过calculateSelector函数计算Animal的接口ID。函数选择器,就是函数签名(如:"myMethod(uint256,string)")的 Keccak(SHA-3)哈希的前 4 字节。我们继续使用Animal这个例子,我们分别实现了Dog和Cat两个合约,都实现了Animal和IERC165接口;

2023-05-06 14:53:12 654

原创 RUST 每日一省:trait种类

它们具有较少的类型签名,其优点在于,在实际的编程中,它们允许用户一次性声明关联类型,并在任何特征方法或函数中使用 Self::A 作为返回类型或参数类型。标准库中的两个这样的示例是 Send 和 Sync 特征,它们在适当的时候由语言为大多数类型自动实现,并确定哪些值可以安全地发送和跨线程共享。trait的基本形式,很简单,但这只是trait的冰山一角。例如下例,我们给Number实现了From trait,这意味着,所有的i32,都可以通过Number::from()函数转化为Number。

2023-05-04 11:14:54 614

原创 RUST 每日一省:泛型约束——trait

使用泛型编程时, 很多情况下的行为并不是针对所有类型都实现的,用trait作为泛型的约束。例如,我们编写一个判断两个变量大小的泛型函数,编译时,会运行如下错误。这个编译错误是说, 由于泛型参数T没有任何约束——如果我们填入两个Struct类型,如何比较呢, 因此编译器认为a<b这个表达式是不合理的, 因为它只能作用于支持比较运算符的类型。编译器也进行了提示,只有impl了PartialOrd的类型, 才能支持比较运算符。修正如下。

2023-05-01 19:13:40 766

原创 solidity 安全 如何阻止重入攻击

我们使用合约的过程中,经常会遇到这种情况,智能合约能够调用外部的合约;这些外部合约又可以回调到调用他们的智能合约;在这种情况下,我们说智能合约被重新输入,这种情况被称为可重入性。正常使用的时候,是没有任何问题;如果攻击者,将攻击代码,插入到合约执行流程中,使得合约执行正常逻辑之外的攻击代码,就会给用户带来损失。当用户使用用户账户调用合约B时,属于正常调用,不会有问题;如果攻击者创建一个attack合约,去调用B时,就可以发生类似如下的过程;B又回调到attack。

2023-04-30 12:48:46 1207

原创 RUST 每日一省:泛型

泛型类型的结构体是指结构体的字段类型是泛型类型,它可以拥有一个或多个泛型类型。定义泛型结构体时,可以在结构体名称后面带上或等,在定义字段的类型时使用T或U。在implfor{}这个语法结构中, 泛型类型既可以出现在位置, 也可以出现在位置。函数的参数和返回值都可以是泛型类型,带有泛型类型的参数或返回值的函数叫作泛型函数。比如,Vec在使用中可以指定T的类型为i32或String等——Vec或者Vec。

2023-04-29 13:33:01 184

原创 RUST 每日一省:借用&引用

在下边例子中,为了在length()函数之后,继续使用变量s1,我们不得不将已经传入length()的s1,再返回来;引用是基于指针的实现, 它与指针的区别是,指针保存的是其指向内存的地址, 而引用可以看作某块内存的别名,使用它需要满足编译器的各种安全检查规则。下边length()和change()两函数,分别代表不可变借用和可变借用的实际用例——可以在不进行所有权转移的情况下,使用变量;这就使我们可以创建多个可变引用,当然,这些可变引用不会同时,这个可以看上边第二段代码,&和&mut同时出现。

2023-04-28 16:58:49 238

原创 solidity Dapp TimeLock时间锁工具

根据_target, _value, _func, _data, _timestamp从队列中取出交易,如果是待执行状态,接着判断时间知否满足条件,只有区块时间大于_timestamp,且小鱼_timestamp+宽限时间才能执行。加入队列由管理员调用。当满足条件 (当前区块时间+最小延期时间

2023-04-27 12:15:48 759

原创 RUST 每日一省:生命周期&作用域

此外,作用域支持互相嵌套,并且可以在子作用域中访问父作用域的元素,但反过来不行。如果我们需要在其作用域外继续使用它,要么转移所有权, 要么按位复制,就可以继续使用, 这取决于该变量是复制语义还是移动语义的。如果我们要把打印a的注释去掉,就会产生如下错误,a进入子作用域之后,发生所有权转移,在自作用结束的时候,释放了a,所以我们继续使用就会报错了。如果有其他变量进入了作用域,也是会发生所有权的变化;去掉注释之后,报错如下,说明t已经在Some(v)=> ()发生了所有权的转移,然后在作用域结束时被释放掉了;

2023-04-24 13:34:31 404

原创 RUST 每日一省:所有权

所有权是是Rust语言中的基础设施。Rust中的每个值都必定有一个唯一的所有者,所有者负责该值的释放和读写权限。

2023-04-22 12:46:54 338

原创 RUST 每日一省:if let & while let

这种混合语法可以提供更多的灵活性,并且一系列if let、else if、else if let分支中的条件也不需要彼此相关。if let块和while let块也会创建新的作用域, value是Option<String>类型, 所以在if let的赋值操作中会转移所有权,value将不再可用。当我们在使用match时,一定要完整匹配,如果你只需要判断某个特定分支时,这时候match就显得比较冗冗余,而if let可以只匹配感兴趣的某个特定的分支, 这种情况下的写法比match简单点。

2023-04-20 12:14:56 325

原创 RUST 每日一省:智能指针

更重要的是, 除了释放内存, Drop还可以做很多其他的工作, 比如释放文件和网络连接。智能指针是一些数据结构,它们的行为类似于指针但拥有额外的元数据和附加功能,这些功能会在创建和销毁指针时被调用和执行。例如Rc智能指针,这种指针会通过记录所有者的数量来使一份数据被多个所有者同时持有,并在没有任何所有者时自动清理数据。智能指针区别于常规结构体的特性在于, 它实现了Deref和Drop 这两个trait。Drop trait则使你可以自定义智能指针离开作用域时运行的代码,最重要的作用自动释放底层资源。

2023-04-19 11:20:12 237

原创 RUST 每日一省:copy&clone的异同

Copy和Clone两者的区别和联系如下。Copy内部没有方法, Clone内部有两个方法。Copy trait是给编译器用的, 告诉编译器这个类型默认采用copy语义, 而不是move语义。Clone trait是给程序员用的,必须手动调用clone方法, 它才能发挥作用。Copy trait不是想实现就能实现的, 它对类型是有要求的, 有些类型不可能impl Copy。而Clone trait则没有什么前提条件, 任何类型都可以实现。

2023-04-18 12:31:57 396

原创 solidity Dapp 从签名中提取消息签名地址

通常, ECDSA(椭圆曲线数字签名算法)包含两个参数, r 和 s. 在以太坊中签名包含第三个参数 v,它可以用于验证哪一个账号的私钥签署了这个消息。Solidity 提供了一个内建函数 ecrecover 它接受 r, s and v 作为参数并且返回签名这的地址。我们如何进行测试签名和验签呢;签名,在线下使用web3库,对信息进行签名;获取到hash和signature;解析signature,提取r,s,v;调用,ecrecover 函数,返回签名的地址;比较地址是否正确;

2023-01-31 22:28:19 477

GmSSL-master.zip

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

2020-05-23

Cadence_virtuoso部分快捷键

Cadence_virtuoso部分快捷键

2011-03-21

空空如也

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

TA关注的人

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