智能合约

Li Guangqiao - 07/03/2024

blockchain

智能合约

主要以Fisco Bcos 和Hyperleger Fabric为主进行合约的学习和研究。

Fisco Bcos合约

Solidity合约

revert错误处理

revert指令的作用是回滚合约。

合约的交易回执中,若状态码为0x16,状态信息为RevertInstruction,表示执行了回滚指令revert。

地址传递

状态变量修改函数的地址传递

例如:

现有合约TestAdd.sol、Test.sol,Test 导入了TestAdd并调用了它的test方法。

已知部署Test 的用户地址为0xe2d3a5f33454452081eb2e4ba0f99f97e40fc840。

合约地址为0x7d26aec47df6c3702c91898b05fec3a2efd0fd2f。

用户调用合约的parent方法,当前合约的msg.sender地址是用户地址0xe2d3a5f33454452081eb2e4ba0f99f97e40fc840。

那么调用test的msg.sender应该是合约地址还是发起交易用户地址?

其中用到了两个solidity的官方api,包含msg.sender当前消息发送者、tx.origin交易原始调用者。

使用错误处理回滚apirevert打印结果显示为合约地址:0x7d26aec47df6c3702c91898b05fec3a2efd0fd2f。

msg.sender的地址具有传递性,并非调用链上和原始调用者保持一致,而是遵循调用关系,比如说,用户调用合约A方法则合约A中的msg.sender为用户公钥地址,合约A方法调用了合约B方法,则合约B中的msg.sender为合约A的地址,依此类推。

tx.origin在整个调用链上始终保持一致,表示为最终发起交易的用户地址。

Test

//Test.sol
pragma solidity ^0.4.25;
import "./TestUtil.sol";
//字符串存储数据结构
contract Test {
    TestUtil t = new TestUtil();
    event print(address,address);
    function parent() public{
        emit print(tx.origin,msg.sender);
        t.test();
    }
}

TestUtil

//TestUtil.sol
pragma solidity ^0.4.25;
//字符串存储数据结构
contract TestUtil {
    function test() public returns(bool re){
        
        address a = 0xe2d3a5f33454452081eb2e4ba0f99f97e40fc840;
        if(msg.sender!=a){
             revert(addressToString(msg.sender));
        }
        return true;
    }
    function addressToString(address _addr) public pure returns(string memory) {
        bytes32 value = bytes32(uint256(uint160(_addr)));
        bytes memory alphabet = "0123456789abcdef";
        bytes memory str = new bytes(42); // 因为以太坊地址长度为20字节,字符串表示为40个字符加上"0x"前缀
        str[0] = '0';
        str[1] = 'x';
        for (uint256 i = 0; i < 20; i++) {
            str[2+i*2] = alphabet[uint8(value[i + 12] >> 4)];
            str[3+i*2] = alphabet[uint8(value[i + 12] & 0x0f)];
        }
        return string(str);
    }
    constructor() public{
        
    }
}
view修饰的查询函数地址传递

msg.sender只需要考虑一种特殊情况的随机性,就是部署当前合约之后,通过一个view修饰的方法返回msg.sender时,每次交易的结果返回的msg.sender值是不一样的。去调view的修饰,则与当前发起交易的用户地址保持一致。

验证环境:

ide:webase v1.5.4

bcos:v2.8.0

合约内容如下:

pragma solidity ^0.4.25;
contract TestSubC {
    function getWithView() public view returns(address){
        return msg.sender;
    }
    function getWithoutView() public returns(address){
        return msg.sender;
    }
}

自定义修饰器(modifier)

函数处理前执行自定义逻辑

modifer check() {
	//自定义逻辑
	_;
}

函数处理后执行自定义逻辑

modifer check() {
	_;
	//自定义逻辑
}

修改器

钩子

初步测试solidity支持钩子,可以通过预留合约钩子来方便后续合约代码的拓展。

子合约继承后,可以通过复写父合约的的钩子方法做额外的处理。

function preTest() internal {}
function afterTest() internal {}
function test() public {
	 preTest();
	//实际测试逻辑
	afterTest();
}
版本限制

v0.4.25版本

知识点
思考

Hyperleger Fabric

Li Guangqiao
Li Guangqiao

一个正在转rust的ExtJs前端工程师。迷信rust的整体发展,十分相信rust在各个领域都能发光发热,至少目前rust在很多领域上验证了其安全性、易维护性。但说实话对于我这种菜鸡也是真的难上手哈哈哈~~。 思路总结:

  • 万物诞生都会有一个需求来源,每一个改变都是为了解决某个问题,最后应该考虑如何去做
  • 学会掌握一些宏观的知识和理论:系统论、还原论
  • 工程化思想,如何描述整体,从整体架构到模块关联等 故学习东西应该像看地图一样,先看整体了解整体的结构,然后再聚焦每一个模块,对于模块的学习,思考三个问题,“是什么?”、“为什么?”、“怎么做?”;那么设计一个东西时也应该去考虑整体性和关联性。

有关于未来的发展,以下是鄙人的粗浅的观点:

  • 编程语言未来应该是每个人必备的工具
  • 未来的交互方式应该会以语言交互为主流
  • 下一个去中心化的技术方案出来之前,区块链依然是web3建立价值体系的基础技术方案,如何将现实价值和虚拟价值联通是进入数字世界的一个大难题。
  • 未来注定是AI的世界。AI的进化会伴随绝大部分人的退化,届时除了尖端人才,人们学习的重心会放在何处?