Address Contract Verified
Address
0x7CAB80B6FaCD52A0F3e044D8bfC43d0ad6D258F4
Balance
0 ETH
Nonce
23
Code Size
4279 bytes
Creator
0x1c7b5841...5976 at tx 0x439f6509...646a8a
Indexed Transactions
0
Contract Bytecode
4279 bytes
0x608060405234801561001057600080fd5b50600061001b61008b565b600080356001600160e01b0319168152602082905260409020549091506001600160a01b0316806100675760405162461bcd60e51b815260040161005e90610e21565b60405180910390fd5b3660008037600080366000845af43d6000803e808015610086573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90565b60005b83518110156101ec5760008482815181106100c957fe5b6020026020010151602001519050600060028111156100e457fe5b8160028111156100f057fe5b14156101335761012e85838151811061010557fe5b60200260200101516000015186848151811061011d57fe5b602002602001015160400151610237565b6101e3565b600181600281111561014157fe5b141561017f5761012e85838151811061015657fe5b60200260200101516000015186848151811061016e57fe5b6020026020010151604001516103b7565b600281600281111561018d57fe5b14156101cb5761012e8583815181106101a257fe5b6020026020010151600001518684815181106101ba57fe5b602002602001015160400151610541565b60405162461bcd60e51b815260040161005e90610d8e565b506001016100b2565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67383838360405161022093929190610b42565b60405180910390a161023282826105fc565b505050565b60008151116102585760405162461bcd60e51b815260040161005e90610ce6565b600061026261008b565b90506001600160a01b03831661028a5760405162461bcd60e51b815260040161005e90610dd5565b6001600160a01b038316600090815260018201602052604090205461ffff811661032c576102d08460405180606001604052806024815260200161105e60249139610723565b6002820180546001600160a01b038616600081815260018087016020908152604083208201805461ffff191661ffff90961695909517909455845490810185559381529190912090910180546001600160a01b03191690911790555b60005b83518110156103b057600084828151811061034657fe5b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b031680156103965760405162461bcd60e51b815260040161005e90610f01565b6103a28583868a610744565b50506001918201910161032f565b5050505050565b60008151116103d85760405162461bcd60e51b815260040161005e90610ce6565b60006103e261008b565b90506001600160a01b03831661040a5760405162461bcd60e51b815260040161005e90610dd5565b6001600160a01b038316600090815260018201602052604090205461ffff81166104ac576104508460405180606001604052806024815260200161105e60249139610723565b6002820180546001600160a01b038616600081815260018087016020908152604083208201805461ffff191661ffff90961695909517909455845490810185559381529190912090910180546001600160a01b03191690911790555b60005b83518110156103b05760008482815181106104c657fe5b6020908102919091018101516001600160e01b031981166000908152918690526040909120549091506001600160a01b0390811690871681141561051c5760405162461bcd60e51b815260040161005e90610f56565b6105278582846107e7565b6105338583868a610744565b5050600191820191016104af565b60008151116105625760405162461bcd60e51b815260040161005e90610ce6565b600061056c61008b565b90506001600160a01b038316156105955760405162461bcd60e51b815260040161005e90610fb3565b60005b82518110156105f65760008382815181106105af57fe5b6020908102919091018101516001600160e01b031981166000908152918590526040909120549091506001600160a01b03166105ec8482846107e7565b5050600101610598565b50505050565b6001600160a01b03821661062e578051156106295760405162461bcd60e51b815260040161005e90610c43565b61071f565b600081511161064f5760405162461bcd60e51b815260040161005e90610e56565b6001600160a01b0382163014610681576106818260405180606001604052806028815260200161103660289139610723565b600080836001600160a01b03168360405161069c9190610b26565b600060405180830381855af49150503d80600081146106d7576040519150601f19603f3d011682016040523d82523d6000602084013e6106dc565b606091505b5091509150816105f657805115610707578060405162461bcd60e51b815260040161005e9190610c29565b60405162461bcd60e51b815260040161005e90610ca0565b5050565b813b81816105f65760405162461bcd60e51b815260040161005e9190610c29565b6001600160e01b03198316600081815260208681526040808320805461ffff60a01b1916600160a01b61ffff98909816979097029690961786556001600160a01b0394909416808352600180890183529483208054958601815583528183206008860401805463ffffffff60079097166004026101000a968702191660e09890981c9590950296909617909355529290925281546001600160a01b031916179055565b6001600160a01b03821661080d5760405162461bcd60e51b815260040161005e90610d31565b6001600160a01b0382163014156108365760405162461bcd60e51b815260040161005e90610eb3565b6001600160e01b03198116600090815260208481526040808320546001600160a01b03861684526001870190925290912054600160a01b90910461ffff169060001901808214610957576001600160a01b038416600090815260018601602052604081208054839081106108a657fe5b600091825260208083206008830401546001600160a01b038916845260018a019091526040909220805460079092166004026101000a90920460e01b9250829190859081106108f157fe5b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b031992909216825286905260409020805461ffff60a01b1916600160a01b61ffff8516021790555b6001600160a01b0384166000908152600186016020526040902080548061097a57fe5b60008281526020808220600860001990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b0319851682528690526040902080546001600160b01b0319169055806103b05760028501546001600160a01b03851660009081526001878101602052604090912001546000199091019061ffff16808214610a8e576000876002018381548110610a1857fe5b6000918252602090912001546002890180546001600160a01b039092169250829184908110610a4357fe5b600091825260208083209190910180546001600160a01b0319166001600160a01b0394851617905592909116815260018981019092526040902001805461ffff191661ffff83161790555b86600201805480610a9b57fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03881682526001898101909152604090912001805461ffff1916905550505050505050565b6001600160a01b03169052565b60008151808452610b12816020860160208601611009565b601f01601f19169290920160200192915050565b60008251610b38818460208701611009565b9190910192915050565b606080825284518282018190526000919060809081850190602080820287018401818b01875b84811015610bfa57898303607f19018652815180516001600160a01b03168452848101518985019060038110610b9a57fe5b858701526040918201519185018a9052815190819052908501908a90898601905b80831015610be55783516001600160e01b0319168252928701926001929092019190870190610bbb565b50978601979450505090830190600101610b68565b5050610c088289018b610aed565b8781036040890152610c1a818a610afa565b9b9a5050505050505050505050565b600060208252610c3c6020830184610afa565b9392505050565b6020808252603c908201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860408201527f3029206275745f63616c6c64617461206973206e6f7420656d70747900000000606082015260800190565b60208082526026908201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656040820152651d995c9d195960d21b606082015260800190565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b60208082526037908201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360408201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606082015260800190565b60208082526027908201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756040820152663a20b1ba34b7b760c91b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b6020808252818101527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f74206578697374604082015260600190565b6020808252603d908201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460408201527f7920627574205f696e6974206973206e6f742061646472657373283029000000606082015260800190565b6020808252602e908201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560408201526d3a30b1363290333ab731ba34b7b760911b606082015260800190565b60208082526035908201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6040820152746e207468617420616c72656164792065786973747360581b606082015260800190565b60208082526038908201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60408201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606082015260800190565b60208082526036908201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604082015275657373206d757374206265206164647265737328302960501b606082015260800190565b60005b8381101561102457818101518382015260200161100c565b838111156105f6575050600091015256fe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a2646970667358221220043c177efb5eac6ee624fabfd8a1fb025490da2d22d3886abcbd9485dc3e506364736f6c63430007060033
Verified Source Code Full Match
Compiler: v0.7.6+commit.7338295f
EVM: istanbul
Optimization: Yes (200 runs)
Router.sol 42 lines
// SPDX-License-Identifier: Unlicense
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IDiamondLoupe.sol";
import "./interfaces/IDiamondCut.sol";
import "./interfaces/IERC165.sol";
import "./libraries/LibDiamond.sol";
contract Router {
constructor(IDiamondCut.FacetCut[] memory _diamondCut) payable {
LibDiamond.diamondCut(_diamondCut, address(0), new bytes(0));
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
// adding ERC165 data
ds.supportedInterfaces[type(IERC165).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;
}
// Find facet for function that is called and execute the
// function if a facet is found and return any value.
fallback() external {
LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
require(facet != address(0), "Diamond: Function does not exist");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}
IERC165.sol 13 lines
// SPDX-License-Identifier: Unlicense
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceId The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
LibDiamond.sol 184 lines
// SPDX-License-Identifier: Unlicense
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "../interfaces/IDiamondCut.sol";
library LibDiamond {
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
struct FacetAddressAndPosition {
address facetAddress;
uint16 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array
}
struct FacetFunctionSelectors {
bytes4[] functionSelectors;
uint16 facetAddressPosition; // position of facetAddress in facetAddresses array
}
struct DiamondStorage {
// maps function selector to the facet address and
// the position of the selector in the facetFunctionSelectors.selectors array
mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
// maps facet addresses to function selectors
mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
// facet addresses
address[] facetAddresses;
// Used to query if a contract implements an interface.
// Used to implement ERC-165.
mapping(bytes4 => bool) supportedInterfaces;
}
function diamondStorage() internal pure returns (DiamondStorage storage ds) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
}
event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);
// Internal function version of diamondCut
function diamondCut(
IDiamondCut.FacetCut[] memory _diamondCut,
address _init,
bytes memory _calldata
) internal {
for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;
if (action == IDiamondCut.FacetCutAction.Add) {
addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} else if (action == IDiamondCut.FacetCutAction.Replace) {
replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} else if (action == IDiamondCut.FacetCutAction.Remove) {
removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);
} else {
revert("LibDiamondCut: Incorrect FacetCutAction");
}
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
// uint16 selectorCount = uint16(diamondStorage().selectors.length);
require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
uint16 selectorPosition = uint16(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
// add new facet address if it does not exist
if (selectorPosition == 0) {
enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = uint16(ds.facetAddresses.length);
ds.facetAddresses.push(_facetAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
require(oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists");
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
require(_facetAddress != address(0), "LibDiamondCut: Add facet can't be address(0)");
uint16 selectorPosition = uint16(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);
// add new facet address if it does not exist
if (selectorPosition == 0) {
enforceHasContractCode(_facetAddress, "LibDiamondCut: New facet has no code");
ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = uint16(ds.facetAddresses.length);
ds.facetAddresses.push(_facetAddress);
}
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
require(oldFacetAddress != _facetAddress, "LibDiamondCut: Can't replace function with same function");
removeFunction(ds, oldFacetAddress, selector);
// add function
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {
require(_functionSelectors.length > 0, "LibDiamondCut: No selectors in facet to cut");
DiamondStorage storage ds = diamondStorage();
// if function does not exist then do nothing and return
require(_facetAddress == address(0), "LibDiamondCut: Remove facet address must be address(0)");
for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;
removeFunction(ds, oldFacetAddress, selector);
}
}
function addFunction(DiamondStorage storage ds, bytes4 _selector, uint16 _selectorPosition, address _facetAddress) internal {
ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;
ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);
ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
}
function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal {
require(_facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist");
// an immutable function is a function defined directly in a diamond
require(_facetAddress != address(this), "LibDiamondCut: Can't remove immutable function");
// replace selector with last selector, then delete last selector
uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;
uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;
// if not the same then replace _selector with lastSelector
if (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];
ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;
ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint16(selectorPosition);
}
// delete the last selector
ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
delete ds.selectorToFacetAndPosition[_selector];
// if no more selectors for facet address then delete the facet address
if (lastSelectorPosition == 0) {
// replace facet address with last facet address and delete last facet address
uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
if (facetAddressPosition != lastFacetAddressPosition) {
address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];
ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = uint16(facetAddressPosition);
}
ds.facetAddresses.pop();
delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;
}
}
function initializeDiamondCut(address _init, bytes memory _calldata) internal {
if (_init == address(0)) {
require(_calldata.length == 0, "LibDiamondCut: _init is address(0) but_calldata is not empty");
} else {
require(_calldata.length > 0, "LibDiamondCut: _calldata is empty but _init is not address(0)");
if (_init != address(this)) {
enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
}
(bool success, bytes memory error) = _init.delegatecall(_calldata);
if (!success) {
if (error.length > 0) {
// bubble up the error
revert(string(error));
} else {
revert("LibDiamondCut: _init function reverted");
}
}
}
}
function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
uint256 contractSize;
assembly {
contractSize := extcodesize(_contract)
}
require(contractSize > 0, _errorMessage);
}
}
IDiamondCut.sol 30 lines
// SPDX-License-Identifier: Unlicense
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IDiamondCut {
enum FacetCutAction {Add, Replace, Remove}
// Add=0, Replace=1, Remove=2
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
/// @notice Add/replace/remove any number of functions and optionally execute
/// a function with delegatecall
/// @param _diamondCut Contains the facet addresses and function selectors
/// @param _init The address of the contract or facet to execute _calldata
/// @param _calldata A function call, including function selector and arguments
/// _calldata is executed with delegatecall on _init
/// @param _signatures The signatures of between n/2 and n validators for this upgrade
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata,
bytes[] memory _signatures
) external;
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
IDiamondLoupe.sol 34 lines
// SPDX-License-Identifier: Unlicense
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
/// These functions are expected to be called frequently
/// by tools.
struct Facet {
address facetAddress;
bytes4[] functionSelectors;
}
/// @notice Gets all facet addresses and their four byte function selectors.
/// @return facets_ Facet
function facets() external view returns (Facet[] memory facets_);
/// @notice Gets all the function selectors supported by a specific facet.
/// @param _facet The facet address.
/// @return facetFunctionSelectors_
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
/// @notice Get all the facet addresses used by a diamond.
/// @return facetAddresses_
function facetAddresses() external view returns (address[] memory facetAddresses_);
/// @notice Gets the facet that supports the given selector.
/// @dev If facet is not found return address(0).
/// @param _functionSelector The function selector.
/// @return facetAddress_ The facet address.
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
IERC20.sol 77 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
Recent Transactions
No transactions found for this address