You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Solidity合约中传递函数作为参数?Ethers实现疑问

Solidity动态规则生成器:用Ethers传递函数到RoleManager合约

首先明确核心点:你在RoleManager里定义的function类型参数,本质是链上已部署函数的引用(合约地址+函数选择器),不能直接在Ethers里凭空生成“动态函数”,必须先把规则逻辑写成独立合约的函数,再将该函数的引用传给RoleManager。下面是具体步骤:

1. 编写规则逻辑合约

先写一个包含规则判断函数的合约,函数签名必须和RoleManager中定义的完全一致:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract RuleLogic {
    // 严格匹配RoleManager中规则函数的签名
    function checkRule(
        bytes32 role,
        address caller,
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory data,
        string memory context
    ) external view returns (bool) {
        // 这里替换成你的实际规则逻辑,示例:仅允许特定地址通过
        return caller == 0x1234567890123456789012345678901234567890;
    }
}

2. 部署规则合约

用Ethers或Hardhat部署这个RuleLogic合约,记录部署后的合约地址。

3. 用Ethers构造函数引用并调用setRule

在Ethers中,需要将规则函数的合约地址和函数选择器拼接成24字节的函数引用,再传给setRule方法。以下是Ethers v6的代码示例:

import { ethers } from "ethers";

// 初始化provider和owner账户的signer
const provider = new ethers.JsonRpcProvider("你的RPC地址");
const signer = provider.getSigner("owner的私钥或钱包地址");

// 合约地址
const roleManagerAddr = "你的RoleManager合约地址";
const ruleLogicAddr = "部署好的RuleLogic合约地址";

// 加载合约ABI(仅需包含用到的函数)
const roleManagerAbi = [
  "function setRule(bytes32 role, function(bytes32,address,address[],uint256[],bytes[],string) external view returns(bool) rule) public onlyOwner"
];
const ruleLogicAbi = [
  "function checkRule(bytes32,address,address[],uint256[],bytes[],string) external view returns(bool)"
];

const roleManager = new ethers.Contract(roleManagerAddr, roleManagerAbi, signer);
const ruleLogic = new ethers.Contract(ruleLogicAddr, ruleLogicAbi);

// 获取函数选择器
const ruleSelector = ruleLogic.interface.getFunction("checkRule").selector;

// 拼接函数引用:合约地址(20字节)+ 选择器(4字节)
const ruleRef = ethers.concat([ruleLogicAddr, ruleSelector]);

// 调用setRule,示例传入role为"ADMIN"的bytes32编码
const targetRole = ethers.encodeBytes32String("ADMIN");
const tx = await roleManager.setRule(targetRole, ruleRef);
await tx.wait();

关键注意事项

  • 函数签名必须完全匹配:参数的类型、顺序、数量,以及返回值类型都要和RoleManager中定义的一致,否则调用会失败。
  • 若需修改规则,只需部署新的RuleLogic合约,或在同一个合约中实现多个规则函数,传递对应函数的引用即可。
  • Solidity不支持“动态生成无合约载体的函数”,所有规则逻辑必须依附于已部署的合约存在。

内容的提问来源于stack exchange,提问作者Ritzy Dev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 22:35:52