Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task 57 用复杂合约测试FISCO BCOS的合约执行逻辑,反馈相关问题 #4008

Open
wants to merge 782 commits into
base: dev
Choose a base branch
from

Conversation

hogoqkl
Copy link

@hogoqkl hogoqkl commented Oct 31, 2023

在测试下面合约时会出现问题:
某个多参数合约方法:

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Test {
function methodWithLotsOfParameters(
uint256 param1,
uint256 param2,
uint256 param3,
uint256 param4,
uint256 param5,
uint256 param6,
uint256 param7,
uint256 param8,
uint256 param9,
uint256 param10,
uint256 param11,
uint256 param12,
uint256 param13,
uint256 param14,
uint256 param15,
uint256 param16,
uint256 param17,
uint256 param18,
uint256 param19,
uint256 param20
) public pure returns (uint256) {
// Perform some operations with the parameters
return param1 + param2 + param3 + param4 + param5 + param6 + param7 + param8 + param9 + param10 + param11 + param12 + param13 + param14 + param15 + param16 + param17 + param18 + param19 + param20;
}
}

填写参数后:
image

返回的这个报错:

image

测试OpenZeppelin和WTF中的相关合约,使用合约IDE进行编译和部署的过程中未发现任何问题。合约IDE的编译版本为0.8.11。

针对测试,写了一个相关复杂合约(主合约代码如下),在编译、部署和调用过程中,未出现任何错误或异常情况,合约的功能和逻辑按预期工作,没有引发潜在的问题或漏洞。
`
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "Ownable.sol";
import "Counters.sol";
import "ECDSA.sol";
import "EIP712.sol";
import "SafeMath.sol";
import "Strings.sol";
import "ERC721.sol";

/*
@title 商品合约
*/
contract Product is ERC721, EIP712, Ownable {

/// @title 商品信息
struct ProductInfo {
    uint256 price;         // 当前价格
    uint256 tokenId;       // 商品NFT对应的TokenId
    address owner;         // 商品所有者钱包地址
    uint16  transferCount; // 转让次数
    uint8   status;        // 商品状态:0 未设置转让(不可购买)  1 设置转让了(可购买)
}

/* =================== Events =================== */

/*
    @title 事件 - 购买商品
    @param _sender 购买商品用户地址(商品持有者地址)
    @param _productId 商品编号
    @param _price 商品价格 
    @param _tokenId NFT token Id 
*/
event BuyProduct(address _sender, uint16 _productId, uint256 _price, uint256 _tokenId);

using Strings for uint256;
using SafeMath for uint256;
using Counters for Counters.Counter;

/* =================== Constants =================== */

//购买商品函数Hash
bytes32 public constant BUYLAND_HASH = keccak256("BuyProduct(address _admin,address _buyer,uint16 _productId,uint256 _productPrice,uint256 _nonce,uint256 _deadline)");

/* =================== State Variables =================== */

mapping(uint16 => ProductInfo) public Product;    // 商品编号对应的商品信息
mapping(address => uint16[]) public userProduct;  // 用户持有的所有商品
string public baseURI;
uint256 public currentTokenId; // 当前生成的最大tokenId
mapping(address => Counters.Counter) private _nonces;   // 用户签名计数器   
mapping(address => bool) private admins;                // 管理员(可信任组)

 /* =================== Modifier =================== */

// 用于判断是否是管理员
modifier onlyAdmin(){
    require(msg.sender == owner(),"only by owner");
    _;
 }

// 用于判断TokenId是否存在
modifier tokenIdExists(uint256 _tokenId) {
    require(_exists(_tokenId), "Token does not exist");
    _;
}

// 用于判断商品归属人
modifier onlyTokenOwner(uint256 _tokenId) {
    require(
        msg.sender == ownerOf(_tokenId),
        "Only the owner can perform this action"
    );
    _;
}

/* =================== Constructor =================== */

 /*
    @param _name 商品NFT名称
    @param _symbol 商品NFT符号
*/
constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) EIP712("Product", "1.0") {
}


/* =================== External Functions =================== */

/*
    @title 购买商品
    @param _productId 商品编号
    @param _productPrice 商品价格
    @param _deadline 签名过期时间
    @param v, r, s 签名信息
*/
function buyProduct(
    uint16  _productId,
    uint256 _productPrice,
    uint256 _deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) external {       
    // 1、验证签名是否正确
    _validateSignature(_productId, _productPrice, _deadline, v, r, s);


    // 2、验证商品是否已被购买
    require(Product[_productId].owner == address(0), "Product is already bought.");

    // 3、tokenId++
    currentTokenId++;

    // 4、mint商品(userAddr, tokenId)
    _safeMint(msg.sender, currentTokenId);

    // 5、设置状态变量商品信息 Product
    Product[_productId] = ProductInfo({
        price: _productPrice,
        tokenId: currentTokenId,
        owner: msg.sender,
        transferCount: 0,
        status: 0
    });

    // 6、更新状态变量用户持有的商品 userProduct
    userProduct[msg.sender].push(_productId);

    // 添加事件
    emit BuyProduct(msg.sender, _productId, _productPrice, currentTokenId);
}


/* =================== External Getter Functions =================== */ 

/*
    @title 查看商品详情
    @param _productId 商品编号
*/
function getProductInfo(uint16 _productId) external view returns (ProductInfo memory) {
    return Product[_productId];
}

/*
    @title 查看用户持有的所有商品
    @param _owner 用户地址
*/
function getAllProductByOwner(address _owner) external  view returns (ProductInfo[] memory) {       
    ProductInfo[] memory productList = new ProductInfo[](userProduct[_owner].length);

    for (uint256 i = 0; i < userProduct[_owner].length; i++) {
        productList[i] = Product[userProduct[_owner][i]];
    }

    return productList;
}

/*
 * @dev 获取用户签名nonce
 */
function getNonces(address owner) external  view returns (uint256) {
    return _nonces[owner].current();
}

/* =================== Internal Getter Functions =================== */ 


/*
    @title 验证购买商品时管理员的签名是否正确
    @param _productId 商品编号
    @param _productPrice 商品价格
    @param _deadline 签名过期时间
    @param v, r, s 管理员签名信息
*/
function _validateSignature(       
    uint16  _productId,
    uint256 _productPrice,
    uint256 _deadline,
    uint8 v,
    bytes32 r,
    bytes32 s
) internal returns (bool) {
    require(block.timestamp <= _deadline, "Buy Product: expired deadline");
    bytes32 structHash = keccak256(abi.encode(BUYLAND_HASH, 
                            owner(),
                            msg.sender,
                            _productId, 
                            _productPrice, 
                             _useNonce(owner()),
                            _deadline
                        ));

    bytes32 hash = _hashTypedDataV4(structHash);

    address signer = ECDSA.recover(hash, v, r, s);

    require(signer == owner(), "Invalid signature");
    return true;
}

/*
 * @dev 返回当前用户的签名计数,然后自增1,签名验证使用
 */
function _useNonce(address owner) internal returns (uint256 current) {
    Counters.Counter storage nonce = _nonces[owner];
    current = nonce.current();
    nonce.increment();
}

}`

bxq2011hust and others added 30 commits March 23, 2023 09:10
Co-authored-by: wenlinli <1574249665@qq.com>
Co-authored-by: jimmyshi <417711026@qq.com>
kyonRay and others added 30 commits September 12, 2023 12:04
…fect, fix rotate error when viewchange rotate block. (FISCO-BCOS#3908)
…dress check when rotate proposal occurs viewchange when this proposal into pre-commit. (FISCO-BCOS#3916)
…dd CONSENSUS_CANDIDATE_SEALER in rpbft, add more debug log in pbft msg. (FISCO-BCOS#3918)
…bug when upgrade chain to 3.5.0, use concurrent_map to avoid pbft cache thread unsafe insert. (FISCO-BCOS#3926)
…sal causing viewchange, directly return in second rotate tx. (FISCO-BCOS#3962)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet