anyFallback

If the anyExec contract execution failed on Chain B, it can call _fallback function to send messages back to Chain A.

anyExecute DAPP receiver contract(Chain B failed) -> anyCall(Chain B) -> SMPC Network -> anyExec(Chain A) -> anyExecute (DAPP sender contract(Chain A))

->anyFallback

Format of the fallback function needs to be:

function anyFallback(address _to, bytes calldata _data) external;

Logic

When anyExecute fails on Chain B, the anycall contract would issue another call back to chain A with data including the anyFallback selector.

Hence the anyExecute execute normal function or fallback function based on the selector.

emit LogAnyCall(
                _from,
                _fallback,
                abi.encodeWithSelector(IApp.anyFallback.selector, _to, _data),
                address(0),
                _ctx.fromChainID,
                0, // pay fee on dest chain
                _appID,
                nonce);

Example

Example Contract Code:https://ftmscan.com/address/0x2b6fbe2a08491130dcc2fe13f0e60b3540d92a55#code

2. Chain B issued callback: https://bscscan.com/tx/0x3ccb1f91ad66348ec5dd8676d1dd59372fd37bca4e202982b582cd8d4e5c582c#eventlog

3. anyFallback executing: https://ftmscan.com/tx/0x215002fb282c630dada2ebeb56ea605ae6c24df8a52db46b977e9c081893d061#eventlog

anyExecute function:

When executing, anyExecute first look at the selector of the calldata passed in to determine if it should execute normal flow or fallback function.

function anyExecute(bytes calldata data)
        external
        
        returns (bool success, bytes memory result)
    {
        bytes4 selector = bytes4(data[:4]);
        if (selector == this.anyExecute.selector) {
            (
                string memory message
            ) = abi.decode(
                data[4:],
                (string)
            );

            if (compareStrings(message,"fail")){
                return (false, "fail on purpose");
            }

            emit NewMsg(message);
        } else if (selector == this.anyFallback.selector) {

            // original data with selector would be passed here if thats the case
            (address _to, bytes memory _data) = abi.decode(data[4:], (address, bytes));
            this.anyFallback(_to, _data);
        } else {
            return (false, "unknown selector");
        }
        return (true, "");
    }

Last updated