版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
智能合约开发实战单元3设计与实现发票合约任务3.1发票合约代码开发任务描述知识准备任务实现任务描述市税务局需要开发一套区块链税务系统进行试点。该系统将涵盖发票的整个开具和使用流程,其核心流程如下:登记试点企业:税务局首先登记有资格认领发票的试点企业。经过登记的企业才能认领区块链发票。登记发票:税务局将试点发票登记进入区块链发票池,只有经过登记进入发票池的发票才是合法的区块链发票,未登记的发票均为无效发票。分配发票:税务局将区块链发票分配给试点企业。开具发票:试点企业根据实际发生的业务,将认领的发票开具给他人。企业只能开具自己认领的发票,不得使用其他企业认领的发票。查询发票:收到发票的企业可以查询发票信息。知识准备
3.1.1函数3.1.2构造函数3.1.3require语句3.1.4布尔类型3.1.5函数修饰器(modifier)3.1.1函数在Solidity中,函数是智能合约的核心组成部分,负责定义合约的行为。函数可以在合约内部调用,以执行特定的操作、处理数据、执行计算、管理状态等。其基本语法结构如下:基本语法functionfunctionName(parameter1Typeparameter1Name,parameter2Typeparameter2Name,...)visibility[payable][pure|view][returns(returnType1,returnType2,...)]{//函数体}3.1.1函数function:这是声明函数的关键字。functionName:这是函数的名称。推荐使用驼峰命名法,即第一个单词以小写字母开头,后续单词的首字母大写,以提高代码的可读性。例如:addVoter,getTotalVotes,transferTokens。1.函数命名代码示例【例3-1】3.1.1函数参数列表包含零个或多个参数,每个参数包括类型和名称。-parameterType:指定参数的数据类型,例如uint、address、string等。-parameterName:参数的名称,便于在函数体中引用。2.参数列表代码示例【例3-2】3.1.1函数可见性修饰符用于控制函数的访问权限,Solidity中有以下四种:public:函数可以在合约外部或其他合约中调用。private:函数只能在当前合约的内部调用,外部无法访问。internal:函数可在当前合约及其派生合约(继承的合约)中调用。external:函数只能从合约外部访问,合约内部调用时需使用this.functionName()。3.可见性3.1.1函数payable是一个特殊的修饰符,表示该函数可以接收以太积分(ETH)。如果一个函数声明为payable,调用时可以附带ETH;否则,非payable函数不能接收ETH。4.payable修饰符代码示例【例3-3】3.1.1函数这两个修饰符用于定义函数的特定行为:pure:表示该函数不读取也不修改合约的状态,仅执行计算逻辑。view:表示该函数不会修改合约的状态,但可以读取状态变量。5.pure和view修饰符3.1.1函数5.pure和view修饰符代码示例【例3-4】3.1.1函数returns关键字用于指定函数的返回值类型。如果函数需要返回多个值,返回类型应该用逗号分隔。6.返回类型(returns)代码示例【例3-5】3.1.1函数函数体包含具体的实现代码,是执行函数功能的地方。这部分代码在函数被调用时执行。7.函数体代码示例【例3-6】3.1.2构造函数构造函数是Solidity中一个非常特殊的函数,它在合约部署时只会被执行一次。构造函数的主要作用是初始化合约的状态,即在合约部署到区块链上时,设置合约中的初始状态。构造函数的语法结构如下:基本语法contractMyContract{//声明状态变量uintpublicstateVariable1;addresspublicstateVariable2;//构造函数constructor(uint_param1,address_param2){//初始化状态变量stateVariable1=_param1;stateVariable2=_param2;}//其他合约方法和逻辑//...}状态变量:在合约中,状态变量是存储在区块链上的变量,用于表示合约的状态。在上述代码中,stateVariable1和stateVariable2是合约的状态变量。构造函数:constructor(uint_param1,stringmemory_param2)这是构造函数的声明,它接受两个参数,_param1和_param2。这些参数可以在合约部署时传递进去,供构造函数内部使用。初始化状态变量:在构造函数的体内,使用传入的参数_param1和_param2来初始化状态变量stateVariable1和stateVariable2。这确保了合约部署时,状态变量有正确的初始值。3.1.2构造函数代码示例【例3-8】不带参数的构造函数的用法基本语法3.1.2构造函数代码示例【例3-9】带参数的构造函数的用法基本语法3.1.3require语句require语句用于进行运行时的条件检查和错误处理。它用于检查某个条件是否满足,如果条件不满足,则触发异常,终止合约的执行。基本语法如下:其中,条件是一个布尔表达式,用于判断某个条件是否满足。如果条件不满足,即为false,则触发异常,终止合约的执行,并输出指定的错误信息。基本语法require(条件,错误信息);3.1.3require语句代码示例【例3-10】检查形式参数基本语法3.1.3require语句代码示例【例3-11】检查用户余额基本语法3.1.4布尔类型(1)声明:布尔类型使用关键字bool声明。(2)初始化:布尔变量可以在声明时初始化为true或false。(3)默认值:如果布尔状态变量没有显式初始化,它的默认值是false。1.声明和初始化boolisActive;boolisActive=true;boolisCompleted=false;boolisVerified;//默认值为false3.1.4布尔类型(1)逻辑运算符:布尔类型支持常见的逻辑运算符:与(&&):只有当两个操作数都为true时,结果才为true。或(||):只要有一个操作数为true,结果就为true。非(!):返回操作数的相反值。2.操作和运算符代码示例【例3-12】布尔逻辑运算的使用3.1.4布尔类型2.操作和运算符代码示例【例3-13】比较运算符的使用(2)比较运算符:布尔类型还可以通过比较运算符产生,常见的比较运算符有:等于(==):检查两个值是否相等。不等于(!=):检查两个值是否不相等。3.1.4布尔类型2.操作和运算符代码示例【例3-14】布尔类型作为函数的返回值3.1.5函数修饰器函数修饰器(modifier)是一种特殊的功能,可以在函数执行之前或之后应用某些逻辑。修饰器可以帮我们在多个函数中重复使用相同的代码逻辑,提高代码的可读性和可维护性。修饰器的语法如下:modifierName是修饰器的名称,可以根据需要自定义。下划线“_”的作用是作为占位符,指示在修饰器内部代码执行的具体位置。可以将其放置在修饰器逻辑代码的前面或后面,从而控制函数的执行顺序。1.不带参数的修饰器modifiermodifierName(){//在函数执行前或后执行的逻辑_;//这个下划线代表函数体的位置}3.1.5函数修饰器代码示例【例3-15】基本修饰器1.不带参数的修饰器3.1.5函数修饰器代码示例【例3-16】修饰器前后的逻辑1.不带参数的修饰器3.1.4布尔类型带参数的修饰器让我们能够在修饰器内部传递参数,并根据这些参数来执行不同的逻辑或条件检查。带参数的修饰器的语法如下所示:在定义带参数的修饰器时,我们可以指定参数的类型和名称,并在修饰器的逻辑中使用这些参数来进行相应的操作。2.带参数的修饰器modifierModifierName(parameterTypeparameterName){//修饰器的逻辑_;//这个下划线代表函数体的位置}3.1.4布尔类型代码示例【例3-17】使用带参数的修饰器2.带参数的修饰器任务实现步骤1:定义合约步骤2:定义合约变量、修饰器和构造函数步骤3:编写将发票添加到发票池函数步骤4:编写添加试点企业函数步骤5:编写将发票分配给指定的企业函数任务实现首先,创建一个新的Solidity文件,命名为Invoice.sol,并在文件中编写以下代码:步骤1:定义合约任务实现接下来,在合约中定义一个私有变量owner,用于存储合约创建者的地址。同时,定义一个修饰器onlyOwner,用于限制只有合约创建者才能执行某些操作。在构造函数中,将owner初始化为合约的部署者地址。步骤2:定义合约变量、修饰器和构造函数任务实现定义一个映射invoicePool,用来记录发票池。映射的键是发票编号,值是企业账户地址,其中账户0表示发票尚未被认领。接着,编写prepareInvoice函数,将发票添加到发票池。只有合约创建者可以调用此函数。步骤3:编写将发票添加到发票池函数任务实现定义一个映射companies,用于记录哪些企业是试点企业。通过registerCompany函数,合约创建者可以将试点企业的地址注册到合约中。步骤4:编写添加试点企业函数任务实现定义一个assignInvoiceTo函数,合约创建者可以通过该函数将发票分配给已注册的试点企业。在分配时,首先要确保发票编号有效且已被添加到池中,并且目标企业是已注册的试点企业。步骤5:编写将发票分配给指定的企业函数任务3.2发票合约代码开发及部署任务描述知识准备任务实现任务描述本任务的目标是开发一套区块链税务系统,允许市税务局管理发票的分配和使用。系统应保证发票的唯一性和不可篡改性,并支持企业开具发票和查询发票信息。1.定义开具发票函数:定义一个私有映射issuedTo用于记录发票编号对应的接收者信息,使用该函数需要经过验证:发票必须是分配给自己的且未被使用过。定义另一个私有映射invoiceValue用于记录发票编号对应的消费金额。2.定义查询发票函数:定义函数queryInvoice,该函数可以根据发票编号查询发票的金额和接收者信息,返回查询结果。3.部署和调用合约:4.合约部署:税务局(账户A)部署合约,合约返回合约地址。5.税务局注册试点企业:税务局(账户A)将企业账户B注册为有资格认领发票的试点企业。6.税务局准备发票:税务局将试点发票登记进入区块链发票池,确保发票有效。7.税务局给企业分配发票:将登记过的发票和注册过的企业(账户B)关联起来。8.企业开具发票:试点企业(账户B)根据实际业务开具发票,只能使用自己认领的发票。9.企业查询发票:收到发票的企业(账户C)查询发票信息,合约返回发票的金额和收款方名称。知识准备
3.2.1字符串类型(string)3.2.2字节数组类型(bytes)3.2.3条件语句3.2.1字符串类型(string)字符串类型是一个动态大小的UTF-8编码的字符串数据。它经常用来存储文本形式的数据。基本语法如下:其中,variableName是变量名,代表存储字符串数据的变量。1.声明及初始化字符串变量可以在声明时进行初始化,也可以在构造函数中进行初始化。(1)在声明时初始化1.声明及初始化stringvariableName;代码示例【例3-18】在声明时直接给string变量赋值3.2.1字符串类型(string)(2)在构造函数中初始化1.声明及初始化stringvariableName;代码示例【例3-19】在合约的构造函数中初始化string变量3.2.1字符串类型(string)(1)字符串拼接Solidity中没有内置的字符串拼接操作符。但是可以使用abi.encodePacked函数和字符串转换来实现字符串拼接。abi.encodePacked会将多个数据项拼接成一个字节数组,然后可以将这个字节数组转换回字符串2.字符串的基本操作代码示例【例3-20】字符串拼接3.2.1字符串类型(string)(2)字符串比较如果要比较两个字符串是否相等,可以通过对字符串进行哈希操作,然后比较它们的哈希值来实现。Solidity使用keccak256哈希函数来对数据进行哈希处理。2.字符串的基本操作代码示例【例3-21】比较两个字符串是否相等3.2.2字节数组类型(bytes)bytes类型是一种灵活的字节数组类型,常用于处理原始字节数据。固定长度字节数组的长度在编译时就已确定,长度范围从1到32字节不等。它的主要特点是存储效率高,因为长度固定,这种数组在内存或存储中的分配非常高效。它适用于存储固定长度的数据,如哈希值(通常为bytes32)和其他固定大小的数据。1.固定长度字节数组代码示例【例3-22】字节数组初始化(1)固定长度字节的初始化该代码定义了三个字节数组(bytes1,bytes2,bytes32),并通过getBytes函数返回它们的值。3.2.2字节数组类型(bytes)(2)在构造函数中初始化1.固定长度字节数组代码示例【例3-23】字节数组初始化3.2.2字节数组类型(bytes)在Solidity中,bytes类型是一个动态长度的字节数组,其长度可以在运行时动态调整。bytes用于存储原始字节数据,而不是字符数据,与string类型类似。bytes类型特别适合于需要在运行时进行字节数据的连接、修改等操作。(1)动态长度字节数组初始化①声明时初始化2.动态长度字节数组代码示例【例3-24】将一个字节数组赋值给bytes变量3.2.2字节数组类型(bytes)②在构造函数中初始化bytes类型也可以在构造函数中进行初始化,这通常用于根据外部输入来设置字节数组的值。2.动态长度字节数组代码示例【例3-25】在构造函数中初始化bytes变量3.2.2字节数组类型(bytes)(2)动态字节数组的基本操作2.动态长度字节数组代码示例【例3-26】访问单个字节3.2.2字节数组类型(bytes)2.动态长度字节数组代码示例【例3-27】获取字节数组长度3.2.2字节数组类型(bytes)“字面量”是指在代码中直接表示固定值的表达式。字面量是一种常量,表示的是它本身的值,而不是变量或对象的引用。字面量可以用于表示各种数据类型的固定值,例如整数、浮点数、字符串、布尔值等。3.字面量代码示例【例3-28】常见的字面量示例3.2.2字节数组类型(bytes)在Solidity中,string和bytes都用于存储可变长度的数据,且可以互相显式转换:-string本质是UTF-8编码的动态字符串,不支持直接访问单个字符;-bytes是动态字节数组,支持通过索引访问单个字节、获取长度(.length)等操作。4.string类型与bytes类型的关系代码示例【例3-29】string和bytes类型之间的转换3.2.2字节数组类型(bytes)4.string类型与bytes类型的关系代码示例【例3-30】判断字符串是否为空3.2.2字节数组类型(bytes)4.string类型与bytes类型的关系代码示例【例3-31】修改字节数组中的字符3.2.2字节数组类型(bytes)4.string类型与bytes类型的关系string和bytes的区别3.2.3条件语句if语句的基本语法如下:1.if语句if(condition){//如果条件成立,执行这里的代码}condition表示要检查的条件,如果该条件成立,则执行大括号中的代码块。如果条件不成立,则跳过if语句并继续执行后续的代码。代码示例【例3-32】使用if语句来判断一个数字是否大于103.2.3条件语句if-else语句的基本语法如下:2.if-else语句if(condition){//如果条件成立,执行这里的代码}else{//如果条件不成立,执行这里的代码}如果条件成立,则执行if代码块中的内容。否则,执行else代码块中的内容。代码示例【例3-33】使用if-else语句来判断奇偶数3.2.3条件语句elseif语句用于在多个条件之间进行选择。基本语法如下:3.elseif语句if(condition1){//如果条件1成立,执行这里的代码}elseif(condition2){//如果条件2成立,执行这里的代码}else{//如果条件1和条件2都不成立,执行这里的代码}在这种情况下,如果条件1成立,则
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 外科护理对心脏骤停患者生存质量的影响
- 心脏外科术后营养支持护理
- 2026国网浙江省电力有限公司招聘85人(第二批)笔试参考题库及答案解析
- 2026年嘉兴市康慈医院公开招聘编外合同制人员25人考试备考试题及答案解析
- 2026福建省晋江圳源环境科技有限责任公司招聘8人考试参考试题及答案解析
- 2026年毕节医学高等专科学校单招职业适应性测试题库有答案解析
- 2026中国铁路青藏集团公司招603人(青海)笔试参考题库及答案解析
- 2026北京市平谷区卫生健康委员会所属事业单位第一次招聘112人考试备考试题及答案解析
- 2026广西农业科学院植物保护研究所蕉类作物病害研究团队招聘科研助理1人考试参考试题及答案解析
- 2026年濮阳医学高等专科学校单招职业适应性测试题库及答案解析
- DB31∕T 875-2015 人身损害受伤人员休息期、营养期、护理期评定准则
- 工厂厂区道路施工方案
- 2024年度景区电瓶车租赁及运营合同3篇
- 浙江省杭州市2024年中考语文试卷(含答案)
- 医疗设备信息化管理制度
- 宁夏闽宁镇:昔日干沙滩-今日金沙滩+课件-高教版(2023)中职语文职业模块
- (高清版)JTGT 3610-2019 公路路基施工技术规范
- 安全技术与管理专业《工程制图与CAD》课程标准
- 钙基新材料产业链分析报告
- 《网店美工与 管理》电子教案《网店美工》电子教案
- 《毛泽东传 1 》读书笔记PPT模板思维导图下载
评论
0/150
提交评论