Source Code
Latest 6 from a total of 6 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Instantiate | 4385039 | 604 days ago | IN | 0 ETH | 0.00000035 | ||||
| Instantiate | 4348798 | 605 days ago | IN | 0 ETH | 0.00000033 | ||||
| Instantiate | 1417426 | 673 days ago | IN | 0 ETH | 0.00010756 | ||||
| Instantiate | 1236113 | 677 days ago | IN | 0 ETH | 0.00003056 | ||||
| Instantiate | 446864 | 695 days ago | IN | 0 ETH | 0.00033778 | ||||
| Instantiate | 407004 | 696 days ago | IN | 0 ETH | 0.00030845 |
Latest 25 internal transactions (View All)
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
RouterProxyFactory
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)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import {RouterProxy, AbstractRouter} from "./RouterProxy.sol";
/// @title Mangrove Router Proxy Factory
/// @notice Factory contract for the deployment of RouterProxy instances using CREATE2 for deterministic addresses.
/// @dev Utilizes Ethereum's CREATE2 opcode for deploying contracts with predictable addresses.
contract RouterProxyFactory {
/// @notice Emitted when a new proxy is deployed through this factory.
/// @param proxy the deployed proxy contract
/// @param owner The address which will be the admin and owner of the newly deployed proxy.
/// @param implementation The address of the router implementation used by the proxy.
event ProxyDeployed(RouterProxy proxy, address indexed owner, AbstractRouter indexed implementation);
/// @notice Computes the deterministic address of a proxy deployed for a specific owner using CREATE2.
/// @param owner The prospective admin and owner of the new proxy contract.
/// @param routerImplementation router contract which implements routing functions
/// @return The address where the proxy will be deployed.
/// @dev The computed address is determined by the owner's address and the factory's address
function computeProxyAddress(address owner, AbstractRouter routerImplementation)
public
view
returns (address payable)
{
bytes memory creationCode = type(RouterProxy).creationCode;
bytes memory args = abi.encode(routerImplementation);
bytes32 initcodeHash = keccak256(abi.encodePacked(creationCode, args));
bytes32 salt = keccak256(abi.encode(owner));
return _extractAddress(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, initcodeHash)));
}
/// @notice Converts a padded bytes32 value to a payable address.
/// @param zeroPaddedAddress The bytes32 value representing an address with padding.
/// @return res The corresponding payable address.
function _extractAddress(bytes32 zeroPaddedAddress) private pure returns (address payable res) {
assembly {
res := zeroPaddedAddress
}
}
/// @notice Deploys a new RouterProxy for a given owner.
/// @param owner The address to be set as initial admin and immutable owner of the proxy.
/// @param routerImplementation router contract which implements routing functions
/// @return proxy The address of the newly deployed RouterProxy.
/// @dev Emits a ProxyDeployed event upon successful deployment.
/// Note that the deployment can be initiated by any caller, on behalf of `owner`.
function deployProxy(address owner, AbstractRouter routerImplementation) public returns (RouterProxy proxy) {
proxy = new RouterProxy{salt: keccak256(abi.encode(owner))}(routerImplementation);
// TODO: The access controlled admin must maybe be immutable (or this is a vector attack)
// We will always link one user with a router address anyway
_afterDeployProxy(proxy, owner);
emit ProxyDeployed(proxy, owner, routerImplementation);
}
/// @notice Hook to be called after a proxy is deployed.
/// @param proxy the deployed proxy contract
/// @param owner The address which will be the admin and owner of the newly deployed proxy.
function _afterDeployProxy(RouterProxy proxy, address owner) internal virtual {
AbstractRouter(address(proxy)).setAdmin(owner);
}
/// @notice Deploys a RouterProxy for a given owner if one has not already been deployed.
/// @param owner The address to be set as initial admin and immutable owner of the proxy.
/// @param routerImplementation router contract which implements routing functions
/// @return proxy The address of the RouterProxy.
/// @return created A boolean indicating if the proxy was created during this call.
/// @dev If the proxy already exists at the computed address, the function will not redeploy it.
/// The `created` return value indicates whether the proxy was created as a result of this call.
function instantiate(address owner, AbstractRouter routerImplementation)
public
returns (RouterProxy proxy, bool created)
{
proxy = RouterProxy(computeProxyAddress(owner, routerImplementation));
if (address(proxy).code.length == 0) {
require(deployProxy(owner, routerImplementation) == proxy, "Deployed via create2 failed");
created = true;
}
}
}// 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: BSD-2-Clause
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);
}{
"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/",
"@openzeppelin/contracts/=lib/openzeppelin/contracts/",
"@orbit-protocol/contracts/=lib/orbit-protocol/contracts/",
"erc4626-tests/=lib/openzeppelin/lib/erc4626-tests/",
"forge-std/=lib/openzeppelin/lib/forge-std/src/",
"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
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract RouterProxy","name":"proxy","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"contract AbstractRouter","name":"implementation","type":"address"}],"name":"ProxyDeployed","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract AbstractRouter","name":"routerImplementation","type":"address"}],"name":"computeProxyAddress","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract AbstractRouter","name":"routerImplementation","type":"address"}],"name":"deployProxy","outputs":[{"internalType":"contract RouterProxy","name":"proxy","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"contract AbstractRouter","name":"routerImplementation","type":"address"}],"name":"instantiate","outputs":[{"internalType":"contract RouterProxy","name":"proxy","type":"address"},{"internalType":"bool","name":"created","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50610613806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630a6eafdd14610046578063ce1821d714610076578063ea2e085714610089575b600080fd5b6100596100543660046103aa565b6100bb565b6040516001600160a01b0390911681526020015b60405180910390f35b6100596100843660046103aa565b61017d565b61009c6100973660046103aa565b61028c565b604080516001600160a01b03909316835290151560208301520161006d565b604080516001600160a01b03841660208201526000910160405160208183030381529060405280519060200120826040516100f590610385565b6001600160a01b0390911681526020018190604051809103906000f5905080158015610125573d6000803e3d6000fd5b5090506101328184610326565b6040516001600160a01b03828116825280841691908516907f9e0862c4ebff2150fbbfd3f8547483f55bdec0c34fd977d3fccaa55d6c4ce7849060200160405180910390a392915050565b6000806040518060200161019090610385565b601f1982820381018352601f9091011660408181526001600160a01b0386166020830152919250600091016040516020818303038152906040529050600082826040516020016101e1929190610413565b60408051601f1981840301815282825280516020918201206001600160a01b038a169184019190915292506000910160408051808303601f190181529082905280516020918201206001600160f81b0319918301919091526bffffffffffffffffffffffff193060601b16602183015260358201819052605582018490529150610281906075016040516020818303038152906040528051906020012090565b979650505050505050565b600080610299848461017d565b9150816001600160a01b03163b60000361031f57816001600160a01b03166102c185856100bb565b6001600160a01b03161461031b5760405162461bcd60e51b815260206004820152601b60248201527f4465706c6f796564207669612063726561746532206661696c65640000000000604482015260640160405180910390fd5b5060015b9250929050565b604051633825b60160e11b81526001600160a01b03828116600483015283169063704b6c0290602401600060405180830381600087803b15801561036957600080fd5b505af115801561037d573d6000803e3d6000fd5b505050505050565b6101ad8061043183390190565b6001600160a01b03811681146103a757600080fd5b50565b600080604083850312156103bd57600080fd5b82356103c881610392565b915060208301356103d881610392565b809150509250929050565b6000815160005b8181101561040457602081850181015186830152016103ea565b50600093019283525090919050565b600061042861042283866103e3565b846103e3565b94935050505056fe60a060405234801561001057600080fd5b506040516101ad3803806101ad83398101604081905261002f9161007b565b6001600160a01b0381166080523360008190556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a1506100ab565b60006020828403121561008d57600080fd5b81516001600160a01b03811681146100a457600080fd5b9392505050565b60805160e46100c960003960008181602a01526070015260e46000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633a4741bd14606c575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156067573d6000f35b3d6000fd5b60927f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f3fea2646970667358221220af5fe4a9984758b02eadf4d17d8ecce26af9b6df17f19bbd560accb23b6fd61564736f6c63430008140033a2646970667358221220bf14b3bf48a8d4c95fa009b573c6156fc1511e3aafdf635cd0d4c94d8950bfbb64736f6c63430008140033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100415760003560e01c80630a6eafdd14610046578063ce1821d714610076578063ea2e085714610089575b600080fd5b6100596100543660046103aa565b6100bb565b6040516001600160a01b0390911681526020015b60405180910390f35b6100596100843660046103aa565b61017d565b61009c6100973660046103aa565b61028c565b604080516001600160a01b03909316835290151560208301520161006d565b604080516001600160a01b03841660208201526000910160405160208183030381529060405280519060200120826040516100f590610385565b6001600160a01b0390911681526020018190604051809103906000f5905080158015610125573d6000803e3d6000fd5b5090506101328184610326565b6040516001600160a01b03828116825280841691908516907f9e0862c4ebff2150fbbfd3f8547483f55bdec0c34fd977d3fccaa55d6c4ce7849060200160405180910390a392915050565b6000806040518060200161019090610385565b601f1982820381018352601f9091011660408181526001600160a01b0386166020830152919250600091016040516020818303038152906040529050600082826040516020016101e1929190610413565b60408051601f1981840301815282825280516020918201206001600160a01b038a169184019190915292506000910160408051808303601f190181529082905280516020918201206001600160f81b0319918301919091526bffffffffffffffffffffffff193060601b16602183015260358201819052605582018490529150610281906075016040516020818303038152906040528051906020012090565b979650505050505050565b600080610299848461017d565b9150816001600160a01b03163b60000361031f57816001600160a01b03166102c185856100bb565b6001600160a01b03161461031b5760405162461bcd60e51b815260206004820152601b60248201527f4465706c6f796564207669612063726561746532206661696c65640000000000604482015260640160405180910390fd5b5060015b9250929050565b604051633825b60160e11b81526001600160a01b03828116600483015283169063704b6c0290602401600060405180830381600087803b15801561036957600080fd5b505af115801561037d573d6000803e3d6000fd5b505050505050565b6101ad8061043183390190565b6001600160a01b03811681146103a757600080fd5b50565b600080604083850312156103bd57600080fd5b82356103c881610392565b915060208301356103d881610392565b809150509250929050565b6000815160005b8181101561040457602081850181015186830152016103ea565b50600093019283525090919050565b600061042861042283866103e3565b846103e3565b94935050505056fe60a060405234801561001057600080fd5b506040516101ad3803806101ad83398101604081905261002f9161007b565b6001600160a01b0381166080523360008190556040519081527f5a272403b402d892977df56625f4164ccaf70ca3863991c43ecfe76a6905b0a19060200160405180910390a1506100ab565b60006020828403121561008d57600080fd5b81516001600160a01b03811681146100a457600080fd5b9392505050565b60805160e46100c960003960008181602a01526070015260e46000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80633a4741bd14606c575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156067573d6000f35b3d6000fd5b60927f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f3fea2646970667358221220af5fe4a9984758b02eadf4d17d8ecce26af9b6df17f19bbd560accb23b6fd61564736f6c63430008140033a2646970667358221220bf14b3bf48a8d4c95fa009b573c6156fc1511e3aafdf635cd0d4c94d8950bfbb64736f6c63430008140033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.