) 案例分析 下面我们考虑一个简单的例子,我们有一个钱包合约,当调用withdraw()函数时,它会逐渐的从钱包中取出ether,合作伙伴也可以添加他们的地址,并花费gas费用来调用withdraw()...函数,然后给予合作伙伴和业主总合同余额的1%。...contractBalance() view returns (uint) { return address(this).balance; } } 注意,在第18行,我们执行一个外部调用,将合同余额的...,他们可以将合作伙伴地址设置为攻击合同地址,并将所有资金永远锁定在TrickleWallet中 防御措施 为了防止这种DOS攻击,请确保在外部调用中指定gas stipend,以限制该事务可以使用的gas...(highestBid))会因为攻击合约的fallback()函数无法接收ether而一直为false,最后攻击合约以较低的ether赢得竞标。
编写水龙头合约 对于我们的第一个例子,我们将编写一个控制水龙头的合约。我们已经在 Ropsten 测试网络上使用了一个水龙头来测试 ether。...它使用内置的 Solidity 函数 require 来测试一个前提条件,即 withdraw_amount 小于或等于 100000000000000000 wei,这是 ether 的基本单位,相当于...如果我们创建一个将 ether 发送到合约地址的交易,就好像它是钱包一样,这个函数将处理它。 在我们的默认函数下面是最后的结束花括号,它表示了合约 Faucet 的定义结束。...只要有人将某个交易发送到合约地址,就会导致合约在 EVM 中运行,并将该合约作为其输入。 发送到合约地址的交易可能包含 ether 或数据或两者。如果它们含有 ether,则将其“存 入”合约余额。...它看起来像这样: function () public payable {} 当你将交易发送到合同地址时,没有数据指定要调用的函数,它会调用此默认函数。
也就是用户在以太坊的测试网,通过水龙头领取测试币的过程。...第五行msg.sender.transfer(amount);msg.sender表示当前合约调用的地址transfer(amount) 表示转账的数量第六行function() public payable...此函数不能有参数,不能返回任何值。如果没有其他函数与给定的函数标识符匹配,或者如果根本没有提供数据,将执行一个合约的调用。此外,每当合同接收没有数据的纯Ether时,会执行回退函数。...此外,为了接收Ether,回退函数必须标记为payable。如果没有这样的函数,合约不能通过常规transactions接收Ether。...通俗地讲,我们部署这个水龙头合约,是不需要转账ETH的,只需要花费gas。如果没有回退函数,合约不能通过常规transactions接收Ether。
并且,开发者在学习Solidity的时候,容易产生一个误解,那就是一个合约只能通过payable函数接收Ether,而没有考虑到接收Ether,而不执行任何函数的情况。...此类合约面对强制将Ether发送到合约的漏洞利用是非常脆弱的。真是应验了那句老话,有钱能使鬼推磨。 具体案例分析 一. 发送和接收以太币存在的安全风险 1....这意味着,任何攻击者都可以创建带有selfdestruct()函数的合约,向其发送Ether,调用 selfdestruct(target) 并强制将 Ether 发送至 target 合约。...预先发送的 Ether 合约不使用 selfdestruct() 函数或调用任何 payable 函数仍可以接收到 Ether 的第二种方式是把 Ether 预发送到合约地址。...攻击者可以通过上述提到的三种方式将ether置入合约: 比如第一种方式,自毁: 部署合约的时候在交易中附加0.1 ether,然后调用attack函数自毁合约,此时将会把0.1 ether发送到案例合约
漏洞 当合约将 Ether 发送到未知地址时,可能会发生此攻击。攻击者可以在 Fallback 函数中的外部地址处构建一个包含恶意代码的合约。...不期而至的 Ether 通常,当 Ether 发送到合约时,它必须执行回退功能或合约中描述的其他功能。这里有两个例外,合约可能会收到了 Ether 但并不会执行任何函数。...正如我们将看到的,错误地使用 this.balance 会导致这种类型的严重漏洞。 有两种方式可以将 Ether(强制)发送给合约,而无需使用 payable 函数或执行合约中的任何代码。...这意味着,任何攻击者都可以创建带有 selfdestruct() 函数的合约,向其发送 Ether,调用 selfdestruct(target) 并强制将 Ether 发送至 target 合约。...Ether 存储量,并且这也是我们执行需求和测试时用到的变量。
,它会把这四个字节当作函数的id来寻找调用函数,而一个函数的id在以太坊的函数选择器的生成规则里就是其函数签名的sha3的前4个bytes,函数前面就是带有括号括起来的参数类型列表的函数名称。...,然后它会把合约里剩余的资金发送给参数所指定的地址,比较特殊的是这笔资金的发送将无视合约的fallback函数,因为我们之前也提到了当合约直接收到一笔不知如何处理的eth时会触发fallback函数,然而...King 闯关要求 合同代表一个非常简单的游戏:谁给它发送了比当前奖金还大的数量的以太,就成为新的国王。...ether的函数是call.value,发送完成后,它才在下面更新了sender的balances,这里就是可重入攻击的关键所在了,因为该函数在发送ether后才更新余额,所以我们可以想办法让它卡在call.value...这里不断给我们发送ether,同样利用的是我们熟悉的fallback函数来实现。
.gas().call.vale()()函数都可以用于向某一地址发送ether,其差别如下: a、transfer转账 transfer函数是最常用的转账函数,它的作用是将合约中的以太币或代币转移到指定的地址...,如果转账失败该函数将抛出异常并回滚所有更改,其语法如下: function transfer(address payable recipient, uint256 amount) public returns...,同时我们注意到这里它用来发送ether的函数是call.value,发送完成后,它才在下面更新了sender的balances,这里就是可重入攻击的关键所在了,因为该函数在发送ether后才更新余额,...什么条件下可以调用授权转账函数进行转账、质押逻辑如何设计、什么时候开始游戏、什么时候进行分红、分红比例如何设计、那些人员可以分红、分红的层级如何设计、邀请奖励如何设计等等,不同类型的智能合约有不同的业务需求和不同的业务场景...黑盒测试是指测试人员不知道智能合约的实现细节,只测试其功能是否符合预期,白盒测试则是指测试人员了解智能合约的实现细节,测试其逻辑是否正确、代码是否规范、是否存在漏洞等,在测试时需要保障测试用例足够的多,
) 与地址类型基本相同,不过多出了 transfer 和 send 两个成员变量 两者区别和转换 Payable 地址是可以发送 ether 的地址,而普通 address 不能 允许从 payable...,那同样可以显式转换为 address 或者 address payable 类型 地址类型成员变量 .balance (uint256) 该地址的 ether 余额,以Wei为单位....transfer(uint256 amount) 向指定地址发送数量为 amount 的 ether(以Wei为单位),失败时抛出异常,发送 2300 gas 的矿工费...pure:纯函数,不允许修改或访问状态 view:不允许修改状态 payable:允许从消息调用中接收以太币Ether 。...函数assert和require可用于判断条件,并在不满足条件时抛出异常 assert() 一般只应用于测试内部错误,并检查常量\ require() 应用于确保满足有效条件(如输入或合约状态变量),或验证调用外部合约的返回值
= 10 ether; if (!...and send ether } 上面的代码中 !...第一个是用于提现的函数调用了存在重入漏洞的智能合约的withdraw()函数发送10个以太到hacker智能合约中,这样就会触发在hacker合约中定义的 function() payable {}这个回调函数...最后,只需围绕我们构建的步骤进行测试,例如检查溢位和下溢位、测试函数的极限、确保返回值的格式正确,等等。 许多以智能合约为中心的分布式应用程序都实现了各种软件工具来辅助审计实践。...还有像Bountyone这样的分散审计平台,当工具不足时,它们会将公司和自由审计师聚合在一起。 提供后续步骤 根据发现的漏洞的严重程度,建议将重点放在合同的某些方面进行改进。
这篇文章涵盖了什么内容: 时间锁定钱包(Time-locked Wallets)的应用 开发环境设置 使用松露框架进行智能合约开发 固体合约的说明 如何编译,迁移和测试智能合约 使用ÐApp与浏览器的智能合约交互...在这篇博客文章中,我们将探讨一些不同之处:将资金锁定在加密钱包合同中的想法。这个想法本身有各种用例。 归属于ICO 有几个例子,但目前锁定资金的最常见原因可能是“归属”。...由于名称与我们的合同名称完全相同,因此它是构造函数,创建合同时仅调用一次。...如果有人向本合同发送ETH,我们会很乐意收到。合同的ETH余额将会增加,并且会触发Received事件。要使任何其他功能接受传入的ETH,您可以使用payable关键字标记它们。...其次,工厂合同允许轻松,轻松地创建TimeLockedWallet合同,而无需提供任何开发设置。所有你需要做的就是从另一个钱包或ĐApp调用一个函数。
创建前预先发送Ether、3. 为其挖矿。 解题流程 目标是使合同余额大于零。...public{ selfdestruct(_addr); } } 给自己的合约发送一些ether、调用ForceSendEther,通过自毁,将ether强行发送到另一个合约...这里就不做测试了。 Privacy 考察知识点 内部存储结构 web3 api的使用。...就在我们将 unlocked 设置为 true 之时,这样的 _name 值将传入 [23] 行的 require() 函数。在Remix中试试这个。...Alien Codex 考察知识点 EVM汇编、abi等 合约是如何从零创建的 OOB (out of boundary) Attack 解题过程 这个题也比较复杂,要比较清楚内部实现才可以。
但本文将介绍两个例外情况,以太币可以存入合约中却不运行任何代码。 这些依赖所转移的以太币数量的合约,在以太币被强制发送时有被攻击的风险。...而漏洞的关键就是(不正确)使用了this.balance。 有两种方法,可以(强制)将以太币转给没有使用 payable 函数或者没有执行任何代码的合约: 1....因此,selfdestruct函数可以强制转移以太币到任何合约,不管这个合约中存在什么代码,甚至根本没有 payable 函数。...根据 32 行的条件claimReward函数总是会返回(即,因为this.balance比finalMileStone大)。 如何避免 这种类型的漏洞通常都是由于滥用this.balance导致的。...如果要求存储的以太币是一个确切数量,应该自定义变量,在 payable 函数中递增,这样才能安全的追踪存入的以太币。这种变量不会受到调用selfdestruct强制发送以太币的影响。
在一定时间(deadline)内,质押(stake)一定数量(threshold)的代币。到期之后可以将代币转入(execute)到另一个合约,也可以将代币提取出来(withdraw)。...5,测试stake4.2 execute筹集到的资金,在满足一定条件之后,转移给另一个合约中。...stake 一些币到达上限测试 execute4.3 withdraw将质押的钱提取出来,这个比较简单,就是将钱转移出来即可。...timeLeft函数首先要有一个deadline变量如何修饰这些函数function stake() public payable deadlineReached(false) stakeNotCompleted...execute函数stake可以被外部合约调用的函数receive() external payable { stake(); }最终代码如下:// SPDX-License-Identifier
攻击者可以强制将以太币发送到任何地址,并且无法阻止(即使在合约的 fallback 函数中使用了revert())。...合约在部署时,应该选用测试时的版本。...有关安全性和继承的更多信息,请查看本文。 详见 SWC-125[52] 使用接口类型代替地址以确保安全 当函数将合同地址作为参数时,最好传递接口或合约类型,而不是地址类型。...如果该函数在源代码中的其他位置调用,则编译器将提供其他类型安全保证。...警告: 这是一个比较细小的问题。如果只是为了防止其他合约能够调用您的合同,那么使用extcodesize来检查足矣。
WETH9 上线至今快有 3 年了,现在社区小伙伴实现了升级版本:WETH10[3],已经部署在 Kovan 测试网 [4] ?...WETH10 新特性 WETH10 和 WETH9 一样实现和以太币的包裹,实现 WETH 与以太币的 1:1 互换 存款:Ether -> WETH 具体是调用deposit存入以太币(或发送到合约)...2 个参数 data 是传递给目标函数的参数。...目标函数的调用使用 ERC677 标准[5]。...flashMint函数会在调用者地址上调用executeOnFlashMint,flashMint 还支持接收一个额外的bytes参数传递给executeOnFlashMint,flashMint 的实现如下
Ownablecontract SimpleMintContract is ERC721, Ownable { // mint 价格 uint256 public mintPrice = 0.05 ether...; // 总共已经被mint数量 uint256 public totalSupply; // 可以mint的最大数量 uint256 public maxSupply;...,部署合约的时候,设置最大数量为2 constructor() payable ERC721('Simple Mint', 'SIMPLEMINT') { maxSupply = 2...function mint() external payable { // require判断函数,前半部判断为false,则抛出后半部分信息 // 判断是否开启mint.../ 判断地址是否已经mint require(mintedWallets[msg.sender] < 1, 'exceeds max per wallet'); // 判断发送到合约的
本文作者: aisiji[1] 本文通过编写一个有漏洞的合约,分析如何攻击、预防并修复漏洞。 Source: Undraw[2] 以太坊智能合约的一个特点——可以调用和利用来自外部合约的代码。...这个函数只在请求的取款小于等于 1 ether 并且一个星期内没有取款的情况下才会成功。 漏洞在 17 行,在这里合约向储户发送请求的 ether。...首先,攻击者可以创建恶意合约(假设地址为0x0… 123),将EtherStore的合约地址作为唯一的构造函数参数。 这将把 public 变量etherStore初始化并指向被攻击合约。...然后攻击者将用大于等于 1 的一定数量的 ether(暂时假设为 1 ether)来调用attackEtherStore函数。...最后的结果是,除了 1 ether 不能提取,攻击者一笔交易从EtherStore合约提取了其他所有 ether。 如何避免漏洞 有很多常用技术可以帮助我们在合约中避免潜在的重入漏洞。
可以被强制发送到账户 谨慎编写用来检查账户余额的不变量。...gas 用于失败后fallback函数的执行(译者注:合约收到Ether也会触发fallback函数执行)。...(这里有一个更复杂的实现 想通过内联汇编和返回大小的注册表来解决这个问题) 无论你的方法如何,重要的是要有一些方法来升级你的合约,否则当被发现不可避免的错误时合约将没法使用。...或者将速率限制做在合约级别,合约期限内只能发出发送一定数量的代币。 浏览例程 合约发布 在将大量资金放入合约之前,合约应当进行大量的长时间的测试。...(例如, 你可能会丢掉所有的钱,黑客可能会通过投票支持某些结果) 所有已知的错误/限制 潜在的攻击和解决办法 潜在的利益冲突(例如,筹集的Ether将纳入自己的腰包,像Slock.it与DAO一样)
Brownie 是一个基于 Python 的 Solidity 合约开发框架,以简洁的 Python 语法为调试和测试提供了便捷的工具链。 Hardhat。...通过 Ethereum 官方提供的基于浏览器的 Remix 开发工具进行调试,Remix 会提供完整的 IDE、编译工具、部署调试的测试节点环境、账户等,可以很方便地进行测试,这是我学习使用时用的最多的工具...关键字 我们可以通过声明 payable 关键字设置方法可从合约中接收 ether。...); } // 方法声明 payable 来接收 Ether function deposit() public payable {} 与 Ether 交互 与 Ether 交互是智能合约的重要应用场景...当一个不接受任何参数也不返回任何参数的函数、当 Ether 被发送至某个合约但 receive() 方法未实现或 msg.data 非空时,会调用 fallback() 方法。
领取专属 10元无门槛券
手把手带您无忧上云