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

baseDAO添加任意合约交互提案处理器遇Michelson解析错误求助

问题:BaseDAO添加任意合约交互处理器时触发FAILWITH错误

需求背景

要给BaseDAO合约的propose入口点动态添加提案处理器,实现调用任意已部署合约任意入口点的功能。添加处理器的结构要求如下:

(pair %add_handler
  (pair (lambda %code
           (pair (pair (map %handler_storage string bytes) (bytes %packed_argument))
                 (pair %proposal_info
                    (address %from)
                    (nat %frozen_token)
                    (bytes %proposal_metadata)))
           (pair (pair (option %guardian address) (map %handler_storage string bytes))
                 (list %operations operation)))
        (lambda %handler_check (pair bytes (map string bytes)) unit))
  (string %name))

通过验证的基础示例:

(Left (Left (Pair (Pair { 
    DROP ;
    NIL operation ;
    EMPTY_MAP string bytes ;
    NONE address ;
    PAIR ;
    PAIR }
  { DROP ; UNIT })
"sample")))

我想集成的合约调用转发逻辑(Ligo代码):

parameter (pair (address :destination) (pair (string :entrypoint) (bytes :parameter)));
storage unit;
code {
        CAR;
        UNPAIR;
        # Extract the destination contract address
        UNPAIR;
        
        # Convert the string to an entrypoint address
        CONTRACT (unit);
        IF_NONE { FAILWITH } { };
        
        # Pack the parameter bytes
        PUSH mutez 0;  # No tez is sent
        UNPAIR;
        PACK;
        
        # Call the target contract with the provided entrypoint and parameter
        TRANSFER_TOKENS;
        NIL operation;
        CONS;
        
        PAIR;
    };

我的尝试代码:

(Left (Left (Pair 
    (Pair {
        UNPAIR ; SWAP ; UNPAIR ; SWAP ; DROP ; UNPAIR ;
        CAR; UNPAIR; UNPAIR;
        CONTRACT (unit %entrypoint);
        IF_NONE { FAILWITH } {};
        PUSH mutez 0; UNPAIR; PACK;
        TRANSFER_TOKENS;
        NIL operation; CONS;
        SWAP; PAIR;
        NONE address; PAIR 
    }
    { DROP; UNIT }
) "arbitrary_contract_interaction")))

执行后被合约验证器拒绝,错误信息:A FAILWITH instruction was reached {"int":"111"}


问题分析与修复方案

1. 参数解析逻辑完全错误

%code lambda的输入是固定结构:((handler_storage, packed_argument), proposal_info),你的代码里用一堆UNPAIR/SWAP乱拆,根本没正确提取到要转发的合约调用参数(packed_argument)。

2. CONTRACT指令硬编码入口点

你写的CONTRACT (unit %entrypoint)是把入口点固定成了entrypoint,但实际需要用传入的动态入口点字符串,同时要确保参数类型匹配。

3. 无意义的FAILWITH触发

处理器代码里直接用FAILWITH会被DAO验证器拦截,而且没有错误上下文;另外handler_check逻辑完全没做参数验证,这会导致恶意参数通过。

修复后的完整代码

(Left (Left (Pair 
    (Pair {
        ; 解析输入:拆分为((handler_storage, packed_arg), proposal_info) → 提取packed_arg
        UNPAIR ; 得到 ((handler_storage, packed_arg), proposal_info)
        CAR ; 取 (handler_storage, packed_arg)
        UNPAIR ; 拆分出 handler_storage 和 packed_arg
        
        ; 解包packed_arg:必须是(address, (entrypoint_name, param_bytes))结构
        UNPACK (pair address (pair string bytes)) packed_arg
        IF_NONE { 
            ; 解包失败时返回空操作+原存储
            NIL operation
            PAIR handler_storage
            NONE address
            PAIR
        } {
            UNPAIR ; 拆分出 destination 和 (entrypoint_name, param_bytes)
            UNPAIR ; 拆分出 entrypoint_name 和 param_bytes
            
            ; 动态获取目标合约(用%_指定动态入口点,参数类型匹配param_bytes)
            CONTRACT %_ (bytes) destination
            IF_NONE {
                ; 合约不存在/入口点不匹配时返回空操作
                NIL operation
                PAIR handler_storage
                NONE address
                PAIR
            } {
                ; 生成转账操作:0tez + 参数
                PUSH mutez 0
                PAIR param_bytes
                TRANSFER_TOKENS
                NIL operation
                CONS
                
                ; 组装返回结构:((NONE, handler_storage), 操作列表)
                PAIR handler_storage
                NONE address
                PAIR
            }
        }
    }
    { 
        ; handler_check:严格验证参数结构
        CAR ; 取packed_arg
        UNPACK (pair address (pair string bytes))
        IF_NONE { FAILWITH "Invalid packed argument" } { UNIT }
    }
) "arbitrary_contract_interaction")))

核心注意事项

  • handler_check必须做严格的参数结构验证,防止恶意输入
  • 处理器执行逻辑里不要用FAILWITH,而是返回空操作列表,避免被DAO验证器拦截
  • 动态入口点用CONTRACT %_ T addr语法,确保参数类型和传入的param_bytes完全匹配

内容的提问来源于stack exchange,提问作者Eight Rice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 13:00:15