Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
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
Contract Source Code (Solidity Standard Json-Input format)
// 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; }
// 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(); } } }
// 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) } } }
// 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; }
// 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; }
{ "optimizer": { "enabled": true, "runs": 1000000 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
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"}]
Contract Creation Code
6080604052348015600f57600080fd5b506115bd8061001f6000396000f3fe6080604052600436106100225760003560e01c80636a0c90ff1461002e57600080fd5b3661002957005b600080fd5b61004161003c3660046114d9565b610043565b005b604460243581013361005681848461005d565b5050505050565b60018201913560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810161009d576100968361012c565b92506100da565b602181036100af57610096838561025d565b604081036100c15761009683856103f8565b609081036100d2576100968361046f565b6100da6104d1565b8183106100e757506100ed565b5061005d565b80821115610127576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000813560601c6e22d473030f116ddee9f6b43ac78ba38103610173577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026830192601481013560801c906024013560f01c6f80000000000000000000000000000000821680156101a9574792506101be565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd0000000000000000000000000000000000000000000000000000000086357fffffffff000000000000000000000000000000000000000000000000000000001603610236577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b81868237600080838386885af1610251573d6000803e3d6000fd5b50939093019392505050565b600080600080853560601c6e22d473030f116ddee9f6b43ac78ba381036102a8577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026870196601481013560801c906024013560f01c6f80000000000000000000000000000000821680156102de574792506102f3565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd000000000000000000000000000000000000000000000000000000008a357fffffffff00000000000000000000000000000000000000000000000000000000160361036b577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b818a8237600080838386885af1965050808901985050505085358060f81c925083158315161561039f573d6000803e3d6000fd5b8060e81c61ffff16915050600386019550826103e65780156103d75760006103c7828861154d565b90506103d486888361005d565b95505b816001036103e157005b6103eb565b948501945b8593505050505b92915050565b60018201916000903560f81c8061041b5761041384846104fb565b9150506103f2565b6001810361042c57610413846105c5565b6003810361043d576104138461077a565b6004810361044f5761041384846108db565b600581036104605761041384610996565b6104686104d1565b5092915050565b60018101906000903560f81c806104905761048983610a56565b9392505050565b600a81036104a15761048983610da8565b601481036104b25761048983611146565b601e81036104c3576104898361116f565b6104cb6104d1565b50919050565b7f398d4d320000000000000000000000000000000000000000000000000000000060005260046000fd5b6000823560601c601484013560601c602885013560801c80610550577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081528560048201528260248201528160448201526020816064836000885af193503d92506001815114601f84111683151784166105b557826000803e826000fd5b5050506038939093019392505050565b6000813560601c601483013560601c60198401358060801c60ff16816fffffffffffffffffffffffffffffffff16915060008415600081146106895782801561061057849250610645565b47925084831015610645577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5081156106845760008060008085895af1610684577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b610769565b82801561069857849250610703565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa50600051925084831015610703577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b508115610769576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815285600482015282602482015260208160448360008b5af13d6001835114601f821116811517821661076557806000803e806000fd5b5050505b505050603994909401949350505050565b60008135606090811c906014840135901c60198401356effffffffffffffffffffffffffffff81169060801c60ff16848180156107b957839150610824565b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000895afa50600051915083821015610824577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5080156108cb577f2e1a7d4d00000000000000000000000000000000000000000000000000000000600052806004526000806024600080895af161088c577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b3084146108cb5760008060008084885af16108cb577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050506039939093019392505050565b6000823560601c601484013560601c602885013560801c80610930577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f36c7851600000000000000000000000000000000000000000000000000000000815285600482015282602482015281604482015283606482015260008060848360006e22d473030f116ddee9f6b43ac78ba35af16105b5573d6000803e3d6000fd5b6000813560601c601483013560601c816000527f1aae13105d9b6581c36534caba5708726e5ea1e03175e823c989a5756966d1f360205260406000206020528060005260406000208054610a48576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528260048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044836000885af15050600181555b505050602891909101919050565b6000610aa2565b8060005260046000fd5b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000845afa505060005190565b8135606090811c90608584013560f090811c91608786013590911c90850135608090811c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff811691600091607489013590911c9082906f800000000000000000000000000000001647851560018114610b6157828015610b26578588019650610b2a565b8596505b5081861115610b5c57610b5c7f1101129400000000000000000000000000000000000000000000000000000000610a5d565b610bb6565b828015610b75578583039750829650610bb4565b610b7e8b610a67565b975085965082871115610bb457610bb47f1101129400000000000000000000000000000000000000000000000000000000610a5d565b505b505050633b9aca0060708a013560e01c633b9aca0003850204905060405196507fcbef2aa90000000000000000000000000000000000000000000000000000000087526080600488015281602488015260006044880152604c89013560601c6064880152602889013560e01c6084880152602c89013560a48801528360c48801528060e4880152505060e061010486015260009150821560018114610c60578015610c6a57610c9f565b6101209250610c9f565b6020840460208506600080821160018114610c8757839150610c8e565b6001840191505b506001810160200260e00195505050505b50816101248601526000841560018114610ceb576020860460208706600080821160018114610cd057839150610cd7565b6001840191505b506001810160200287019450505050610cf2565b6020840191505b50610144860181905261016486018481528415610d1657848660898b010160208301375b50918501608401848152918415610d3257846089890160208501375b60009250850160849081019088013560f81c1560018114610d655760208252600060208301528660408301039350610d72565b6000825286602083010393505b505081850160405260008083878460148c013560601c5af1610d98573d6000803e3d6000fd5b5050930190920160890192915050565b6000602882013560601c605c83013560801c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff8116906f800000000000000000000000000000001660aa85013560f01c84831560018114610e44578315610e3f5747851115610e3b577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b8491505b610e92565b838015610e5657479550859250610e90565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa5060005195505b505b50606c87013560801c925082841160018114610ed2577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b9284039250608487013560f881901c9060f01c60ff1681810360006001848414610fac5760ff83901d8084180380600c8114610f5857600b8114610f6557600a8114610f725760098114610f7f5760088114610f8b5760078114610f975760068114610fa25760005b82811015610f5257600a9390930292600101610f3b565b50610fa9565b64e8d4a510009250610fa9565b64174876e8009250610fa9565b6402540be4009250610fa9565b633b9aca009250610fa9565b6305f5e1009250610fa9565b629896809250610fa9565b620f424092505b50505b84841060018114610fd45797810297633b9aca00607c8e013560e01c8b028302049250610fee565b81633b9aca0002607c8e013560e01c8b0204925081890498505b505080871160018114611025577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b908703905060405196507fad5425c600000000000000000000000000000000000000000000000000000000875260148b013560601c600488015260868b01356024880152886044880152603c8b013560648801528760848801528060a488015250505050608087013560e01c60c4840152600060e48401524261010484015260a687013560e01c6101248401526000610144840152610180610164840152816101848401526000821160018114611100576000806101a486858c3560601c5af16110f3573d6000803e3d6000fd5b6101a48401604052611135565b8260ac89016101a4860137600080846101a40186858c3560601c5af161112a573d6000803e3d6000fd5b826101c40184016040525b50509490940160ac01949350505050565b60288101906000908035606090811c9160140135901c61116782828661127d565b949350505050565b6000813560601c6014830135603484013560801c60448501356064860195508115600181036111c957479250826111c9576111c97f669567ea00000000000000000000000000000000000000000000000000000000610a5d565b504681036111fa576111fa7fac6b05f500000000000000000000000000000000000000000000000000000000610a5d565b82611228576112287f1e4ec46b00000000000000000000000000000000000000000000000000000000610a5d565b6040517fc9630cb000000000000000000000000000000000000000000000000000000000815281600482015283602482015260008060448386895af1611272573d6000803e3d6000fd5b509495945050505050565b6000604051905081358060f01c8160101b60f01c8260201b60f01c8360301b60f01c8460401b60801c9450601887013560801c478111156112e2577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b60288801358060581c60ff168160601c91508760008114611308578860808b0152611345565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008f5afa5060005160808b01525b5086895260208901869052604089018590526060890184905260a089019290925260c0880181905260e08089018390527f2147796000000000000000000000000000000000000000000000000000000000610100808b01919091526101048a0182815260808b01516101248c0152601f9889017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09081169283016101448d01819052988a0181169092016101208101610164808e01829052988b018416808301610140016101848f018190526101a48f01979097526101c48e0197909752603d9d909d019c939a509798929793969290950116909201010190611461565b60008382018351808252808760208401379590950195945050505050565b61146d88878984611443565b975061147e888660208a0184611443565b975061148f888560408a0184611443565b97506114a0888460608a0184611443565b9750508061010087010160405260008082610100890160a08a01518d5af16114cc573d6000803e3d6000fd5b5094979650505050505050565b600080602083850312156114ec57600080fd5b823567ffffffffffffffff81111561150357600080fd5b8301601f8101851361151457600080fd5b803567ffffffffffffffff81111561152b57600080fd5b85602082840101111561153d57600080fd5b6020919091019590945092505050565b808201808211156103f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea264697066735822122027294167b7006c7aef9b0238bcddf1a1d540bf2131f293e4e53fcf24a87fb9f364736f6c634300081c0033
Deployed Bytecode
0x6080604052600436106100225760003560e01c80636a0c90ff1461002e57600080fd5b3661002957005b600080fd5b61004161003c3660046114d9565b610043565b005b604460243581013361005681848461005d565b5050505050565b60018201913560f81c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0810161009d576100968361012c565b92506100da565b602181036100af57610096838561025d565b604081036100c15761009683856103f8565b609081036100d2576100968361046f565b6100da6104d1565b8183106100e757506100ed565b5061005d565b80821115610127576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b6000813560601c6e22d473030f116ddee9f6b43ac78ba38103610173577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026830192601481013560801c906024013560f01c6f80000000000000000000000000000000821680156101a9574792506101be565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd0000000000000000000000000000000000000000000000000000000086357fffffffff000000000000000000000000000000000000000000000000000000001603610236577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b81868237600080838386885af1610251573d6000803e3d6000fd5b50939093019392505050565b600080600080853560601c6e22d473030f116ddee9f6b43ac78ba381036102a8577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b6026870196601481013560801c906024013560f01c6f80000000000000000000000000000000821680156102de574792506102f3565b6effffffffffffffffffffffffffffff831692505b506040517f23b872dd000000000000000000000000000000000000000000000000000000008a357fffffffff00000000000000000000000000000000000000000000000000000000160361036b577fee90c4680000000000000000000000000000000000000000000000000000000060005260046000fd5b818a8237600080838386885af1965050808901985050505085358060f81c925083158315161561039f573d6000803e3d6000fd5b8060e81c61ffff16915050600386019550826103e65780156103d75760006103c7828861154d565b90506103d486888361005d565b95505b816001036103e157005b6103eb565b948501945b8593505050505b92915050565b60018201916000903560f81c8061041b5761041384846104fb565b9150506103f2565b6001810361042c57610413846105c5565b6003810361043d576104138461077a565b6004810361044f5761041384846108db565b600581036104605761041384610996565b6104686104d1565b5092915050565b60018101906000903560f81c806104905761048983610a56565b9392505050565b600a81036104a15761048983610da8565b601481036104b25761048983611146565b601e81036104c3576104898361116f565b6104cb6104d1565b50919050565b7f398d4d320000000000000000000000000000000000000000000000000000000060005260046000fd5b6000823560601c601484013560601c602885013560801c80610550577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081528560048201528260248201528160448201526020816064836000885af193503d92506001815114601f84111683151784166105b557826000803e826000fd5b5050506038939093019392505050565b6000813560601c601483013560601c60198401358060801c60ff16816fffffffffffffffffffffffffffffffff16915060008415600081146106895782801561061057849250610645565b47925084831015610645577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5081156106845760008060008085895af1610684577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b610769565b82801561069857849250610703565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa50600051925084831015610703577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b508115610769576040517fa9059cbb00000000000000000000000000000000000000000000000000000000815285600482015282602482015260208160448360008b5af13d6001835114601f821116811517821661076557806000803e806000fd5b5050505b505050603994909401949350505050565b60008135606090811c906014840135901c60198401356effffffffffffffffffffffffffffff81169060801c60ff16848180156107b957839150610824565b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000895afa50600051915083821015610824577f7dd37f700000000000000000000000000000000000000000000000000000000060005260046000fd5b5080156108cb577f2e1a7d4d00000000000000000000000000000000000000000000000000000000600052806004526000806024600080895af161088c577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b3084146108cb5760008060008084885af16108cb577ff4b3b1bc0000000000000000000000000000000000000000000000000000000060005260046000fd5b5050506039939093019392505050565b6000823560601c601484013560601c602885013560801c80610930577f70a0823100000000000000000000000000000000000000000000000000000000600052846004526020600060246000865afa50506000515b6040517f36c7851600000000000000000000000000000000000000000000000000000000815285600482015282602482015281604482015283606482015260008060848360006e22d473030f116ddee9f6b43ac78ba35af16105b5573d6000803e3d6000fd5b6000813560601c601483013560601c816000527f1aae13105d9b6581c36534caba5708726e5ea1e03175e823c989a5756966d1f360205260406000206020528060005260406000208054610a48576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528260048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044836000885af15050600181555b505050602891909101919050565b6000610aa2565b8060005260046000fd5b7f70a0823100000000000000000000000000000000000000000000000000000000600052306004526020600060246000845afa505060005190565b8135606090811c90608584013560f090811c91608786013590911c90850135608090811c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff811691600091607489013590911c9082906f800000000000000000000000000000001647851560018114610b6157828015610b26578588019650610b2a565b8596505b5081861115610b5c57610b5c7f1101129400000000000000000000000000000000000000000000000000000000610a5d565b610bb6565b828015610b75578583039750829650610bb4565b610b7e8b610a67565b975085965082871115610bb457610bb47f1101129400000000000000000000000000000000000000000000000000000000610a5d565b505b505050633b9aca0060708a013560e01c633b9aca0003850204905060405196507fcbef2aa90000000000000000000000000000000000000000000000000000000087526080600488015281602488015260006044880152604c89013560601c6064880152602889013560e01c6084880152602c89013560a48801528360c48801528060e4880152505060e061010486015260009150821560018114610c60578015610c6a57610c9f565b6101209250610c9f565b6020840460208506600080821160018114610c8757839150610c8e565b6001840191505b506001810160200260e00195505050505b50816101248601526000841560018114610ceb576020860460208706600080821160018114610cd057839150610cd7565b6001840191505b506001810160200287019450505050610cf2565b6020840191505b50610144860181905261016486018481528415610d1657848660898b010160208301375b50918501608401848152918415610d3257846089890160208501375b60009250850160849081019088013560f81c1560018114610d655760208252600060208301528660408301039350610d72565b6000825286602083010393505b505081850160405260008083878460148c013560601c5af1610d98573d6000803e3d6000fd5b5050930190920160890192915050565b6000602882013560601c605c83013560801c7fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffff8116906f800000000000000000000000000000001660aa85013560f01c84831560018114610e44578315610e3f5747851115610e3b577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b8491505b610e92565b838015610e5657479550859250610e90565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008a5afa5060005195505b505b50606c87013560801c925082841160018114610ed2577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b9284039250608487013560f881901c9060f01c60ff1681810360006001848414610fac5760ff83901d8084180380600c8114610f5857600b8114610f6557600a8114610f725760098114610f7f5760088114610f8b5760078114610f975760068114610fa25760005b82811015610f5257600a9390930292600101610f3b565b50610fa9565b64e8d4a510009250610fa9565b64174876e8009250610fa9565b6402540be4009250610fa9565b633b9aca009250610fa9565b6305f5e1009250610fa9565b629896809250610fa9565b620f424092505b50505b84841060018114610fd45797810297633b9aca00607c8e013560e01c8b028302049250610fee565b81633b9aca0002607c8e013560e01c8b0204925081890498505b505080871160018114611025577f5945ea560000000000000000000000000000000000000000000000000000000060005260046000fd5b908703905060405196507fad5425c600000000000000000000000000000000000000000000000000000000875260148b013560601c600488015260868b01356024880152886044880152603c8b013560648801528760848801528060a488015250505050608087013560e01c60c4840152600060e48401524261010484015260a687013560e01c6101248401526000610144840152610180610164840152816101848401526000821160018114611100576000806101a486858c3560601c5af16110f3573d6000803e3d6000fd5b6101a48401604052611135565b8260ac89016101a4860137600080846101a40186858c3560601c5af161112a573d6000803e3d6000fd5b826101c40184016040525b50509490940160ac01949350505050565b60288101906000908035606090811c9160140135901c61116782828661127d565b949350505050565b6000813560601c6014830135603484013560801c60448501356064860195508115600181036111c957479250826111c9576111c97f669567ea00000000000000000000000000000000000000000000000000000000610a5d565b504681036111fa576111fa7fac6b05f500000000000000000000000000000000000000000000000000000000610a5d565b82611228576112287f1e4ec46b00000000000000000000000000000000000000000000000000000000610a5d565b6040517fc9630cb000000000000000000000000000000000000000000000000000000000815281600482015283602482015260008060448386895af1611272573d6000803e3d6000fd5b509495945050505050565b6000604051905081358060f01c8160101b60f01c8260201b60f01c8360301b60f01c8460401b60801c9450601887013560801c478111156112e2577f110112940000000000000000000000000000000000000000000000000000000060005260046000fd5b60288801358060581c60ff168160601c91508760008114611308578860808b0152611345565b7f70a08231000000000000000000000000000000000000000000000000000000006000523060045260206000602460008f5afa5060005160808b01525b5086895260208901869052604089018590526060890184905260a089019290925260c0880181905260e08089018390527f2147796000000000000000000000000000000000000000000000000000000000610100808b01919091526101048a0182815260808b01516101248c0152601f9889017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09081169283016101448d01819052988a0181169092016101208101610164808e01829052988b018416808301610140016101848f018190526101a48f01979097526101c48e0197909752603d9d909d019c939a509798929793969290950116909201010190611461565b60008382018351808252808760208401379590950195945050505050565b61146d88878984611443565b975061147e888660208a0184611443565b975061148f888560408a0184611443565b97506114a0888460608a0184611443565b9750508061010087010160405260008082610100890160a08a01518d5af16114cc573d6000803e3d6000fd5b5094979650505050505050565b600080602083850312156114ec57600080fd5b823567ffffffffffffffff81111561150357600080fd5b8301601f8101851361151457600080fd5b803567ffffffffffffffff81111561152b57600080fd5b85602082840101111561153d57600080fd5b6020919091019590945092505050565b808201808211156103f2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea264697066735822122027294167b7006c7aef9b0238bcddf1a1d540bf2131f293e4e53fcf24a87fb9f364736f6c634300081c0033
Loading...
Loading
Loading...
Loading

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.