ETH Price: $3,981.33 (+2.94%)

Contract

0xfCa1150eA45ba50323C27a7d5E823d92D2e59A05

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

N/A
Transaction Hash
Method
Block
From
To

There are no matching entries

3 Internal Transactions and 6 Token Transfers found.

Latest 3 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
138868282025-10-16 15:47:193 days ago1760629639
0xfCa1150e...2D2e59A05
0.0125 ETH
138868282025-10-16 15:47:193 days ago1760629639
0xfCa1150e...2D2e59A05
0.0125 ETH
136533082025-10-13 22:55:195 days ago1760396119  Contract Creation0 ETH

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
CallForwarder

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.28;

import {ComposerCommands} from "../enums/DeltaEnums.sol";
import {Transfers} from "../transfers/Transfers.sol";
import {ExternalCallsGeneric} from "../generic/ExternalCallsGeneric.sol";
import {BridgeForwarder} from "./bridges/BridgeForwarder.sol";

/**
 * @notice An arbitrary call contract to forward generic calls
 * Does pull funds if desired
 * One transfers funds to this contract and operates with them, ideally pre-funded
 * All composer transfer options are available (approve,transferFrom,transfer,native transfers)
 * Can generically call any target and checks if the selector for these calls is not `transferFrom`
 * We assume that this contract is never an approve target!
 */
contract CallForwarder is Transfers, ExternalCallsGeneric, BridgeForwarder {
    // base receive function
    receive() external payable {}

    /**
     * A selector different to the classic Composer
     * Should be called by a more universal composer
     * that cannot call arbitrary selectors.
     */
    function deltaForwardCompose(bytes calldata) external payable {
        uint256 currentOffset;
        uint256 endOffset;
        address callerAddress;
        assembly {
            let calldataLength := calldataload(0x24)
            currentOffset := 0x44
            endOffset := add(currentOffset, calldataLength)
            callerAddress := caller()
        }
        _deltaComposeInternal(callerAddress, currentOffset, endOffset);
    }

    function _deltaComposeInternal(address callerAddress, uint256 currentOffset, uint256 endOffset) internal virtual override(ExternalCallsGeneric) {
        while (true) {
            uint256 operation;
            assembly {
                operation := shr(248, calldataload(currentOffset))
                currentOffset := add(1, currentOffset)
            }

            if (operation == ComposerCommands.EXT_CALL) {
                currentOffset = _callExternal(currentOffset);
            } else if (operation == ComposerCommands.EXT_TRY_CALL) {
                currentOffset = _tryCallExternal(currentOffset, callerAddress);
            } else if (operation == ComposerCommands.TRANSFERS) {
                currentOffset = _transfers(currentOffset, callerAddress);
            } else if (operation == ComposerCommands.BRIDGING) {
                currentOffset = _bridge(currentOffset);
            } else {
                _invalidOperation();
            }

            // break criteria - we reached the end of the calldata exactly
            if (currentOffset >= endOffset) break;
        }
        // revert if we went past the end
        if (currentOffset > endOffset) revert InvalidCalldata();
    }
}

// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.28;

/**
 * Permit classifier enums
 */
library TransferIds {
    uint256 internal constant TRANSFER_FROM = 0;
    uint256 internal constant SWEEP = 1;
    uint256 internal constant WRAP_NATIVE = 2;
    uint256 internal constant UNWRAP_WNATIVE = 3;
    uint256 internal constant PERMIT2_TRANSFER_FROM = 4;
    uint256 internal constant APPROVE = 5;
}

/**
 * Permit classifier enums
 */
library PermitIds {
    uint256 internal constant TOKEN_PERMIT = 0;
    uint256 internal constant AAVE_V3_CREDIT_PERMIT = 1;
    uint256 internal constant ALLOW_CREDIT_PERMIT = 2;
}

/**
 * Lender classifier enums, expected to be encoded as uint16
 */
library LenderIds {
    uint256 internal constant UP_TO_AAVE_V3 = 1000;
    uint256 internal constant UP_TO_AAVE_V2 = 2000;
    uint256 internal constant UP_TO_COMPOUND_V3 = 3000;
    uint256 internal constant UP_TO_COMPOUND_V2 = 4000;
    uint256 internal constant UP_TO_MORPHO = 5000;
}

/**
 * Operations enums, encoded as uint8
 */
library LenderOps {
    uint256 internal constant DEPOSIT = 0;
    uint256 internal constant BORROW = 1;
    uint256 internal constant REPAY = 2;
    uint256 internal constant WITHDRAW = 3;
    uint256 internal constant DEPOSIT_LENDING_TOKEN = 4;
    uint256 internal constant WITHDRAW_LENDING_TOKEN = 5;
}

/**
 * Lender classifier enums, expected to be encoded as uint16
 */
library FlashLoanIds {
    uint256 internal constant MORPHO = 0;
    uint256 internal constant BALANCER_V2 = 1;
    uint256 internal constant AAVE_V3 = 2;
    uint256 internal constant AAVE_V2 = 3;
}

/**
 * ERC4626 classifier enums
 */
library ERC4626Ids {
    uint256 internal constant DEPOSIT = 0;
    uint256 internal constant WITHDRAW = 1;
}

/**
 * Uniswp V4 operations outside of swaps
 */
library Gen2025ActionIds {
    uint256 internal constant UNLOCK = 0;
    uint256 internal constant UNI_V4_TAKE = 1;
    uint256 internal constant UNI_V4_SETTLE = 2;
    uint256 internal constant UNI_V4_SYNC = 3;
    uint256 internal constant BAL_V3_TAKE = 4;
    uint256 internal constant BAL_V3_SETTLE = 5;
}

/// @title Commands for OneDeltaComposer
library ComposerCommands {
    uint256 internal constant SWAPS = 0x10;
    uint256 internal constant EXT_CALL = 0x20;
    uint256 internal constant EXT_TRY_CALL = 0x21;
    uint256 internal constant LENDING = 0x30;
    uint256 internal constant TRANSFERS = 0x40;
    uint256 internal constant PERMIT = 0x50;
    uint256 internal constant FLASH_LOAN = 0x60;
    uint256 internal constant ERC4626 = 0x70;
    uint256 internal constant GEN_2025_SINGELTONS = 0x80;
    uint256 internal constant BRIDGING = 0x90;
}

/// @title Commands for Bridge
library BridgeIds {
    uint256 internal constant STARGATE_V2 = 0x00;
    uint256 internal constant ACROSS = 0x0A;
    uint256 internal constant SQUID_ROUTER = 0x14;
    uint256 internal constant GASZIP = 0x1E;
}

File 3 of 14 : BaseUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {ERC20Selectors} from "contracts/1delta/shared/selectors/ERC20Selectors.sol";
import {Masks} from "contracts/1delta/shared/masks/Masks.sol";
import {DeltaErrors} from "contracts/1delta/shared/errors/Errors.sol";

contract BaseUtils is ERC20Selectors, Masks, DeltaErrors {
    error InvalidAssetId(uint16 assetId);
    error InsufficientValue();
    error InsufficientAmount();
    error SlippageTooHigh(uint256 expected, uint256 actual);
    error ZeroBalance();
    error BridgeFailed();
    error InvalidDestination();
    error InvalidReceiver();

    uint256 internal constant FEE_DENOMINATOR = 1e9;
    uint256 internal constant INSUFFICIENT_VALUE = 0x1101129400000000000000000000000000000000000000000000000000000000;
    uint256 internal constant INSUFFICIENT_AMOUNT = 0x5945ea5600000000000000000000000000000000000000000000000000000000;
    uint256 internal constant ZERO_BALANCE = 0x669567ea00000000000000000000000000000000000000000000000000000000;
    uint256 internal constant BRIDGE_FAILED = 0xc3b9eede00000000000000000000000000000000000000000000000000000000;
    uint256 internal constant INVALID_DESTINATION = 0xac6b05f500000000000000000000000000000000000000000000000000000000;
    uint256 internal constant INVALID_RECEIVER = 0x1e4ec46b00000000000000000000000000000000000000000000000000000000;
}

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

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

contract Across is BaseUtils {
    /**
     * @notice Handles Across bridging operations
     * @dev Decodes calldata and directly executes the bridge operation using assembly
     * @param currentOffset Current position in the calldata
     * @return Updated calldata offset after processing
     *
     * | Offset | Length (bytes) | Description                  |
     * |--------|----------------|------------------------------|
     * | 0      | 20             | spokePool                    |
     * | 20     | 20             | depositor                    |
     * | 40     | 20             | inputTokenAddress            |
     * | 60     | 32             | receivingAssetId             |
     * | 92     | 16             | amount                       |
     * | 108    | 16             | FixedFee (in input decimals) |
     * | 124    | 4              | FeePercentage                |
     * | 128    | 4              | destinationChainId           |
     * | 132    | 1              | fromTokenDecimals            |
     * | 133    | 1              | toTokenDecimals              |
     * | 134    | 32             | receiver                     |
     * | 166    | 4              | deadline                     |
     * | 170    | 2              | message.length: msgLen       |
     * | 172    | msgLen         | message                      |
     */
    function _bridgeAcross(uint256 currentOffset) internal returns (uint256) {
        assembly {
            let inputTokenAddress := shr(96, calldataload(add(currentOffset, 40)))

            let amount := shr(128, calldataload(add(currentOffset, 92)))

            // whether to use native is indicated by the flag
            let isNative := and(NATIVE_FLAG, amount)

            // clear the native flag
            amount := and(amount, not(NATIVE_FLAG))

            // get the length as uint16
            let messageLength := shr(240, calldataload(add(currentOffset, 170)))

            let requiredNativeValue := 0

            // Check if amount is zero and handle accordingly
            // zero means self balance
            switch iszero(amount)
            case 1 {
                switch isNative
                case 0 {
                    mstore(0, ERC20_BALANCE_OF)
                    mstore(0x04, address())
                    pop(staticcall(gas(), inputTokenAddress, 0x0, 0x24, 0x0, 0x20))
                    amount := mload(0x0)
                }
                default {
                    // get native balance
                    amount := selfbalance()
                    requiredNativeValue := amount
                }
            }
            // non zero amount
            default {
                if isNative {
                    // For native assets, check that hte contract holds enough
                    if gt(amount, selfbalance()) {
                        mstore(0, INSUFFICIENT_VALUE)
                        revert(0, 4)
                    }
                    requiredNativeValue := amount
                }
            }
            // ff is the fixed fee here, then it becomes the amount with fixed fee realized
            let ff := shr(128, calldataload(add(currentOffset, 108)))
            switch gt(amount, ff)
            case 1 { ff := sub(amount, ff) }
            default {
                mstore(0, INSUFFICIENT_AMOUNT)
                revert(0, 4)
            }

            let fromTokenDecimals := calldataload(add(currentOffset, 132))
            let toTokenDecimals := and(shr(240, fromTokenDecimals), UINT8_MASK)
            fromTokenDecimals := shr(248, fromTokenDecimals)
            let decimalDiff := sub(toTokenDecimals, fromTokenDecimals)

            let outputAmount := 0

            let decimalAdjustment := 1

            if xor(fromTokenDecimals, toTokenDecimals) {
                // abs(decimalDiff)
                let mask := sar(255, decimalDiff)
                let absDiff := sub(xor(decimalDiff, mask), mask)

                switch absDiff
                // shorthands
                case 12 { decimalAdjustment := 1000000000000 }
                case 11 { decimalAdjustment := 100000000000 }
                case 10 { decimalAdjustment := 10000000000 }
                case 9 { decimalAdjustment := 1000000000 }
                case 8 { decimalAdjustment := 100000000 }
                case 7 { decimalAdjustment := 10000000 }
                case 6 { decimalAdjustment := 1000000 }
                // arbitrary loop
                default { for { let i := 0 } lt(i, absDiff) { i := add(i, 1) } { decimalAdjustment := mul(decimalAdjustment, 10) } }
            }

            // calculate percentage fee with decimal adjustment
            switch lt(toTokenDecimals, fromTokenDecimals)
            case 1 {
                outputAmount := div(mul(amount, shr(224, calldataload(add(currentOffset, 124)))), mul(FEE_DENOMINATOR, decimalAdjustment))
                ff := div(ff, decimalAdjustment) // apply decimal adjustment on amount with fixed fee
            }
            // none or output has more decimals
            default {
                outputAmount := div(mul(decimalAdjustment, mul(amount, shr(224, calldataload(add(currentOffset, 124))))), FEE_DENOMINATOR)
                ff := mul(ff, decimalAdjustment) // apply decimal adjustment on amount with fixed fee
            } // also handles the case where decimals are the same

            switch gt(ff, outputAmount)
            case 1 { outputAmount := sub(ff, outputAmount) }
            default {
                mstore(0, INSUFFICIENT_AMOUNT)
                revert(0, 4)
            }

            let ptr := mload(0x40)

            // deposit function selector
            mstore(ptr, 0xad5425c600000000000000000000000000000000000000000000000000000000)
            mstore(add(ptr, 0x04), shr(96, calldataload(add(currentOffset, 20)))) // depositor
            mstore(add(ptr, 0x24), calldataload(add(currentOffset, 134))) // recipient (32 bytes)
            mstore(add(ptr, 0x44), inputTokenAddress) // inputToken
            mstore(add(ptr, 0x64), calldataload(add(currentOffset, 60))) // outputToken (32 bytes)
            mstore(add(ptr, 0x84), amount) // amount
            mstore(add(ptr, 0xa4), outputAmount) // outputAmount
            mstore(add(ptr, 0xc4), shr(224, calldataload(add(currentOffset, 128)))) // destinationChainId
            mstore(add(ptr, 0xe4), 0) // exclusiveRelayer (zero address)
            mstore(add(ptr, 0x104), timestamp()) // quoteTimestamp (block timestamp)
            // fillDeadline (exact deadline)
            mstore(add(ptr, 0x124), shr(224, calldataload(add(currentOffset, 166))))
            mstore(add(ptr, 0x144), 0) // exclusivityDeadline (zero)
            mstore(add(ptr, 0x164), 0x180) // message offset
            mstore(add(ptr, 0x184), messageLength) // message length

            // Handle message
            switch gt(messageLength, 0)
            case 1 {
                // add the message from the calldata
                calldatacopy(add(ptr, 0x1a4), add(currentOffset, 172), messageLength)

                // call and forward error
                if iszero(
                    call(
                        gas(),
                        shr(96, calldataload(currentOffset)), // spoke pool address
                        requiredNativeValue,
                        ptr,
                        add(0x1a4, messageLength), // add length of variable data
                        0x00,
                        0x00
                    )
                ) {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }

                mstore(0x40, add(ptr, add(0x1c4, messageLength))) // one word after the message
            }
            default {
                // call and forward error
                if iszero(
                    call(
                        gas(),
                        shr(96, calldataload(currentOffset)), // spoke pool address
                        requiredNativeValue,
                        ptr,
                        0x1a4,
                        0x00,
                        0x00
                    )
                ) {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }

                mstore(0x40, add(ptr, 0x1a4)) // one word after the message
            }
            currentOffset := add(currentOffset, add(172, messageLength))
        }

        return currentOffset;
    }
}

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

import {StargateV2} from "./StargateV2/StargateV2.sol";
import {Across} from "./Across/Across.sol";
import {SquidRouter} from "./Squid_Router/SquidRouter.sol";
import {GasZip} from "./GasZip/GasZip.sol";
import {BridgeIds} from "contracts/1delta/composer/enums/DeltaEnums.sol";

/**
 * Aggregates multiple bridge calls
 */
contract BridgeForwarder is StargateV2, Across, SquidRouter, GasZip {
    function _bridge(uint256 currentOffset) internal returns (uint256) {
        uint256 bridgeOperation;
        assembly {
            let firstSlice := calldataload(currentOffset)
            bridgeOperation := shr(248, firstSlice)
            currentOffset := add(currentOffset, 1)
        }
        if (bridgeOperation == BridgeIds.STARGATE_V2) {
            return _bridgeStargateV2(currentOffset);
        } else if (bridgeOperation == BridgeIds.ACROSS) {
            return _bridgeAcross(currentOffset);
        } else if (bridgeOperation == BridgeIds.SQUID_ROUTER) {
            return _bridgeSquidRouter(currentOffset);
        } else if (bridgeOperation == BridgeIds.GASZIP) {
            return _bridgeGasZip(currentOffset);
        } else {
            _invalidOperation();
        }
    }
}

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

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

contract GasZip is BaseUtils {
    /**
     * @notice Handles GasZip bridging (GasZip v1)
     * https://dev.gas.zip/gas/code-examples/evm-deposit/contract-forwarder
     *
     * | Offset | Length (bytes) | Description                  |
     * |--------|----------------|------------------------------|
     * | 0      | 20             | gasZipRouter                 |
     * | 20     | 32             | receiver                     |
     * | 52     | 16             | amount                       |
     * | 68     | 32             | destinatinChainId            |
     */
    function _bridgeGasZip(uint256 currentOffset) internal returns (uint256) {
        assembly {
            function revertWith(code) {
                mstore(0, code)
                revert(0, 0x4)
            }

            let gasZipRouter := shr(96, calldataload(currentOffset))
            let receiver := calldataload(add(currentOffset, 20))
            let amount := shr(128, calldataload(add(currentOffset, 52)))
            let destinatinChainId := calldataload(add(currentOffset, 68))
            currentOffset := add(currentOffset, 100)

            // amount zero means sefbalance
            switch iszero(amount)
            case 1 {
                amount := selfbalance()
                // revert if no balance to send
                if iszero(amount) { revertWith(ZERO_BALANCE) }
            }

            // prevent same-chain
            if eq(destinatinChainId, chainid()) { revertWith(INVALID_DESTINATION) }

            // check that receiver is nonzero
            if iszero(receiver) { revertWith(INVALID_RECEIVER) }

            let ptr := mload(0x40)
            // deposit(uint256 destinationChains, bytes32 to)
            mstore(ptr, 0xc9630cb000000000000000000000000000000000000000000000000000000000)
            mstore(add(ptr, 0x04), destinatinChainId)
            mstore(add(ptr, 0x24), receiver)

            if iszero(call(gas(), gasZipRouter, amount, ptr, 0x44, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }
        return currentOffset;
    }
}

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

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

contract SquidRouter is BaseUtils {
    /**
     * @notice Handles SquidRouter bridging operations
     * @param currentOffset Current position in the calldata
     * @return Updated calldata offset after processing
     *
     * Generic layout:
     * | Offset | Length (bytes) | Description                                |
     * |--------|----------------|--------------------------------------------|
     * | 0      | 20             | gateway                                    |
     * | 20     | 20             | token to be bridged                        |
     */
    function _bridgeSquidRouter(uint256 currentOffset) internal returns (uint256) {
        address gateway;
        address asset;

        assembly {
            gateway := shr(96, calldataload(currentOffset))
            currentOffset := add(currentOffset, 20)
            asset := shr(96, calldataload(currentOffset))
            currentOffset := add(currentOffset, 20)
        }

        return _squidRouterBridgeCall(gateway, asset, currentOffset);
    }

    /*
     *
     * | Offset       | Length (bytes) | Description                                |
     * |--------------|----------------|--------------------------------------------|
     * | 0            | 2              | bridgedTokenSymbol.length: sl              |
     * | 2            | 2              | destinationChain.length: dl                |
     * | 4            | 2              | destinationAddress.length: al              |
     * | 6            | 2              | payload.length: pl                         |
     * | 8            | 16             | amount                                     |
     * | 24           | 16             | nativeAmount                               |
     * | 40           | 20             | gasRefundRecipient                         |
     * | 60           | 1              | enableExpress                              |
     * | 61           | s1             | bridgedTokenSymbol                         |
     * | 61+s1        | dl             | destinationChain                           |
     * | 61+s1+dl     | al             | destinationAddress                         |
     * | 61+s1+dl+al  | pl             | payload                                    |
     */
    function _squidRouterBridgeCall(address gateway, address asset, uint256 currentOffset) private returns (uint256 ptr) {
        assembly {
            ptr := mload(0x40)
            {
                let firstThenAmount := calldataload(currentOffset)
                let symbolLen := shr(240, firstThenAmount)
                let destLen := shr(240, shl(16, firstThenAmount))
                let contractAddrLen := shr(240, shl(32, firstThenAmount))
                let payloadLen := shr(240, shl(48, firstThenAmount))
                firstThenAmount := shr(128, shl(64, firstThenAmount))

                let nativeAmount := shr(128, calldataload(add(currentOffset, 24)))
                if gt(nativeAmount, selfbalance()) {
                    mstore(0x00, INSUFFICIENT_VALUE)
                    revert(0x00, 0x04)
                }
                let gasRefundRecipient := calldataload(add(currentOffset, 40))
                let enableExpress := and(UINT8_MASK, shr(88, gasRefundRecipient))
                gasRefundRecipient := shr(96, gasRefundRecipient)

                // set and store amount
                switch firstThenAmount
                // zero-> selfbalance
                case 0 {
                    mstore(0x00, ERC20_BALANCE_OF)
                    mstore(0x04, address())
                    pop(staticcall(gas(), asset, 0x00, 0x24, 0x00, 0x20))
                    mstore(add(ptr, 128), mload(0x00))
                }
                // provided amount
                default { mstore(add(ptr, 128), firstThenAmount) }

                mstore(ptr, symbolLen)
                mstore(add(ptr, 32), destLen)
                mstore(add(ptr, 64), contractAddrLen)
                mstore(add(ptr, 96), payloadLen)
                // mstore(add(ptr, 128), amount)
                mstore(add(ptr, 160), nativeAmount)
                mstore(add(ptr, 192), gasRefundRecipient)
                mstore(add(ptr, 224), enableExpress)

                currentOffset := add(currentOffset, 61)
            }

            // offsets (for strings and bytes)
            let off1
            let off2
            let off3
            let off4
            let total
            {
                // zero padding length
                let padLen1 := and(add(mload(ptr), 31), not(31))
                let padLen2 := and(add(mload(add(ptr, 32)), 31), not(31))
                let padLen3 := and(add(mload(add(ptr, 64)), 31), not(31))
                let padLen4 := and(add(mload(add(ptr, 96)), 31), not(31))

                // offsets (for strings and bytes)
                off1 := 224 // 7 args, 7 * 32 = 224
                off2 := add(off1, add(32, padLen1))
                off3 := add(off2, add(32, padLen2))
                off4 := add(off3, add(32, padLen3))

                // 4 (selector) + 224 head + dynamic sections (padded lengths + 128)
                total := add(356, add(add(padLen1, padLen2), add(padLen3, padLen4)))
            }

            mstore(add(ptr, 256), 0x2147796000000000000000000000000000000000000000000000000000000000)
            let head := add(ptr, 260)

            // head (7 args)
            mstore(head, off1)
            mstore(add(head, 32), mload(add(ptr, 128))) // amount
            mstore(add(head, 64), off2)
            mstore(add(head, 96), off3)
            mstore(add(head, 128), off4)
            mstore(add(head, 160), mload(add(ptr, 192))) // gasRefundRecipient
            mstore(add(head, 192), mload(add(ptr, 224))) // enableExpress

            function copyTo(_head, _at, offs, currOffs) -> newOffs {
                let p := add(_head, offs)
                let l := mload(_at)
                mstore(p, l)
                calldatacopy(add(p, 32), currOffs, l)
                newOffs := add(currOffs, l)
            }

            // bridgedTokenSymbol
            currentOffset := copyTo(head, ptr, off1, currentOffset)

            // destinationChain
            currentOffset := copyTo(head, add(ptr, 32), off2, currentOffset)

            // destinationAddress
            currentOffset := copyTo(head, add(ptr, 64), off3, currentOffset)

            // payload
            currentOffset := copyTo(head, add(ptr, 96), off4, currentOffset)

            mstore(0x40, add(add(ptr, 256), total))

            if iszero(call(gas(), gateway, mload(add(ptr, 160)), add(ptr, 256), total, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            // set ptr to offset as return value
            ptr := currentOffset
        }
    }
}

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

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

contract StargateV2 is BaseUtils {
    /**
     * @notice Handles Stargate V2 bridging operations
     * @dev Decodes calldata and forwards the call to the appropriate Stargate adapter function
     * @param currentOffset Current position in the calldata
     * @return Updated calldata offset after processing
     *
     * | Offset       | Length (bytes) | Description                  |
     * |--------------|----------------|------------------------------|
     * | 0            | 20             | tokenAddress                 |
     * | 20           | 20             | stargate pool                |
     * | 40           | 4              | dstEid                       |
     * | 44           | 32             | receiver                     |
     * | 76           | 20             | refundReceiver               |
     * | 96           | 16             | amount                       |
     * | 112          | 4              | slippage                     |
     * | 116          | 16             | fee                          |
     * | 132          | 1              | isBusMode                    |
     * | 133          | 2              | composeMsg.length: cl        |
     * | 135          | 2              | extraOptions.length: el      |
     * | 137          | cl             | composeMsg                   |
     * | 137+cl       | el             | extraOptions                 |
     */
    function _bridgeStargateV2(uint256 currentOffset) internal returns (uint256) {
        assembly {
            function revertWith(code) {
                mstore(0, code)
                revert(0, 4)
            }

            function getBalance(token) -> b {
                mstore(0, ERC20_BALANCE_OF)
                mstore(0x04, address())
                pop(staticcall(gas(), token, 0x0, 0x24, 0x0, 0x20))
                b := mload(0x0)
            }

            let asset
            let composeMsgLength
            let extraOptionsLength
            let amount
            let requiredValue
            let fee
            let minAmountLD

            // underlying (=0 means native)
            asset := shr(96, calldataload(currentOffset))

            // native fee
            fee := shr(128, calldataload(add(currentOffset, 116)))

            // get bytes lenght
            composeMsgLength := shr(240, calldataload(add(currentOffset, 133)))
            extraOptionsLength := shr(240, calldataload(add(currentOffset, 135)))

            amount := shr(128, calldataload(add(currentOffset, 96)))
            // native flag is high bit
            let isNative := and(NATIVE_FLAG, amount)
            // clear the native flag
            amount := and(amount, not(NATIVE_FLAG))

            let slfBal := selfbalance()
            // check if amount is 0
            switch iszero(amount)
            case 1 {
                // native is asset = 0
                switch isNative
                case 0 {
                    // use token balance
                    amount := getBalance(asset)
                    // value to send is just the fee
                    requiredValue := fee
                    // check if fee is enough
                    if gt(requiredValue, slfBal) { revertWith(INSUFFICIENT_VALUE) }
                }
                default {
                    // amount is the balance minus the fee
                    amount := sub(slfBal, fee)
                    // and value to send is everything
                    requiredValue := slfBal
                }
            }
            default {
                // native is asset = 0
                switch isNative
                case 0 {
                    // erc20 case: value is just the fee
                    requiredValue := fee
                }
                default {
                    // value to send is amount desired plus fee
                    requiredValue := add(amount, fee)
                }
                // check if we have enough to pay the fee
                if gt(requiredValue, slfBal) { revertWith(INSUFFICIENT_VALUE) }
            }

            // amount adjusted for slippage
            minAmountLD :=
                div(
                    mul(
                        amount,
                        sub(
                            FEE_DENOMINATOR,
                            shr(224, calldataload(add(currentOffset, 112))) // slippage (assured to not overflow)
                        )
                    ),
                    FEE_DENOMINATOR
                )

            // Set up function call memory
            let ptr := mload(0x40)
            // sendToken selector: 0xcbef2aa9
            mstore(ptr, 0xcbef2aa900000000000000000000000000000000000000000000000000000000)

            // sendParam struct
            mstore(add(ptr, 0x04), 128)

            // nativeFee
            mstore(add(ptr, 0x24), fee)

            // lzTokenFee
            mstore(add(ptr, 0x44), 0)

            // refund address
            mstore(add(ptr, 0x64), shr(96, calldataload(add(currentOffset, 76))))

            // sendParam struct
            mstore(add(ptr, 0x84), shr(224, calldataload(add(currentOffset, 40))))
            mstore(add(ptr, 0xa4), calldataload(add(currentOffset, 44)))
            mstore(add(ptr, 0xc4), amount)
            mstore(add(ptr, 0xe4), minAmountLD)

            // byte offsets
            // extraOptions offset
            mstore(add(ptr, 0x104), 0xe0) // this one is fixed

            // composeMsg offset
            let composeMsgOffset
            switch iszero(extraOptionsLength)
            case 1 { composeMsgOffset := 0x120 }
            case 0 {
                let divResult := div(extraOptionsLength, 32)
                let modResult := mod(extraOptionsLength, 32)
                let numWords
                switch gt(modResult, 0)
                case 1 { numWords := add(divResult, 1) }
                default { numWords := divResult }

                composeMsgOffset := add(0xe0, mul(0x20, add(numWords, 1))) // +1 for the extraOptions's length
            }
            mstore(add(ptr, 0x124), composeMsgOffset)

            // oftCmd offset
            let oftCmdOffset
            switch iszero(composeMsgLength)
            case 1 { oftCmdOffset := add(composeMsgOffset, 0x20) }
            default {
                let divResult := div(composeMsgLength, 32)
                let modResult := mod(composeMsgLength, 32)
                let numWords
                switch gt(modResult, 0)
                case 1 { numWords := add(divResult, 1) }
                default { numWords := divResult }

                oftCmdOffset := add(composeMsgOffset, mul(0x20, add(numWords, 1))) // +1 for the composeMsg's length
            }
            mstore(add(ptr, 0x144), oftCmdOffset)

            // extraOptions
            let extraOptionsPtr := add(ptr, 0x164) // fixed one, relative to ptr
            mstore(extraOptionsPtr, extraOptionsLength)
            if gt(extraOptionsLength, 0) {
                calldatacopy(add(extraOptionsPtr, 0x20), add(add(currentOffset, 137), composeMsgLength), extraOptionsLength)
            }

            // composeMsg
            let composeMsgPtr := add(composeMsgOffset, add(ptr, 0x84))
            mstore(composeMsgPtr, composeMsgLength)
            if gt(composeMsgLength, 0) { calldatacopy(add(composeMsgPtr, 0x20), add(currentOffset, 137), composeMsgLength) }

            let callSize // callsize for calling stargate

            // oftCmd
            let oftCmdPtr := add(oftCmdOffset, add(ptr, 0x84))
            switch iszero(
                shr(248, calldataload(add(currentOffset, 132))) // isTaxiMode flag (already masked)
            )
            case 1 {
                mstore(oftCmdPtr, 0x0)
                callSize := sub(add(oftCmdPtr, 0x20), ptr) // add only length word
            }
            default {
                mstore(oftCmdPtr, 0x20)
                mstore(add(oftCmdPtr, 0x20), 0)

                callSize := sub(add(oftCmdPtr, 0x40), ptr) // add length and busMode flag
            }

            // Update free memory pointer
            mstore(0x40, add(ptr, callSize))

            if iszero(call(gas(), shr(96, calldataload(add(currentOffset, 20))), requiredValue, ptr, callSize, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            currentOffset := add(add(add(currentOffset, 137), composeMsgLength), extraOptionsLength)
        }

        return currentOffset;
    }
}

// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.28;

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

// solhint-disable max-line-length

/**
 * @notice External call on any target - prevents `transferFrom` selector & call on Permit2
 */
abstract contract ExternalCallsGeneric is BaseUtils {
    /// @dev mask for selector in calldata
    bytes32 private constant SELECTOR_MASK = 0xffffffff00000000000000000000000000000000000000000000000000000000;

    // Forbidden()
    bytes4 private constant FORBIDDEN = 0xee90c468;

    function _callExternal(uint256 currentOffset) internal returns (uint256) {
        /*
         * | Offset | Length (bytes) | Description          |
         * |--------|----------------|----------------------|
         * | 0      | 20             | target               |
         * | 20     | 16             | nativeValue          |
         * | 36     | 2              | calldataLength:  cl  |
         * | 38     | cl             | calldata             |
         */
        assembly {
            // get first three addresses
            let target := shr(96, calldataload(currentOffset))

            // prevent calls to permit2
            if eq(target, 0x000000000022D473030F116dDEE9F6B43aC78BA3) {
                mstore(0x0, FORBIDDEN)
                revert(0x0, 0x4)
            }

            currentOffset := add(20, currentOffset)

            let callValue := shr(128, calldataload(currentOffset))
            currentOffset := add(16, currentOffset)

            let dataLength := shr(240, calldataload(currentOffset))
            currentOffset := add(2, currentOffset)

            switch and(NATIVE_FLAG, callValue)
            case 0 { callValue := and(callValue, UINT120_MASK) }
            default { callValue := selfbalance() }

            // free memo ptr for populating the tx
            let ptr := mload(0x40)

            // extract the selector from the calldata
            // and check if it is `transferFrom`
            if eq(and(SELECTOR_MASK, calldataload(currentOffset)), ERC20_TRANSFER_FROM) {
                mstore(0x0, FORBIDDEN)
                revert(0x0, 0x4)
            }

            // copy calldata
            calldatacopy(ptr, currentOffset, dataLength)
            if iszero(
                call(
                    gas(),
                    target,
                    callValue,
                    ptr, //
                    dataLength,
                    // the length must be correct or the call will fail
                    0x0, // output = empty
                    0x0 // output size = zero
                )
            ) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
            // increment offset by data length
            currentOffset := add(currentOffset, dataLength)
        }
        return currentOffset;
    }

    function _tryCallExternal(uint256 currentOffset, address callerAddress) internal returns (uint256) {
        /*
         * | Offset | Length (bytes) | Description          |
         * |--------|----------------|----------------------|
         * | 0      | 20             | target               |
         * | 20     | 16             | nativeValue          |
         * | 36     | 2              | calldataLength:  cl  |
         * | 38     | cl             | calldata             |
         * | 38+cl  | 1              | catchHandling        | <- 0: revert; 1: exit in catch if revert; else continue after catch
         * | 39+cl  | 2              | catchDataLength: dl  |
         * | 41+cl  | dl             | catchData            |
         */
        bool success;
        uint256 catchHandling;
        uint256 catchCalldataLength;
        assembly {
            let target := shr(96, calldataload(currentOffset))

            // prevent calls to permit2
            if eq(target, 0x000000000022D473030F116dDEE9F6B43aC78BA3) {
                mstore(0x0, FORBIDDEN)
                revert(0x0, 0x4)
            }

            currentOffset := add(20, currentOffset)

            let callValue := shr(128, calldataload(currentOffset))
            currentOffset := add(16, currentOffset)

            let dataLength := shr(240, calldataload(currentOffset))
            currentOffset := add(2, currentOffset)

            switch and(NATIVE_FLAG, callValue)
            case 0 { callValue := and(callValue, UINT120_MASK) }
            default { callValue := selfbalance() }

            // free memo ptr for populating the tx
            let ptr := mload(0x40)

            // extract the selector from the calldata
            // and check if it is `transferFrom`
            if eq(and(SELECTOR_MASK, calldataload(currentOffset)), ERC20_TRANSFER_FROM) {
                mstore(0x0, FORBIDDEN)
                revert(0x0, 0x4)
            }

            // copy calldata
            calldatacopy(ptr, currentOffset, dataLength)
            success :=
                call(
                    gas(),
                    target,
                    callValue,
                    ptr, //
                    dataLength,
                    // the length must be correct or the call will fail
                    0x0, // output = empty
                    0x0 // output size = zero
                )

            // increment offset by data length
            currentOffset := add(currentOffset, dataLength)

            let nexstSlice := calldataload(currentOffset)
            // top byte of next slice
            catchHandling := shr(248, nexstSlice)
            // case: 0 revert if not successful
            if and(iszero(catchHandling), iszero(success)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }

            catchCalldataLength := and(UINT16_MASK, shr(232, nexstSlice))
            currentOffset := add(currentOffset, 3)
        }

        // execution logic on failute
        if (!success) {
            // Catch and run fallback
            // execute further calldata if provided
            if (catchCalldataLength > 0) {
                // Calculate the absolute end position for the catch data (last param of the _deltaComposeInternal)
                uint256 catchMaxIndex = currentOffset + catchCalldataLength;
                _deltaComposeInternal(callerAddress, currentOffset, catchMaxIndex);
                // Update currentOffset to the end of catch data
                currentOffset = catchMaxIndex;
            }
            // case 1 - exit function execution here
            if (catchHandling == 1) {
                assembly {
                    return(0, 0)
                }
            }
        } else {
            // if the call was successful, skip the catch data
            assembly {
                currentOffset := add(currentOffset, catchCalldataLength)
            }
        }
        return currentOffset;
    }

    function _deltaComposeInternal(
        address callerAddress,
        uint256 currentOffset,
        uint256 calldataLength //
    )
        internal
        virtual;
}

// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.28;

import {BaseUtils} from "contracts/1delta/composer/generic/BaseUtils.sol";

/**
 * @title Token transfer contract - should work across all EVMs - use Uniswap style Permit2
 */
contract AssetTransfers is BaseUtils {
    // approval slot
    bytes32 private constant CALL_MANAGEMENT_APPROVALS = 0x1aae13105d9b6581c36534caba5708726e5ea1e03175e823c989a5756966d1f3;

    /// @notice fixed selector transferFrom(...) on permit2
    bytes32 private constant PERMIT2_TRANSFER_FROM = 0x36c7851600000000000000000000000000000000000000000000000000000000;

    /// @notice deterministically deployed pemrit2 address
    address private constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

    /*
     * | Offset | Length (bytes) | Description         |
     * |--------|----------------|---------------------|
     * | 0      | 20             | asset               |
     * | 20     | 20             | receiver            |
     * | 40     | 16             | amount              |
     */
    function _permit2TransferFrom(uint256 currentOffset, address callerAddress) internal returns (uint256) {
        ////////////////////////////////////////////////////
        // Transfers tokens from caller to this address
        // zero amount flags that the entire balance is sent
        ////////////////////////////////////////////////////
        assembly {
            let underlying := shr(96, calldataload(currentOffset))
            let receiver := shr(96, calldataload(add(currentOffset, 20)))
            let amount := shr(128, calldataload(add(currentOffset, 40)))

            // when entering 0 as amount, use the callwe balance
            if iszero(amount) {
                // selector for balanceOf(address)
                mstore(0, ERC20_BALANCE_OF)
                // add this address as parameter
                mstore(0x04, callerAddress)
                // call to token
                pop(
                    staticcall(
                        gas(),
                        underlying, // token
                        0x0,
                        0x24,
                        0x0,
                        0x20
                    )
                )
                // load the retrieved balance
                amount := mload(0x0)
            }

            let ptr := mload(0x40)
            mstore(ptr, PERMIT2_TRANSFER_FROM)
            mstore(add(ptr, 0x04), callerAddress)
            mstore(add(ptr, 0x24), receiver)
            mstore(add(ptr, 0x44), amount)
            mstore(add(ptr, 0x64), underlying)
            if iszero(call(gas(), PERMIT2, 0, ptr, 0x84, 0x0, 0x0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
            currentOffset := add(currentOffset, 56)
        }
        return currentOffset;
    }

    /*
     * | Offset | Length (bytes) | Description         |
     * |--------|----------------|---------------------|
     * | 0      | 20             | asset               |
     * | 20     | 20             | receiver            |
     * | 40     | 16             | amount              |
     */
    function _transferFrom(uint256 currentOffset, address callerAddress) internal returns (uint256) {
        ////////////////////////////////////////////////////
        // Transfers tokens from caller to this address
        // zero amount flags that the entire balance is sent
        ////////////////////////////////////////////////////
        assembly {
            let underlying := shr(96, calldataload(currentOffset))
            let receiver := shr(96, calldataload(add(currentOffset, 20)))
            let amount := shr(128, calldataload(add(currentOffset, 40)))

            // when entering 0 as amount, use the callwe balance
            if iszero(amount) {
                // selector for balanceOf(address)
                mstore(0, ERC20_BALANCE_OF)
                // add this address as parameter
                mstore(0x04, callerAddress)
                // call to token
                pop(
                    staticcall(
                        gas(),
                        underlying, // token
                        0x0,
                        0x24,
                        0x0,
                        0x20
                    )
                )
                // load the retrieved balance
                amount := mload(0x0)
            }

            let ptr := mload(0x40) // free memory pointer

            // selector for transferFrom(address,address,uint256)
            mstore(ptr, ERC20_TRANSFER_FROM)
            mstore(add(ptr, 0x04), callerAddress)
            mstore(add(ptr, 0x24), receiver)
            mstore(add(ptr, 0x44), amount)

            let success := call(gas(), underlying, 0, ptr, 0x64, ptr, 32)

            let rdsize := returndatasize()

            if iszero(
                and(
                    success, // call itself succeeded
                    or(
                        iszero(rdsize), // no return data, or
                        and(
                            gt(rdsize, 31), // at least 32 bytes
                            eq(mload(ptr), 1) // starts with uint256(1)
                        )
                    )
                )
            ) {
                returndatacopy(0, 0, rdsize)
                revert(0, rdsize)
            }
            currentOffset := add(currentOffset, 56)
        }
        return currentOffset;
    }

    /*
     * | Offset | Length (bytes) | Description         |
     * |--------|----------------|---------------------|
     * | 0      | 20             | asset               |
     * | 20     | 20             | receiver            | <- use wrapped native here to wrap
     * | 40     | 1              | config              |
     * | 41     | 16             | amount              |
     */
    function _sweep(uint256 currentOffset) internal returns (uint256) {
        ////////////////////////////////////////////////////
        // Transfers either token or native balance from this
        // contract to receiver. Reverts if minAmount is
        // less than the contract balance
        //  config
        //  0: sweep balance and validate against amount
        //     fetches the balance and checks balance >= amount
        //  1: transfer amount to receiver, skip validation
        ////////////////////////////////////////////////////
        assembly {
            let underlying := shr(96, calldataload(currentOffset))
            // we skip shr by loading the address to the lower bytes
            let receiver := shr(96, calldataload(add(currentOffset, 20)))
            // load so that amount is in the lower 14 bytes already
            let providedAmount := calldataload(add(currentOffset, 25))
            // load config
            let config := and(UINT8_MASK, shr(128, providedAmount))
            // mask amount
            providedAmount := and(UINT128_MASK, providedAmount)

            // initialize transferAmount
            let transferAmount

            // zero address is native
            switch iszero(underlying)
            ////////////////////////////////////////////////////
            // Transfer token
            ////////////////////////////////////////////////////
            case 0 {
                // for config = 0, the amount is the balance and we
                // check that the balance is larger tha the amount provided
                switch config
                case 0 {
                    // selector for balanceOf(address)
                    mstore(0, ERC20_BALANCE_OF)
                    // add this address as parameter
                    mstore(0x04, address())
                    // call to token
                    pop(
                        staticcall(
                            gas(),
                            underlying,
                            0x0,
                            0x24,
                            0x0,
                            0x20 //
                        )
                    )
                    // load the retrieved balance
                    transferAmount := mload(0x0)
                    // revert if balance is not enough
                    if lt(transferAmount, providedAmount) {
                        mstore(0, SLIPPAGE)
                        revert(0, 0x4)
                    }
                }
                default { transferAmount := providedAmount }

                if gt(transferAmount, 0) {
                    let ptr := mload(0x40) // free memory pointer

                    // selector for transfer(address,uint256)
                    mstore(ptr, ERC20_TRANSFER)
                    mstore(add(ptr, 0x04), receiver)
                    mstore(add(ptr, 0x24), transferAmount)

                    let success := call(gas(), underlying, 0, ptr, 0x44, ptr, 32)

                    let rdsize := returndatasize()

                    if iszero(
                        and(
                            success, // call itself succeeded
                            or(
                                iszero(rdsize), // no return data, or
                                and(
                                    gt(rdsize, 31), // at least 32 bytes
                                    eq(mload(ptr), 1) // starts with uint256(1)
                                )
                            )
                        )
                    ) {
                        returndatacopy(0, 0, rdsize)
                        revert(0, rdsize)
                    }
                }
            }
            ////////////////////////////////////////////////////
            // Transfer native
            ////////////////////////////////////////////////////
            default {
                switch config
                case 0 {
                    transferAmount := selfbalance()
                    // revert if balance is not enough
                    if lt(transferAmount, providedAmount) {
                        mstore(0, SLIPPAGE)
                        revert(0, 0x4)
                    }
                }
                default { transferAmount := providedAmount }

                if gt(transferAmount, 0) {
                    if iszero(
                        call(
                            gas(),
                            receiver,
                            transferAmount,
                            0x0, // input = empty for fallback/receive
                            0x0, // input size = zero
                            0x0, // output = empty
                            0x0 // output size = zero
                        )
                    ) {
                        mstore(0, NATIVE_TRANSFER)
                        revert(0, 0x4) // revert when native transfer fails
                    }
                }
            }
            currentOffset := add(currentOffset, 57)
        }
        return currentOffset;
    }

    /*
     * | Offset | Length (bytes) | Description          |
     * |--------|----------------|----------------------|
     * | 0      | 20             | token                |
     * | 20     | 20             | target               |
     */
    function _approve(uint256 currentOffset) internal returns (uint256) {
        assembly {
            // load underlying and target
            let underlying := shr(96, calldataload(currentOffset))
            let target := shr(96, calldataload(add(currentOffset, 20)))
            // check whether the approval alderady was done
            // if so, we can skip this part silently
            mstore(0x0, underlying)
            mstore(0x20, CALL_MANAGEMENT_APPROVALS)
            mstore(0x20, keccak256(0x0, 0x40))
            mstore(0x0, target)
            let key := keccak256(0x0, 0x40)
            // check if already approved
            if iszero(sload(key)) {
                let ptr := mload(0x40)
                // selector for approve(address,uint256)
                mstore(ptr, ERC20_APPROVE)
                mstore(add(ptr, 0x04), target)
                mstore(add(ptr, 0x24), MAX_UINT256)
                pop(
                    call(
                        gas(),
                        underlying, //
                        0,
                        ptr,
                        0x44,
                        ptr,
                        32
                    )
                )
                sstore(key, 1)
            }
            currentOffset := add(currentOffset, 40)
        }
        return currentOffset;
    }

    /*
     * | Offset | Length (bytes) | Description         |
     * |--------|----------------|---------------------|
     * | 0      | 20             | wrappedNativeAddress|
     * | 20     | 20             | receiver            |
     * | 40     | 1              | config              |
     * | 41     | 16             | amount              |
     */
    function _unwrap(uint256 currentOffset) internal virtual returns (uint256) {
        ////////////////////////////////////////////////////
        // Transfers either token or native balance from this
        // contract to receiver. Reverts if minAmount is
        // less than the contract balance
        //  config
        //  0: sweep balance and validate against amount
        //     fetches the balance and checks balance >= amount
        //  1: transfer amount to receiver, skip validation
        ////////////////////////////////////////////////////
        assembly {
            // load receiver
            let wrapperAsset := shr(96, calldataload(currentOffset))
            // load receiver
            let receiver := shr(96, calldataload(add(currentOffset, 20)))
            // load so that amount is in the lower 14 bytes already
            let providedAmount := calldataload(add(currentOffset, 25))
            // load config
            let config := and(UINT8_MASK, shr(128, providedAmount))
            // mask amount
            providedAmount := and(UINT128_MASK, providedAmount)

            let transferAmount

            // mask away the top bitmap
            providedAmount := and(UINT120_MASK, providedAmount)
            // validate if config is zero, otherwise skip
            switch config
            case 0 {
                // selector for balanceOf(address)
                mstore(0x0, ERC20_BALANCE_OF)
                // add this address as parameter
                mstore(0x4, address())

                // call to underlying
                pop(staticcall(gas(), wrapperAsset, 0x0, 0x24, 0x0, 0x20))

                transferAmount := mload(0x0)
                if lt(transferAmount, providedAmount) {
                    mstore(0, SLIPPAGE)
                    revert(0, 0x4)
                }
            }
            default { transferAmount := providedAmount }

            if gt(transferAmount, 0) {
                // selector for withdraw(uint256)
                mstore(0x0, 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000)
                mstore(0x4, transferAmount)
                if iszero(
                    call(
                        gas(),
                        wrapperAsset,
                        0x0, // no ETH
                        0x0, // start of data
                        0x24, // input size = selector plus amount
                        0x0, // output = empty
                        0x0 // output size = zero
                    )
                ) {
                    // should only revert if receiver cannot receive native
                    mstore(0, NATIVE_TRANSFER)
                    revert(0, 0x4)
                }
                // transfer to receiver if different from this address
                if xor(receiver, address()) {
                    // transfer native to receiver
                    if iszero(
                        call(
                            gas(),
                            receiver,
                            transferAmount,
                            0x0, // input = empty for fallback
                            0x0, // input size = zero
                            0x0, // output = empty
                            0x0 // output size = zero
                        )
                    ) {
                        // should only revert if receiver cannot receive native
                        mstore(0, NATIVE_TRANSFER)
                        revert(0, 0x4)
                    }
                }
            }
            currentOffset := add(currentOffset, 57)
        }
        return currentOffset;
    }
}

// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.28;

import {AssetTransfers} from "./AssetTransfers.sol";
import {TransferIds} from "../enums/DeltaEnums.sol";

/**
 * @title Token transfer contract - should work across all EVMs - user Uniswap style Permit2
 */
contract Transfers is AssetTransfers {
    function _transfers(uint256 currentOffset, address callerAddress) internal returns (uint256) {
        uint256 transferOperation;
        assembly {
            let firstSlice := calldataload(currentOffset)
            transferOperation := shr(248, firstSlice)
            currentOffset := add(currentOffset, 1)
        }
        if (transferOperation == TransferIds.TRANSFER_FROM) {
            return _transferFrom(currentOffset, callerAddress);
        } else if (transferOperation == TransferIds.SWEEP) {
            return _sweep(currentOffset);
        } else if (transferOperation == TransferIds.UNWRAP_WNATIVE) {
            return _unwrap(currentOffset);
        } else if (transferOperation == TransferIds.PERMIT2_TRANSFER_FROM) {
            return _permit2TransferFrom(currentOffset, callerAddress);
        } else if (transferOperation == TransferIds.APPROVE) {
            return _approve(currentOffset);
        } else {
            _invalidOperation();
        }
    }
}

File 12 of 14 : Errors.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.28;

/**
 * @title Raw error data holder contract
 */
abstract contract DeltaErrors {
    ////////////////////////////////////////////////////
    // Error data
    ////////////////////////////////////////////////////

    // the compiler should drop these since they are unused
    // but it should still be included in the ABI to parse the
    // errors below
    error Slippage();
    error NativeTransferFailed();
    error WrapFailed();
    error InvalidDex();
    error BadPool();
    error InvalidFlashLoan();
    error InvalidOperation();
    error InvalidCaller();
    error InvalidInitiator();
    error InvalidCalldata();
    error Target();
    error InvalidDexId();

    // Slippage()
    bytes4 internal constant SLIPPAGE = 0x7dd37f70;
    // NativeTransferFailed()
    bytes4 internal constant NATIVE_TRANSFER = 0xf4b3b1bc;
    // WrapFailed()
    bytes4 internal constant WRAP = 0xc30d93ce;
    // InvalidDex()
    bytes4 internal constant INVALID_DEX = 0x7948739e;
    // BadPool()
    bytes4 internal constant BAD_POOL = 0xb2c02722;
    // InvalidFlashLoan()
    bytes4 internal constant INVALID_FLASH_LOAN = 0xbafe1c53;
    // InvalidOperation()
    bytes4 internal constant INVALID_OPERATION = 0x398d4d32;
    // InvalidCaller()
    bytes4 internal constant INVALID_CALLER = 0x48f5c3ed;
    // InvalidInitiator()
    bytes4 internal constant INVALID_INITIATOR = 0xbfda1f28;
    // InvalidCalldata()
    bytes4 internal constant INVALID_CALLDATA = 0x8129bbcd;
    // Target()
    bytes4 internal constant INVALID_TARGET = 0x4fe6f55f;
    // InvalidDexId()
    bytes4 internal constant INVALID_DEX_ID = 0x0bbef348;

    function _invalidOperation() internal pure {
        assembly {
            mstore(0, INVALID_OPERATION)
            revert(0, 0x4)
        }
    }
}

File 13 of 14 : Masks.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity ^0.8.28;

abstract contract Masks {
    /// @dev Mask of lower 20 bytes.
    uint256 internal constant ADDRESS_MASK = 0x00ffffffffffffffffffffffffffffffffffffffff;
    /// @dev Mask of lower 1 byte.
    uint256 internal constant UINT8_MASK = 0xff;
    /// @dev Mask of lower 2 bytes.
    uint256 internal constant UINT16_MASK = 0xffff;
    /// @dev Mask of lower 3 bytes.
    uint256 internal constant UINT24_MASK = 0xffffff;
    /// @dev Mask of lower 4 bytes.
    uint256 internal constant UINT32_MASK = 0xffffffff;
    /// @dev Mask of lower 16 bytes.
    uint256 internal constant UINT128_MASK = 0x00000000000000000000000000000000ffffffffffffffffffffffffffffffff;
    /// @dev Mask of lower 15 bytes.
    uint256 internal constant UINT120_MASK = 0x0000000000000000000000000000000000ffffffffffffffffffffffffffffff;
    /// @dev MIN_SQRT_RATIO + 1 from Uniswap's TickMath
    uint160 internal constant MIN_SQRT_RATIO = 4295128740;
    /// @dev MAX_SQRT_RATIO - 1 from Uniswap's TickMath
    uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970341;
    /// @dev Maximum Uint256 value
    uint256 internal constant MAX_UINT256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
    /// @dev Use this to distinguish FF upper bytes addresses and lower bytes addresses
    uint256 internal constant FF_ADDRESS_COMPLEMENT = 0x000000000000000000000000000000000000000000ffffffffffffffffffffff;

    /// @dev We use uint112-encoded amounts to typically fit one bit flag, one path length (uint16)
    ///      add 2 amounts (2xuint112) into 32bytes, as such we use this mask for extracting those
    uint256 internal constant UINT112_MASK = 0x000000000000000000000000000000000000ffffffffffffffffffffffffffff;

    /// @dev Mask for Is Native
    uint256 internal constant NATIVE_FLAG = 1 << 127;
    /// @dev Mask for shares
    uint256 internal constant USE_SHARES_FLAG = 1 << 126;
}

File 14 of 14 : ERC20Selectors.sol
// SPDX-License-Identifier: BUSL-1.1

pragma solidity 0.8.28;

abstract contract ERC20Selectors {
    ////////////////////////////////////////////////////
    // ERC20 selectors
    ////////////////////////////////////////////////////

    /// @dev selector for approve(address,uint256)
    bytes32 internal constant ERC20_APPROVE = 0x095ea7b300000000000000000000000000000000000000000000000000000000;

    /// @dev selector for transferFrom(address,address,uint256)
    bytes32 internal constant ERC20_TRANSFER_FROM = 0x23b872dd00000000000000000000000000000000000000000000000000000000;

    /// @dev selector for transfer(address,uint256)
    bytes32 internal constant ERC20_TRANSFER = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;

    /// @dev selector for allowance(address,address)
    bytes32 internal constant ERC20_ALLOWANCE = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000;

    /// @dev selector for balanceOf(address)
    bytes32 internal constant ERC20_BALANCE_OF = 0x70a0823100000000000000000000000000000000000000000000000000000000;
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"name":"BadPool","type":"error"},{"inputs":[],"name":"BridgeFailed","type":"error"},{"inputs":[],"name":"InsufficientAmount","type":"error"},{"inputs":[],"name":"InsufficientValue","type":"error"},{"inputs":[{"internalType":"uint16","name":"assetId","type":"uint16"}],"name":"InvalidAssetId","type":"error"},{"inputs":[],"name":"InvalidCalldata","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidDestination","type":"error"},{"inputs":[],"name":"InvalidDex","type":"error"},{"inputs":[],"name":"InvalidDexId","type":"error"},{"inputs":[],"name":"InvalidFlashLoan","type":"error"},{"inputs":[],"name":"InvalidInitiator","type":"error"},{"inputs":[],"name":"InvalidOperation","type":"error"},{"inputs":[],"name":"InvalidReceiver","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"Slippage","type":"error"},{"inputs":[{"internalType":"uint256","name":"expected","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"SlippageTooHigh","type":"error"},{"inputs":[],"name":"Target","type":"error"},{"inputs":[],"name":"WrapFailed","type":"error"},{"inputs":[],"name":"ZeroBalance","type":"error"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"deltaForwardCompose","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052348015600f57600080fd5b506115bd8061001f6000396000f3fe6080604052600436106100225760003560e01c80636a0c90ff1461002e57600080fd5b3661002957005b600080fd5b61004161003c3660046114d9565b610043565b005b604460243581013361005681848461005d565b5050505050565b60018201913560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810161009d576100968361012c565b92506100da565b602181036100af57610096838561025d565b604081036100c15761009683856103f8565b609081036100d2576100968361046f565b6100da6104d1565b8183106100e757506100ed565b5061005d565b80821115610127576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000813560601c6e22d473030f116ddee9f6b43ac78ba38103610173577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026830192601481013560801c906024013560f01c6f80000000000000000000000000000000821680156101a9574792506101be565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd0000000000000000000000000000000000000000000000000000000086357fffffffff000000000000000000000000000000000000000000000000000000001603610236577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b81868237600080838386885af1610251573d6000803e3d6000fd5b50939093019392505050565b600080600080853560601c6e22d473030f116ddee9f6b43ac78ba381036102a8577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026870196601481013560801c906024013560f01c6f80000000000000000000000000000000821680156102de574792506102f3565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd000000000000000000000000000000000000000000000000000000008a357fffffffff00000000000000000000000000000000000000000000000000000000160361036b577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b818a8237600080838386885af1965050808901985050505085358060f81c925083158315161561039f573d6000803e3d6000fd5b8060e81c61ffff16915050600386019550826103e65780156103d75760006103c7828861154d565b90506103d486888361005d565b95505b816001036103e157005b6103eb565b948501945b8593505050505b92915050565b60018201916000903560f81c8061041b5761041384846104fb565b9150506103f2565b6001810361042c57610413846105c5565b6003810361043d576104138461077a565b6004810361044f5761041384846108db565b600581036104605761041384610996565b6104686104d1565b5092915050565b60018101906000903560f81c806104905761048983610a56565b9392505050565b600a81036104a15761048983610da8565b601481036104b25761048983611146565b601e81036104c3576104898361116f565b6104cb6104d1565b50919050565b7f398d4d320000000000000000000000000000000000000000000000000000000060005260046000fd5b6000823560601c601484013560601c602885013560801c80610550577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081528560048201528260248201528160448201526020816064836000885af193503d92506001815114601f84111683151784166105b557826000803e826000fd5b5050506038939093019392505050565b6000813560601c601483013560601c60198401358060801c60ff16816fffffffffffffffffffffffffffffffff16915060008415600081146106895782801561061057849250610645565b47925084831015610645577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5081156106845760008060008085895af1610684577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b610769565b82801561069857849250610703565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa50600051925084831015610703577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b508115610769576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815285600482015282602482015260208160448360008b5af13d6001835114601f821116811517821661076557806000803e806000fd5b5050505b505050603994909401949350505050565b60008135606090811c906014840135901c60198401356effffffffffffffffffffffffffffff81169060801c60ff16848180156107b957839150610824565b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000895afa50600051915083821015610824577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5080156108cb577f2e1a7d4d00000000000000000000000000000000000000000000000000000000600052806004526000806024600080895af161088c577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b3084146108cb5760008060008084885af16108cb577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050506039939093019392505050565b6000823560601c601484013560601c602885013560801c80610930577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f36c7851600000000000000000000000000000000000000000000000000000000815285600482015282602482015281604482015283606482015260008060848360006e22d473030f116ddee9f6b43ac78ba35af16105b5573d6000803e3d6000fd5b6000813560601c601483013560601c816000527f1aae13105d9b6581c36534caba5708726e5ea1e03175e823c989a5756966d1f360205260406000206020528060005260406000208054610a48576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528260048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044836000885af15050600181555b505050602891909101919050565b6000610aa2565b8060005260046000fd5b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000845afa505060005190565b8135606090811c90608584013560f090811c91608786013590911c90850135608090811c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff811691600091607489013590911c9082906f800000000000000000000000000000001647851560018114610b6157828015610b26578588019650610b2a565b8596505b5081861115610b5c57610b5c7f1101129400000000000000000000000000000000000000000000000000000000610a5d565b610bb6565b828015610b75578583039750829650610bb4565b610b7e8b610a67565b975085965082871115610bb457610bb47f1101129400000000000000000000000000000000000000000000000000000000610a5d565b505b505050633b9aca0060708a013560e01c633b9aca0003850204905060405196507fcbef2aa90000000000000000000000000000000000000000000000000000000087526080600488015281602488015260006044880152604c89013560601c6064880152602889013560e01c6084880152602c89013560a48801528360c48801528060e4880152505060e061010486015260009150821560018114610c60578015610c6a57610c9f565b6101209250610c9f565b6020840460208506600080821160018114610c8757839150610c8e565b6001840191505b506001810160200260e00195505050505b50816101248601526000841560018114610ceb576020860460208706600080821160018114610cd057839150610cd7565b6001840191505b506001810160200287019450505050610cf2565b6020840191505b50610144860181905261016486018481528415610d1657848660898b010160208301375b50918501608401848152918415610d3257846089890160208501375b60009250850160849081019088013560f81c1560018114610d655760208252600060208301528660408301039350610d72565b6000825286602083010393505b505081850160405260008083878460148c013560601c5af1610d98573d6000803e3d6000fd5b5050930190920160890192915050565b6000602882013560601c605c83013560801c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff8116906f800000000000000000000000000000001660aa85013560f01c84831560018114610e44578315610e3f5747851115610e3b577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b8491505b610e92565b838015610e5657479550859250610e90565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa5060005195505b505b50606c87013560801c925082841160018114610ed2577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b9284039250608487013560f881901c9060f01c60ff1681810360006001848414610fac5760ff83901d8084180380600c8114610f5857600b8114610f6557600a8114610f725760098114610f7f5760088114610f8b5760078114610f975760068114610fa25760005b82811015610f5257600a9390930292600101610f3b565b50610fa9565b64e8d4a510009250610fa9565b64174876e8009250610fa9565b6402540be4009250610fa9565b633b9aca009250610fa9565b6305f5e1009250610fa9565b629896809250610fa9565b620f424092505b50505b84841060018114610fd45797810297633b9aca00607c8e013560e01c8b028302049250610fee565b81633b9aca0002607c8e013560e01c8b0204925081890498505b505080871160018114611025577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b908703905060405196507fad5425c600000000000000000000000000000000000000000000000000000000875260148b013560601c600488015260868b01356024880152886044880152603c8b013560648801528760848801528060a488015250505050608087013560e01c60c4840152600060e48401524261010484015260a687013560e01c6101248401526000610144840152610180610164840152816101848401526000821160018114611100576000806101a486858c3560601c5af16110f3573d6000803e3d6000fd5b6101a48401604052611135565b8260ac89016101a4860137600080846101a40186858c3560601c5af161112a573d6000803e3d6000fd5b826101c40184016040525b50509490940160ac01949350505050565b60288101906000908035606090811c9160140135901c61116782828661127d565b949350505050565b6000813560601c6014830135603484013560801c60448501356064860195508115600181036111c957479250826111c9576111c97f669567ea00000000000000000000000000000000000000000000000000000000610a5d565b504681036111fa576111fa7fac6b05f500000000000000000000000000000000000000000000000000000000610a5d565b82611228576112287f1e4ec46b00000000000000000000000000000000000000000000000000000000610a5d565b6040517fc9630cb000000000000000000000000000000000000000000000000000000000815281600482015283602482015260008060448386895af1611272573d6000803e3d6000fd5b509495945050505050565b6000604051905081358060f01c8160101b60f01c8260201b60f01c8360301b60f01c8460401b60801c9450601887013560801c478111156112e2577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b60288801358060581c60ff168160601c91508760008114611308578860808b0152611345565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008f5afa5060005160808b01525b5086895260208901869052604089018590526060890184905260a089019290925260c0880181905260e08089018390527f2147796000000000000000000000000000000000000000000000000000000000610100808b01919091526101048a0182815260808b01516101248c0152601f9889017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09081169283016101448d01819052988a0181169092016101208101610164808e01829052988b018416808301610140016101848f018190526101a48f01979097526101c48e0197909752603d9d909d019c939a509798929793969290950116909201010190611461565b60008382018351808252808760208401379590950195945050505050565b61146d88878984611443565b975061147e888660208a0184611443565b975061148f888560408a0184611443565b97506114a0888460608a0184611443565b9750508061010087010160405260008082610100890160a08a01518d5af16114cc573d6000803e3d6000fd5b5094979650505050505050565b600080602083850312156114ec57600080fd5b823567ffffffffffffffff81111561150357600080fd5b8301601f8101851361151457600080fd5b803567ffffffffffffffff81111561152b57600080fd5b85602082840101111561153d57600080fd5b6020919091019590945092505050565b808201808211156103f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea264697066735822122027294167b7006c7aef9b0238bcddf1a1d540bf2131f293e4e53fcf24a87fb9f364736f6c634300081c0033

Deployed Bytecode

0x6080604052600436106100225760003560e01c80636a0c90ff1461002e57600080fd5b3661002957005b600080fd5b61004161003c3660046114d9565b610043565b005b604460243581013361005681848461005d565b5050505050565b60018201913560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810161009d576100968361012c565b92506100da565b602181036100af57610096838561025d565b604081036100c15761009683856103f8565b609081036100d2576100968361046f565b6100da6104d1565b8183106100e757506100ed565b5061005d565b80821115610127576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000813560601c6e22d473030f116ddee9f6b43ac78ba38103610173577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026830192601481013560801c906024013560f01c6f80000000000000000000000000000000821680156101a9574792506101be565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd0000000000000000000000000000000000000000000000000000000086357fffffffff000000000000000000000000000000000000000000000000000000001603610236577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b81868237600080838386885af1610251573d6000803e3d6000fd5b50939093019392505050565b600080600080853560601c6e22d473030f116ddee9f6b43ac78ba381036102a8577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026870196601481013560801c906024013560f01c6f80000000000000000000000000000000821680156102de574792506102f3565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd000000000000000000000000000000000000000000000000000000008a357fffffffff00000000000000000000000000000000000000000000000000000000160361036b577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b818a8237600080838386885af1965050808901985050505085358060f81c925083158315161561039f573d6000803e3d6000fd5b8060e81c61ffff16915050600386019550826103e65780156103d75760006103c7828861154d565b90506103d486888361005d565b95505b816001036103e157005b6103eb565b948501945b8593505050505b92915050565b60018201916000903560f81c8061041b5761041384846104fb565b9150506103f2565b6001810361042c57610413846105c5565b6003810361043d576104138461077a565b6004810361044f5761041384846108db565b600581036104605761041384610996565b6104686104d1565b5092915050565b60018101906000903560f81c806104905761048983610a56565b9392505050565b600a81036104a15761048983610da8565b601481036104b25761048983611146565b601e81036104c3576104898361116f565b6104cb6104d1565b50919050565b7f398d4d320000000000000000000000000000000000000000000000000000000060005260046000fd5b6000823560601c601484013560601c602885013560801c80610550577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081528560048201528260248201528160448201526020816064836000885af193503d92506001815114601f84111683151784166105b557826000803e826000fd5b5050506038939093019392505050565b6000813560601c601483013560601c60198401358060801c60ff16816fffffffffffffffffffffffffffffffff16915060008415600081146106895782801561061057849250610645565b47925084831015610645577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5081156106845760008060008085895af1610684577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b610769565b82801561069857849250610703565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa50600051925084831015610703577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b508115610769576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815285600482015282602482015260208160448360008b5af13d6001835114601f821116811517821661076557806000803e806000fd5b5050505b505050603994909401949350505050565b60008135606090811c906014840135901c60198401356effffffffffffffffffffffffffffff81169060801c60ff16848180156107b957839150610824565b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000895afa50600051915083821015610824577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5080156108cb577f2e1a7d4d00000000000000000000000000000000000000000000000000000000600052806004526000806024600080895af161088c577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b3084146108cb5760008060008084885af16108cb577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050506039939093019392505050565b6000823560601c601484013560601c602885013560801c80610930577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f36c7851600000000000000000000000000000000000000000000000000000000815285600482015282602482015281604482015283606482015260008060848360006e22d473030f116ddee9f6b43ac78ba35af16105b5573d6000803e3d6000fd5b6000813560601c601483013560601c816000527f1aae13105d9b6581c36534caba5708726e5ea1e03175e823c989a5756966d1f360205260406000206020528060005260406000208054610a48576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528260048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044836000885af15050600181555b505050602891909101919050565b6000610aa2565b8060005260046000fd5b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000845afa505060005190565b8135606090811c90608584013560f090811c91608786013590911c90850135608090811c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff811691600091607489013590911c9082906f800000000000000000000000000000001647851560018114610b6157828015610b26578588019650610b2a565b8596505b5081861115610b5c57610b5c7f1101129400000000000000000000000000000000000000000000000000000000610a5d565b610bb6565b828015610b75578583039750829650610bb4565b610b7e8b610a67565b975085965082871115610bb457610bb47f1101129400000000000000000000000000000000000000000000000000000000610a5d565b505b505050633b9aca0060708a013560e01c633b9aca0003850204905060405196507fcbef2aa90000000000000000000000000000000000000000000000000000000087526080600488015281602488015260006044880152604c89013560601c6064880152602889013560e01c6084880152602c89013560a48801528360c48801528060e4880152505060e061010486015260009150821560018114610c60578015610c6a57610c9f565b6101209250610c9f565b6020840460208506600080821160018114610c8757839150610c8e565b6001840191505b506001810160200260e00195505050505b50816101248601526000841560018114610ceb576020860460208706600080821160018114610cd057839150610cd7565b6001840191505b506001810160200287019450505050610cf2565b6020840191505b50610144860181905261016486018481528415610d1657848660898b010160208301375b50918501608401848152918415610d3257846089890160208501375b60009250850160849081019088013560f81c1560018114610d655760208252600060208301528660408301039350610d72565b6000825286602083010393505b505081850160405260008083878460148c013560601c5af1610d98573d6000803e3d6000fd5b5050930190920160890192915050565b6000602882013560601c605c83013560801c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff8116906f800000000000000000000000000000001660aa85013560f01c84831560018114610e44578315610e3f5747851115610e3b577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b8491505b610e92565b838015610e5657479550859250610e90565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa5060005195505b505b50606c87013560801c925082841160018114610ed2577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b9284039250608487013560f881901c9060f01c60ff1681810360006001848414610fac5760ff83901d8084180380600c8114610f5857600b8114610f6557600a8114610f725760098114610f7f5760088114610f8b5760078114610f975760068114610fa25760005b82811015610f5257600a9390930292600101610f3b565b50610fa9565b64e8d4a510009250610fa9565b64174876e8009250610fa9565b6402540be4009250610fa9565b633b9aca009250610fa9565b6305f5e1009250610fa9565b629896809250610fa9565b620f424092505b50505b84841060018114610fd45797810297633b9aca00607c8e013560e01c8b028302049250610fee565b81633b9aca0002607c8e013560e01c8b0204925081890498505b505080871160018114611025577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b908703905060405196507fad5425c600000000000000000000000000000000000000000000000000000000875260148b013560601c600488015260868b01356024880152886044880152603c8b013560648801528760848801528060a488015250505050608087013560e01c60c4840152600060e48401524261010484015260a687013560e01c6101248401526000610144840152610180610164840152816101848401526000821160018114611100576000806101a486858c3560601c5af16110f3573d6000803e3d6000fd5b6101a48401604052611135565b8260ac89016101a4860137600080846101a40186858c3560601c5af161112a573d6000803e3d6000fd5b826101c40184016040525b50509490940160ac01949350505050565b60288101906000908035606090811c9160140135901c61116782828661127d565b949350505050565b6000813560601c6014830135603484013560801c60448501356064860195508115600181036111c957479250826111c9576111c97f669567ea00000000000000000000000000000000000000000000000000000000610a5d565b504681036111fa576111fa7fac6b05f500000000000000000000000000000000000000000000000000000000610a5d565b82611228576112287f1e4ec46b00000000000000000000000000000000000000000000000000000000610a5d565b6040517fc9630cb000000000000000000000000000000000000000000000000000000000815281600482015283602482015260008060448386895af1611272573d6000803e3d6000fd5b509495945050505050565b6000604051905081358060f01c8160101b60f01c8260201b60f01c8360301b60f01c8460401b60801c9450601887013560801c478111156112e2577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b60288801358060581c60ff168160601c91508760008114611308578860808b0152611345565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008f5afa5060005160808b01525b5086895260208901869052604089018590526060890184905260a089019290925260c0880181905260e08089018390527f2147796000000000000000000000000000000000000000000000000000000000610100808b01919091526101048a0182815260808b01516101248c0152601f9889017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09081169283016101448d01819052988a0181169092016101208101610164808e01829052988b018416808301610140016101848f018190526101a48f01979097526101c48e0197909752603d9d909d019c939a509798929793969290950116909201010190611461565b60008382018351808252808760208401379590950195945050505050565b61146d88878984611443565b975061147e888660208a0184611443565b975061148f888560408a0184611443565b97506114a0888460608a0184611443565b9750508061010087010160405260008082610100890160a08a01518d5af16114cc573d6000803e3d6000fd5b5094979650505050505050565b600080602083850312156114ec57600080fd5b823567ffffffffffffffff81111561150357600080fd5b8301601f8101851361151457600080fd5b803567ffffffffffffffff81111561152b57600080fd5b85602082840101111561153d57600080fd5b6020919091019590945092505050565b808201808211156103f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea264697066735822122027294167b7006c7aef9b0238bcddf1a1d540bf2131f293e4e53fcf24a87fb9f364736f6c634300081c0033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
0xfCa1150eA45ba50323C27a7d5E823d92D2e59A05
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.