ETH Price: $2,736.54 (-7.19%)

Contract

0xd78BCC3A131c56cD8a1295F9E3071588CA50EAA5
 

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Bind15094332024-03-30 19:58:01670 days ago1711828681IN
0xd78BCC3A...8CA50EAA5
0 ETH0.000031870.00084803

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
2339872024-03-01 7:23:09700 days ago1709277789  Contract Creation0 ETH

Cross-Chain Transactions
Loading...
Loading

Similar Match Source Code
This contract matches the deployed Bytecode of the Source Code for Contract 0x25d1d41b...ec1d70E96
The constructor portion of the code might be different and could alter the actual behaviour of the contract

Contract Name:
RouterProxy

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 5 : RouterProxy.sol
// SPDX-License-Identifier:	MIT
pragma solidity ^0.8.18;

import {AbstractRouter} from "./abstract/AbstractRouter.sol";

/// @title Minimalistic Mangrove Router Proxy
/// @notice A proxy contract that delegates calls to an instance of an AbstractRouter contract.
///         It does not allow updates of implementation contract.
/// @dev it assumes the IMPLEMENTATION uses first storage slot to hold the admin address (this is guaranteed as long as `AbstractRouter` is `AccessControlled`)
contract RouterProxy {
  /// @notice The address of the deployed SmartRouter contract acting as the delegate implementation.
  /// @dev The SmartRouter instance must be AccessControlled to ensure the storage layout is matched.
  AbstractRouter public immutable IMPLEMENTATION;

  /// @notice Emitted when the admin of the proxy is set.
  /// * This is a copy of the AccessControlled event to set without calling the implementation.
  /// @param admin The address of the admin of the proxy.
  event SetAdmin(address admin);

  /// @notice Deploys a Proxy for the SmartRouter that handles incoming transactions and delegates them to the implementation.
  /// @param implementation The address of the deployed SmartRouter contract to which calls will be delegated.
  /// @dev Initializes the contract with an AccessControlled base to set up access control.
  constructor(AbstractRouter implementation) {
    IMPLEMENTATION = implementation;
    // store the msg sender at address 0 (_admin storage slot on access controlled)
    assembly {
      sstore(0, caller())
    }
    emit SetAdmin(msg.sender);
  }

  /// @notice Fallback function to delegate calls to the implementation contract.
  fallback() external {
    AbstractRouter implementation = IMPLEMENTATION;
    assembly {
      // Copy msg.data. We take full control of memory in this inline assembly
      // block because it will not return to Solidity code. We overwrite the
      // Solidity scratch pad at memory position 0.
      calldatacopy(0, 0, calldatasize())

      // Call the implementation.
      // out and outsize are 0 because we don't know the size yet.
      let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

      // Copy the returned data.
      returndatacopy(0, 0, returndatasize())

      switch result
      // delegatecall returns 0 on error.
      case 0 { revert(0, returndatasize()) }
      default { return(0, returndatasize()) }
    }
  }
}

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

import {AccessControlled} from "@mgv-strats/src/strategies/utils/AccessControlled.sol";
import {RoutingOrderLib as RL} from "./RoutingOrderLib.sol";

/// @title AbstractRouter
/// @notice Partial implementation and requirements for liquidity routers.

abstract contract AbstractRouter is AccessControlled(msg.sender) {
  ///@notice This modifier verifies that `msg.sender` an allowed caller of this router.
  modifier onlyBound() {
    require(isBound(msg.sender), "AccessControlled/Invalid");
    _;
  }

  ///@notice This modifier verifies that `msg.sender` is the admin or an allowed caller of this router.
  modifier boundOrAdmin() {
    require(msg.sender == admin() || isBound(msg.sender), "AccessControlled/Invalid");
    _;
  }

  ///@notice logging bound maker contract
  ///@param maker the maker address. This is indexed, so that RPC calls can filter on it.
  ///@notice by emitting this data, an indexer will be able to keep track of what maker contracts are allowed to call this router.
  event MakerBind(address indexed maker);

  ///@notice logging unbound maker contract
  ///@param maker the maker address. This is indexed, so that RPC calls can filter on it.
  ///@notice by emitting this data, an indexer will be able to keep track of what maker contracts are allowed to call this router.
  event MakerUnbind(address indexed maker);

  ///@notice getter for the `makers: addr => bool` mapping
  ///@param mkr the address of a maker contract
  ///@return true if `mkr` is authorized to call this router.
  function isBound(address mkr) public view virtual returns (bool) {
    return RL.boundMakerContracts()[mkr];
  }

  ///@notice pulls liquidity from the reserve and sends it to the calling maker contract.
  ///@param routingOrder the arguments of the pull order
  ///@param amount of token that needs to be routed
  ///@param strict if false the router may pull at more than `amount` to msg.sender. Otherwise it pulls at least `amount`.
  ///@return pulled the amount of `routingOrder.token` that has been sent to `msg.sender`
  function pull(RL.RoutingOrder calldata routingOrder, uint amount, bool strict)
    external
    onlyBound
    returns (uint pulled)
  {
    if (strict && amount == 0) {
      return 0;
    }
    pulled = __pull__(routingOrder, amount, strict);
  }

  ///@notice router dependent hook to customize pull orders.
  ///@param routingOrder the arguments of the pull order
  ///@param amount of token that needs to be routed
  ///@param strict if false the router may pull at more than `amount` to msg.sender. Otherwise it pulls at least `amount`.
  ///@return pulled the amount of `routingOrder.token` that has been sent to `msg.sender`
  function __pull__(RL.RoutingOrder memory routingOrder, uint amount, bool strict) internal virtual returns (uint);

  ///@notice pushes liquidity from msg.sender to the reserve
  ///@param routingOrder the arguments of the push order
  ///@param amount of token that needs to be routed
  ///@return pushed the amount of `routingOrder.token` that has been taken from `msg.sender`
  function push(RL.RoutingOrder calldata routingOrder, uint amount) external onlyBound returns (uint pushed) {
    if (amount == 0) {
      return 0;
    }
    pushed = __push__(routingOrder, amount);
  }

  ///@notice router dependent hook to customize pull orders.
  ///@param routingOrder the arguments of the pull order
  ///@param amount of token that needs to be routed
  ///@return pushed the amount of `routingOrder.token` that has been sent to `msg.sender`
  function __push__(RL.RoutingOrder memory routingOrder, uint amount) internal virtual returns (uint pushed);

  ///@notice iterative `push` of the whole maker contract's balance
  ///@dev minimizes external calls in case several assets needs to be pushed via the router.
  ///@param routingOrders to be executed
  function flush(RL.RoutingOrder[] memory routingOrders) external onlyBound {
    for (uint i = 0; i < routingOrders.length; ++i) {
      uint amount = routingOrders[i].token.balanceOf(msg.sender);
      if (amount > 0) {
        require(__push__(routingOrders[i], amount) == amount, "router/flushFailed");
      }
    }
  }

  ///@notice adds a maker contract address to the allowed makers of this router
  ///@dev this function is callable by router's admin to bootstrap, but later on an allowed maker contract can add another address
  ///@param makerContract the maker contract address
  function bind(address makerContract) public onlyAdmin {
    RL.boundMakerContracts()[makerContract] = true;
    emit MakerBind(makerContract);
  }

  ///@notice removes a maker contract address from the allowed makers of this router
  ///@param makerContract the maker contract address
  function _unbind(address makerContract) internal {
    RL.boundMakerContracts()[makerContract] = false;
    emit MakerUnbind(makerContract);
  }

  ///@notice removes `msg.sender` from the allowed makers of this router
  function unbind() external onlyBound {
    _unbind(msg.sender);
  }

  ///@notice removes a makerContract from the allowed makers of this router
  ///@param makerContract the maker contract address
  function unbind(address makerContract) external onlyAdmin {
    _unbind(makerContract);
  }

  /**
   * @notice Returns the token balance available for a specific routing order
   * @param routingOrder The routing order to check the balance for
   * @return balance The balance of the token in the routing order
   */
  function tokenBalanceOf(RL.RoutingOrder calldata routingOrder) public view virtual returns (uint balance);
}

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

/// @title This contract is used to restrict access to privileged functions of inheriting contracts through modifiers.
/// @notice The contract stores an admin address which is checked against `msg.sender` in the `onlyAdmin` modifier.
/// @notice Additionally, a specific `msg.sender` can be verified with the `onlyCaller` modifier.
contract AccessControlled {
  /**
   * @notice logs new `admin` of `this`
   * @param admin The new admin.
   * @notice By emitting this data, an indexer will be able to keep track of what address is the admin of this contract.
   */
  event SetAdmin(address admin);
  /**
   * @notice The admin address.
   */

  address internal _admin;

  /**
   * @notice `AccessControlled`'s constructor
   * @param admin_ The address of the admin that can access privileged functions and also allowed to change the admin. Cannot be `address(0)`.
   */
  constructor(address admin_) {
    _setAdmin(admin_);
  }

  /**
   * @notice This modifier verifies that `msg.sender` is the admin.
   */
  modifier onlyAdmin() {
    require(msg.sender == _admin, "AccessControlled/Invalid");
    _;
  }

  /**
   * @notice This modifier verifies that `msg.sender` is the caller.
   * @param caller The address of the caller that can access the modified function.
   */
  modifier onlyCaller(address caller) {
    require(msg.sender == caller, "AccessControlled/Invalid");
    _;
  }

  /**
   * @notice This modifier verifies that `msg.sender` is either caller or the admin
   * @param caller The address of a caller that can access the modified function.
   */
  modifier adminOrCaller(address caller) {
    // test _admin second to save a storage read when possible
    require(msg.sender == caller || msg.sender == _admin, "AccessControlled/Invalid");
    _;
  }

  /**
   * @notice Retrieves the current admin.
   * @return current admin.
   */
  function admin() public view returns (address current) {
    return _admin;
  }

  /**
   * @notice This function is called to add logic on admin change for inheriting contracts.
   * @param admin_ The new admin. Cannot be `address(0)`.
   */
  function _onAdminChange(address admin_) internal virtual {}

  /**
   * @notice This sets and log a new admin
   * @param admin_ The new admin. Cannot be `address(0)`.
   */
  function _setAdmin(address admin_) internal {
    require(admin_ != address(0), "AccessControlled/0xAdmin");
    _admin = admin_;
    emit SetAdmin(admin_);
    _onAdminChange(admin_);
  }

  /**
   * @notice This sets the admin. Only the current admin can change the admin.
   * @param admin_ The new admin. Cannot be `address(0)`.
   */
  function setAdmin(address admin_) external onlyAdmin {
    _setAdmin(admin_);
  }
}

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

import {IERC20} from "@mgv/lib/IERC20.sol";

/// @title Library to obtain Routing orders of various kind

library RoutingOrderLib {
  ///@notice pointer to first storage slot used for randomized access
  bytes32 private constant OFFSET = keccak256("MangroveStrats.RoutingOrderLib.Layout");

  ///@notice Argument to pull/push
  ///@param token the asset to be routed
  ///@param olKeyHash the id of the market that triggered the calling offer logic. Is bytes32(0) when routing is done outside offer logic.
  ///@param offerId the id of the offer that triggered the calling offer logic. Is uint(0) when routing is done outsider offer logic.
  ///@param fundOwner the owner of the routed funds. If calling router is a proxy, it address is determined by `fundOwner`.
  struct RoutingOrder {
    IERC20 token;
    bytes32 olKeyHash;
    uint offerId;
    address fundOwner;
  }

  ///@notice helper to create a RoutingOrder struct without zero'ed fields for market coordinates.
  ///@param token the asset to be routed
  ///@param fundOwner the owner of the routed funds
  ///@return ro the routing order struct
  function createOrder(IERC20 token, address fundOwner) internal pure returns (RoutingOrder memory ro) {
    ro.token = token;
    ro.fundOwner = fundOwner;
  }

  ///@notice the bound maker contracts which are allowed to call this router.
  struct Layout {
    mapping(address => bool) boundMakerContracts;
  }

  ///@notice allowed pullers/pushers for this router
  ///@return bound contracts to this router, in the form of a storage mapping
  function boundMakerContracts() internal view returns (mapping(address => bool) storage) {
    bytes32 offset = OFFSET;
    Layout storage st;
    assembly ("memory-safe") {
      st.slot := offset
    }
    return st.boundMakerContracts;
  }
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2;

interface IERC20 {
  function totalSupply() external view returns (uint);

  function balanceOf(address account) external view returns (uint);

  function transfer(address recipient, uint amount) external returns (bool);

  function allowance(address owner, address spender) external view returns (uint);

  function approve(address spender, uint amount) external returns (bool);

  function transferFrom(address sender, address recipient, uint amount) external returns (bool);

  function symbol() external view returns (string memory);

  event Transfer(address indexed from, address indexed to, uint value);
  event Approval(address indexed owner, address indexed spender, uint value);

  function decimals() external view returns (uint8);

  function name() external view returns (string memory);
}

Settings
{
  "remappings": [
    "@mgv/src/=node_modules/@mangrovedao/mangrove-core/src/",
    "@mgv/lib/=node_modules/@mangrovedao/mangrove-core/lib/",
    "@mgv/test/=node_modules/@mangrovedao/mangrove-core/test/",
    "@mgv/script/=node_modules/@mangrovedao/mangrove-core/script/",
    "@mgv/forge-std/=node_modules/@mangrovedao/mangrove-core/lib/forge-std/src/",
    "ds-test/=node_modules/@mangrovedao/mangrove-core/lib/forge-std/lib/ds-test/src/",
    "@mgv-strats/src/=src/",
    "@mgv-strats/lib/=lib/",
    "@mgv-strats/test/=test/",
    "@mgv-strats/script/=script/",
    "@uniswap/v3-core/=node_modules/@uniswap/v3-core/",
    "@uniswap/v2-core/=node_modules/@uniswap/v2-core/",
    "@uniswap/v3-periphery/=node_modules/@uniswap/v3-periphery/",
    "@uniswap/lib/=node_modules/@uniswap/lib/",
    "base64-sol/=node_modules/base64-sol/",
    "@openzeppelin/contracts/=lib/openzeppelin/contracts/",
    "@orbit-protocol/contracts/=lib/orbit-protocol/contracts/",
    "openzeppelin/=lib/openzeppelin/",
    "orbit-protocol/=lib/orbit-protocol/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract AbstractRouter","name":"implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"SetAdmin","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"IMPLEMENTATION","outputs":[{"internalType":"contract AbstractRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

0x60a060405234801561001057600080fd5b506040516101ad3803806101ad83398101604081905261002f9161007b565b6001600160a01b0381166080523360008190556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a1506100ab565b60006020828403121561008d57600080fd5b81516001600160a01b03811681146100a457600080fd5b9392505050565b60805160e46100c960003960008181602a01526070015260e46000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633a4741bd14606c575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156067573d6000f35b3d6000fd5b60927f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f3fea2646970667358221220af5fe4a9984758b02eadf4d17d8ecce26af9b6df17f19bbd560accb23b6fd61564736f6c63430008140033000000000000000000000000270c0bc25795dcef15bb6d374670ebe9ecf76998

Deployed Bytecode

0x6080604052348015600f57600080fd5b506004361060285760003560e01c80633a4741bd14606c575b7f000000000000000000000000270c0bc25795dcef15bb6d374670ebe9ecf769983660008037600080366000845af43d6000803e8080156067573d6000f35b3d6000fd5b60927f000000000000000000000000270c0bc25795dcef15bb6d374670ebe9ecf7699881565b6040516001600160a01b03909116815260200160405180910390f3fea2646970667358221220af5fe4a9984758b02eadf4d17d8ecce26af9b6df17f19bbd560accb23b6fd61564736f6c63430008140033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ 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.