More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 17,536 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Wallet | 9771839 | 1738 days ago | IN | 0 ETH | 0.00338435 | ||||
Create Wallet | 9771839 | 1738 days ago | IN | 0 ETH | 0.00338369 | ||||
Create Wallet | 9771839 | 1738 days ago | IN | 0 ETH | 0.00338355 | ||||
Create Wallet | 9771837 | 1738 days ago | IN | 0 ETH | 0.00338391 | ||||
Create Wallet | 9771837 | 1738 days ago | IN | 0 ETH | 0.00338369 | ||||
Create Wallet | 9771837 | 1738 days ago | IN | 0 ETH | 0.00253779 | ||||
Create Wallet | 9771695 | 1738 days ago | IN | 0 ETH | 0.00676739 | ||||
Create Wallet | 9771441 | 1738 days ago | IN | 0 ETH | 0.00592134 | ||||
Create Wallet | 9770289 | 1738 days ago | IN | 0 ETH | 0.00676812 | ||||
Create Wallet | 9769814 | 1738 days ago | IN | 0 ETH | 0.00846015 | ||||
Create Wallet | 9769681 | 1738 days ago | IN | 0 ETH | 0.00084601 | ||||
Create Wallet | 9769681 | 1738 days ago | IN | 0 ETH | 0.00084588 | ||||
Create Wallet | 9769681 | 1738 days ago | IN | 0 ETH | 0.00084587 | ||||
Create Wallet | 9769681 | 1738 days ago | IN | 0 ETH | 0.00084592 | ||||
Create Wallet | 9769680 | 1738 days ago | IN | 0 ETH | 0.00084601 | ||||
Create Wallet | 9769680 | 1738 days ago | IN | 0 ETH | 0.00084588 | ||||
Create Wallet | 9769680 | 1738 days ago | IN | 0 ETH | 0.00084592 | ||||
Create Wallet | 9769673 | 1738 days ago | IN | 0 ETH | 0.00169195 | ||||
Create Wallet | 9769503 | 1738 days ago | IN | 0 ETH | 0.0067687 | ||||
Create Wallet | 9768970 | 1738 days ago | IN | 0 ETH | 0.00592172 | ||||
Create Wallet | 9768545 | 1738 days ago | IN | 0 ETH | 0.00592249 | ||||
Create Wallet | 9767474 | 1738 days ago | IN | 0 ETH | 0.00169184 | ||||
Create Wallet | 9767474 | 1738 days ago | IN | 0 ETH | 0.00169192 | ||||
Create Wallet | 9767474 | 1738 days ago | IN | 0 ETH | 0.00169199 | ||||
Create Wallet | 9767473 | 1738 days ago | IN | 0 ETH | 0.00169192 |
Latest 25 internal transactions (View All)
Advanced mode:
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:
WalletFactory
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
Yes with 999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-02-04 */ pragma solidity ^0.4.24; /** * @title Owned * @dev Basic contract to define an owner. * @author Julien Niset - <[email protected]> */ contract Owned { // The owner address public owner; event OwnerChanged(address indexed _newOwner); /** * @dev Throws if the sender is not the owner. */ modifier onlyOwner { require(msg.sender == owner, "Must be owner"); _; } constructor() public { owner = msg.sender; } /** * @dev Lets the owner transfer ownership of the contract to a new owner. * @param _newOwner The new owner. */ function changeOwner(address _newOwner) external onlyOwner { require(_newOwner != address(0), "Address must not be null"); owner = _newOwner; emit OwnerChanged(_newOwner); } } /** * @title Managed * @dev Basic contract that defines a set of managers. Only the owner can add/remove managers. * @author Julien Niset - <[email protected]> */ contract Managed is Owned { // The managers mapping (address => bool) public managers; /** * @dev Throws if the sender is not a manager. */ modifier onlyManager { require(managers[msg.sender] == true, "M: Must be manager"); _; } event ManagerAdded(address indexed _manager); event ManagerRevoked(address indexed _manager); /** * @dev Adds a manager. * @param _manager The address of the manager. */ function addManager(address _manager) external onlyOwner { require(_manager != address(0), "M: Address must not be null"); if(managers[_manager] == false) { managers[_manager] = true; emit ManagerAdded(_manager); } } /** * @dev Revokes a manager. * @param _manager The address of the manager. */ function revokeManager(address _manager) external onlyOwner { require(managers[_manager] == true, "M: Target must be an existing manager"); delete managers[_manager]; emit ManagerRevoked(_manager); } } /** * ENS Registry interface. */ contract ENSRegistry { function owner(bytes32 _node) public view returns (address); function resolver(bytes32 _node) public view returns (address); function ttl(bytes32 _node) public view returns (uint64); function setOwner(bytes32 _node, address _owner) public; function setSubnodeOwner(bytes32 _node, bytes32 _label, address _owner) public; function setResolver(bytes32 _node, address _resolver) public; function setTTL(bytes32 _node, uint64 _ttl) public; } /** * ENS Resolver interface. */ contract ENSResolver { function addr(bytes32 _node) public view returns (address); function setAddr(bytes32 _node, address _addr) public; function name(bytes32 _node) public view returns (string); function setName(bytes32 _node, string _name) public; } /** * ENS Reverse Registrar interface. */ contract ENSReverseRegistrar { function claim(address _owner) public returns (bytes32 _node); function claimWithResolver(address _owner, address _resolver) public returns (bytes32); function setName(string _name) public returns (bytes32); function node(address _addr) public view returns (bytes32); } /* * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'slice'. A slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length slice). Since a slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on slice that need to return * a slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ /* solium-disable */ library strings { struct slice { uint _len; uint _ptr; } function memcpy(uint dest, uint src, uint len) private pure { // Copy word-length chunks while possible for(; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint mask = 256 ** (32 - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string memory self) internal pure returns (slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (self & 0xffffffffffffffffffffffffffffffff == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (self & 0xffffffffffffffff == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (self & 0xffffffff == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (self & 0xffff == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (self & 0xff == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a slice. * @return A new slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new slice containing the same data as the current slice. * @param self The slice to copy. * @return A new slice containing the same data as `self`. */ function copy(slice memory self) internal pure returns (slice memory) { return slice(self._len, self._ptr); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the slice. Note that this operation * takes time proportional to the length of the slice; avoid using it * in loops, and call `slice.empty()` if you only need to know whether * the slice is empty or not. * @param self The slice to operate on. * @return The length of the slice in runes. */ function len(slice memory self) internal pure returns (uint l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (l = 0; ptr < end; l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the slice is empty (has a length of 0). * @param self The slice to operate on. * @return True if the slice is empty, False otherwise. */ function empty(slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first slice to compare. * @param other The second slice to compare. * @return The result of the comparison. */ function compare(slice memory self, slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint256 mask = uint256(-1); // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } uint256 diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first slice to compare. * @param self The second slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(slice memory self, slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the slice into `rune`, advancing the * slice to point to the next rune and returning `self`. * @param self The slice to operate on. * @param rune The slice that will contain the first rune. * @return `rune`. */ function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint l; uint b; // Load the first byte of the rune into the LSBs of b assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (b < 0x80) { l = 1; } else if(b < 0xE0) { l = 2; } else if(b < 0xF0) { l = 3; } else { l = 4; } // Check for truncated codepoints if (l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += l; self._len -= l; rune._len = l; return rune; } /* * @dev Returns the first rune in the slice, advancing the slice to point * to the next rune. * @param self The slice to operate on. * @return A slice containing only the first rune from `self`. */ function nextRune(slice memory self) internal pure returns (slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the slice. * @param self The slice to operate on. * @return The number of the first codepoint in the slice. */ function ord(slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the slice. * @param self The slice to hash. * @return The hash of the slice. */ function keccak(slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function startsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the slice ends with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function endsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function until(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the slice. `self` is set to the empty slice * if `needle` is not found. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty slice. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice memory self, slice memory needle) internal pure returns (slice memory token) { split(self, needle, token); } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice memory self, slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(slice memory self, slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice memory self, slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(slice memory self, slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } } /** * @title ENSConsumer * @dev Helper contract to resolve ENS names. * @author Julien Niset - <[email protected]> */ contract ENSConsumer { using strings for *; // namehash('addr.reverse') bytes32 constant public ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; // the address of the ENS registry address ensRegistry; /** * @dev No address should be provided when deploying on Mainnet to avoid storage cost. The * contract will use the hardcoded value. */ constructor(address _ensRegistry) public { ensRegistry = _ensRegistry; } /** * @dev Resolves an ENS name to an address. * @param _node The namehash of the ENS name. */ function resolveEns(bytes32 _node) public view returns (address) { address resolver = getENSRegistry().resolver(_node); return ENSResolver(resolver).addr(_node); } /** * @dev Gets the official ENS registry. */ function getENSRegistry() public view returns (ENSRegistry) { return ENSRegistry(ensRegistry); } /** * @dev Gets the official ENS reverse registrar. */ function getENSReverseRegistrar() public view returns (ENSReverseRegistrar) { return ENSReverseRegistrar(getENSRegistry().owner(ADDR_REVERSE_NODE)); } } /** * @dev Interface for an ENS Mananger. */ interface IENSManager { function changeRootnodeOwner(address _newOwner) external; function register(string _label, address _owner) external; function isAvailable(bytes32 _subnode) external view returns(bool); } /** * @title Proxy * @dev Basic proxy that delegates all calls to a fixed implementing contract. * The implementing contract cannot be upgraded. * @author Julien Niset - <[email protected]> */ contract Proxy { address implementation; event Received(uint indexed value, address indexed sender, bytes data); constructor(address _implementation) public { implementation = _implementation; } function() external payable { if(msg.data.length == 0 && msg.value > 0) { emit Received(msg.value, msg.sender, msg.data); } else { // solium-disable-next-line security/no-inline-assembly assembly { let target := sload(0) calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas, target, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } } } /** * @title Module * @dev Interface for a module. * A module MUST implement the addModule() method to ensure that a wallet with at least one module * can never end up in a "frozen" state. * @author Julien Niset - <[email protected]> */ interface Module { /** * @dev Inits a module for a wallet by e.g. setting some wallet specific parameters in storage. * @param _wallet The wallet. */ function init(BaseWallet _wallet) external; /** * @dev Adds a module to a wallet. * @param _wallet The target wallet. * @param _module The modules to authorise. */ function addModule(BaseWallet _wallet, Module _module) external; /** * @dev Utility method to recover any ERC20 token that was sent to the * module by mistake. * @param _token The token to recover. */ function recoverToken(address _token) external; } /** * @title BaseWallet * @dev Simple modular wallet that authorises modules to call its invoke() method. * Based on https://gist.github.com/Arachnid/a619d31f6d32757a4328a428286da186 by * @author Julien Niset - <[email protected]> */ contract BaseWallet { // The implementation of the proxy address public implementation; // The owner address public owner; // The authorised modules mapping (address => bool) public authorised; // The enabled static calls mapping (bytes4 => address) public enabled; // The number of modules uint public modules; event AuthorisedModule(address indexed module, bool value); event EnabledStaticCall(address indexed module, bytes4 indexed method); event Invoked(address indexed module, address indexed target, uint indexed value, bytes data); event Received(uint indexed value, address indexed sender, bytes data); event OwnerChanged(address owner); /** * @dev Throws if the sender is not an authorised module. */ modifier moduleOnly { require(authorised[msg.sender], "BW: msg.sender not an authorized module"); _; } /** * @dev Inits the wallet by setting the owner and authorising a list of modules. * @param _owner The owner. * @param _modules The modules to authorise. */ function init(address _owner, address[] _modules) external { require(owner == address(0) && modules == 0, "BW: wallet already initialised"); require(_modules.length > 0, "BW: construction requires at least 1 module"); owner = _owner; modules = _modules.length; for(uint256 i = 0; i < _modules.length; i++) { require(authorised[_modules[i]] == false, "BW: module is already added"); authorised[_modules[i]] = true; Module(_modules[i]).init(this); emit AuthorisedModule(_modules[i], true); } } /** * @dev Enables/Disables a module. * @param _module The target module. * @param _value Set to true to authorise the module. */ function authoriseModule(address _module, bool _value) external moduleOnly { if (authorised[_module] != _value) { if(_value == true) { modules += 1; authorised[_module] = true; Module(_module).init(this); } else { modules -= 1; require(modules > 0, "BW: wallet must have at least one module"); delete authorised[_module]; } emit AuthorisedModule(_module, _value); } } /** * @dev Enables a static method by specifying the target module to which the call * must be delegated. * @param _module The target module. * @param _method The static method signature. */ function enableStaticCall(address _module, bytes4 _method) external moduleOnly { require(authorised[_module], "BW: must be an authorised module for static call"); enabled[_method] = _module; emit EnabledStaticCall(_module, _method); } /** * @dev Sets a new owner for the wallet. * @param _newOwner The new owner. */ function setOwner(address _newOwner) external moduleOnly { require(_newOwner != address(0), "BW: address cannot be null"); owner = _newOwner; emit OwnerChanged(_newOwner); } /** * @dev Performs a generic transaction. * @param _target The address for the transaction. * @param _value The value of the transaction. * @param _data The data of the transaction. */ function invoke(address _target, uint _value, bytes _data) external moduleOnly { // solium-disable-next-line security/no-call-value require(_target.call.value(_value)(_data), "BW: call to target failed"); emit Invoked(msg.sender, _target, _value, _data); } /** * @dev This method makes it possible for the wallet to comply to interfaces expecting the wallet to * implement specific static methods. It delegates the static call to a target contract if the data corresponds * to an enabled method, or logs the call otherwise. */ function() public payable { if(msg.data.length > 0) { address module = enabled[msg.sig]; if(module == address(0)) { emit Received(msg.value, msg.sender, msg.data); } else { require(authorised[module], "BW: must be an authorised module for static call"); // solium-disable-next-line security/no-inline-assembly assembly { calldatacopy(0, 0, calldatasize()) let result := staticcall(gas, module, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } } } } /** * ERC20 contract interface. */ contract ERC20 { function totalSupply() public view returns (uint); function decimals() public view returns (uint); function balanceOf(address tokenOwner) public view returns (uint balance); function allowance(address tokenOwner, address spender) public view returns (uint remaining); function transfer(address to, uint tokens) public returns (bool success); function approve(address spender, uint tokens) public returns (bool success); function transferFrom(address from, address to, uint tokens) public returns (bool success); } /** * @title ModuleRegistry * @dev Registry of authorised modules. * Modules must be registered before they can be authorised on a wallet. * @author Julien Niset - <[email protected]> */ contract ModuleRegistry is Owned { mapping (address => Info) internal modules; mapping (address => Info) internal upgraders; event ModuleRegistered(address indexed module, bytes32 name); event ModuleDeRegistered(address module); event UpgraderRegistered(address indexed upgrader, bytes32 name); event UpgraderDeRegistered(address upgrader); struct Info { bool exists; bytes32 name; } /** * @dev Registers a module. * @param _module The module. * @param _name The unique name of the module. */ function registerModule(address _module, bytes32 _name) external onlyOwner { require(!modules[_module].exists, "MR: module already exists"); modules[_module] = Info({exists: true, name: _name}); emit ModuleRegistered(_module, _name); } /** * @dev Deregisters a module. * @param _module The module. */ function deregisterModule(address _module) external onlyOwner { require(modules[_module].exists, "MR: module does not exists"); delete modules[_module]; emit ModuleDeRegistered(_module); } /** * @dev Registers an upgrader. * @param _upgrader The upgrader. * @param _name The unique name of the upgrader. */ function registerUpgrader(address _upgrader, bytes32 _name) external onlyOwner { require(!upgraders[_upgrader].exists, "MR: upgrader already exists"); upgraders[_upgrader] = Info({exists: true, name: _name}); emit UpgraderRegistered(_upgrader, _name); } /** * @dev Deregisters an upgrader. * @param _upgrader The _upgrader. */ function deregisterUpgrader(address _upgrader) external onlyOwner { require(upgraders[_upgrader].exists, "MR: upgrader does not exists"); delete upgraders[_upgrader]; emit UpgraderDeRegistered(_upgrader); } /** * @dev Utility method enbaling the owner of the registry to claim any ERC20 token that was sent to the * registry. * @param _token The token to recover. */ function recoverToken(address _token) external onlyOwner { uint total = ERC20(_token).balanceOf(address(this)); ERC20(_token).transfer(msg.sender, total); } /** * @dev Gets the name of a module from its address. * @param _module The module address. * @return the name. */ function moduleInfo(address _module) external view returns (bytes32) { return modules[_module].name; } /** * @dev Gets the name of an upgrader from its address. * @param _upgrader The upgrader address. * @return the name. */ function upgraderInfo(address _upgrader) external view returns (bytes32) { return upgraders[_upgrader].name; } /** * @dev Checks if a module is registered. * @param _module The module address. * @return true if the module is registered. */ function isRegisteredModule(address _module) external view returns (bool) { return modules[_module].exists; } /** * @dev Checks if a list of modules are registered. * @param _modules The list of modules address. * @return true if all the modules are registered. */ function isRegisteredModule(address[] _modules) external view returns (bool) { for(uint i = 0; i < _modules.length; i++) { if (!modules[_modules[i]].exists) { return false; } } return true; } /** * @dev Checks if an upgrader is registered. * @param _upgrader The upgrader address. * @return true if the upgrader is registered. */ function isRegisteredUpgrader(address _upgrader) external view returns (bool) { return upgraders[_upgrader].exists; } } /** * @title WalletFactory * @dev The WalletFactory contract creates and assigns wallets to accounts. * @author Julien Niset - <[email protected]> */ contract WalletFactory is Owned, Managed, ENSConsumer { // The address of the module registry address public moduleRegistry; // The address of the base wallet implementation address public walletImplementation; // The address of the ENS manager address public ensManager; // The address of the ENS resolver address public ensResolver; // *************** Events *************************** // event ModuleRegistryChanged(address addr); event WalletImplementationChanged(address addr); event ENSManagerChanged(address addr); event ENSResolverChanged(address addr); event WalletCreated(address indexed _wallet, address indexed _owner); // *************** Constructor ********************** // /** * @dev Default constructor. */ constructor( address _ensRegistry, address _moduleRegistry, address _walletImplementation, address _ensManager, address _ensResolver ) ENSConsumer(_ensRegistry) public { moduleRegistry = _moduleRegistry; walletImplementation = _walletImplementation; ensManager = _ensManager; ensResolver = _ensResolver; } // *************** External Functions ********************* // /** * @dev Lets the manager create a wallet for an account. The wallet is initialised with a list of modules. * @param _owner The account address. * @param _modules The list of modules. * @param _label Optional ENS label of the new wallet (e.g. franck). */ function createWallet(address _owner, address[] _modules, string _label) external onlyManager { require(_owner != address(0), "WF: owner cannot be null"); require(_modules.length > 0, "WF: cannot assign with less than 1 module"); require(ModuleRegistry(moduleRegistry).isRegisteredModule(_modules), "WF: one or more modules are not registered"); // create the proxy Proxy proxy = new Proxy(walletImplementation); address wallet = address(proxy); // check for ENS bytes memory labelBytes = bytes(_label); if (labelBytes.length != 0) { // add the factory to the modules so it can claim the reverse ENS address[] memory extendedModules = new address[](_modules.length + 1); extendedModules[0] = address(this); for(uint i = 0; i < _modules.length; i++) { extendedModules[i + 1] = _modules[i]; } // initialise the wallet with the owner and the extended modules BaseWallet(wallet).init(_owner, extendedModules); // register ENS registerWalletENS(wallet, _label); // remove the factory from the authorised modules BaseWallet(wallet).authoriseModule(address(this), false); } else { // initialise the wallet with the owner and the modules BaseWallet(wallet).init(_owner, _modules); } emit WalletCreated(wallet, _owner); } /** * @dev Lets the owner change the address of the module registry contract. * @param _moduleRegistry The address of the module registry contract. */ function changeModuleRegistry(address _moduleRegistry) external onlyOwner { require(_moduleRegistry != address(0), "WF: address cannot be null"); moduleRegistry = _moduleRegistry; emit ModuleRegistryChanged(_moduleRegistry); } /** * @dev Lets the owner change the address of the implementing contract. * @param _walletImplementation The address of the implementing contract. */ function changeWalletImplementation(address _walletImplementation) external onlyOwner { require(_walletImplementation != address(0), "WF: address cannot be null"); walletImplementation = _walletImplementation; emit WalletImplementationChanged(_walletImplementation); } /** * @dev Lets the owner change the address of the ENS manager contract. * @param _ensManager The address of the ENS manager contract. */ function changeENSManager(address _ensManager) external onlyOwner { require(_ensManager != address(0), "WF: address cannot be null"); ensManager = _ensManager; emit ENSManagerChanged(_ensManager); } /** * @dev Lets the owner change the address of the ENS resolver contract. * @param _ensResolver The address of the ENS resolver contract. */ function changeENSResolver(address _ensResolver) external onlyOwner { require(_ensResolver != address(0), "WF: address cannot be null"); ensResolver = _ensResolver; emit ENSResolverChanged(_ensResolver); } /** * @dev Register an ENS subname to a wallet. * @param _wallet The wallet address. * @param _label ENS label of the new wallet (e.g. franck). */ function registerWalletENS(address _wallet, string _label) internal { // claim reverse bytes memory methodData = abi.encodeWithSignature("claimWithResolver(address,address)", ensManager, ensResolver); BaseWallet(_wallet).invoke(getENSReverseRegistrar(), 0, methodData); // register with ENS manager IENSManager(ensManager).register(_label, _wallet); } /** * @dev Inits the module for a wallet by logging an event. * The method can only be called by the wallet itself. * @param _wallet The wallet. */ function init(BaseWallet _wallet) external pure { //do nothing } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"_moduleRegistry","type":"address"}],"name":"changeModuleRegistry","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getENSReverseRegistrar","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"}],"name":"init","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_manager","type":"address"}],"name":"addManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getENSRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_manager","type":"address"}],"name":"revokeManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ensManager","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ADDR_REVERSE_NODE","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"walletImplementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_ensManager","type":"address"}],"name":"changeENSManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_node","type":"bytes32"}],"name":"resolveEns","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ensResolver","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_owner","type":"address"},{"name":"_modules","type":"address[]"},{"name":"_label","type":"string"}],"name":"createWallet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"moduleRegistry","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_walletImplementation","type":"address"}],"name":"changeWalletImplementation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_ensResolver","type":"address"}],"name":"changeENSResolver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"managers","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_ensRegistry","type":"address"},{"name":"_moduleRegistry","type":"address"},{"name":"_walletImplementation","type":"address"},{"name":"_ensManager","type":"address"},{"name":"_ensResolver","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"}],"name":"ModuleRegistryChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"}],"name":"WalletImplementationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"}],"name":"ENSManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"}],"name":"ENSResolverChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_owner","type":"address"}],"name":"WalletCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_manager","type":"address"}],"name":"ManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_manager","type":"address"}],"name":"ManagerRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_newOwner","type":"address"}],"name":"OwnerChanged","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405160a08061192e833981016040908152815160208301519183015160608401516080909401516000805433600160a060020a0319918216178255600280548216600160a060020a03968716179055600380548216968616969096179095556004805486169385169390931790925560058054851695841695909517909455600680549093169190931617905561187f9081906100af90396000f3006080604052600436106101065763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166308d668bc811461010b57806309d734421461012e57806319ab453c1461015f5780632d06177a146101805780632f680795146101a1578063377e32e6146101b65780635a6971f9146101d75780637cf8a2eb146101ec5780638117abc1146102135780638da5cb5b1461022857806390ed991c1461023d5780639eb869c71461025e578063a6f9dae114610276578063adce1c5f14610297578063aff18575146102ac578063b95459e4146102e5578063c799cd11146102fa578063fb4199991461031b578063fdff9b4d1461033c575b600080fd5b34801561011757600080fd5b5061012c600160a060020a0360043516610371565b005b34801561013a57600080fd5b5061014361049e565b60408051600160a060020a039092168252519081900360200190f35b34801561016b57600080fd5b5061012c600160a060020a036004351661055d565b34801561018c57600080fd5b5061012c600160a060020a0360043516610560565b3480156101ad57600080fd5b5061014361069d565b3480156101c257600080fd5b5061012c600160a060020a03600435166106ac565b3480156101e357600080fd5b506101436107fd565b3480156101f857600080fd5b5061020161080c565b60408051918252519081900360200190f35b34801561021f57600080fd5b50610143610830565b34801561023457600080fd5b5061014361083f565b34801561024957600080fd5b5061012c600160a060020a036004351661084e565b34801561026a57600080fd5b5061014360043561097b565b34801561028257600080fd5b5061012c600160a060020a0360043516610ab4565b3480156102a357600080fd5b50610143610bd5565b3480156102b857600080fd5b5061012c60048035600160a060020a03169060248035808201929081013591604435908101910135610be4565b3480156102f157600080fd5b50610143611213565b34801561030657600080fd5b5061012c600160a060020a0360043516611222565b34801561032757600080fd5b5061012c600160a060020a036004351661134f565b34801561034857600080fd5b5061035d600160a060020a036004351661147c565b604080519115158252519081900360200190f35b600054600160a060020a031633146103d85760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561043d5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60038054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f9bf4baeb20b6008af8dfd7fed5c50dce707a05623b022e5d61a00c7db7f90c729181900360200190a150565b60006104a861069d565b604080517f02571be30000000000000000000000000000000000000000000000000000000081527f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260048201529051600160a060020a0392909216916302571be3916024808201926020929091908290030181600087803b15801561052c57600080fd5b505af1158015610540573d6000803e3d6000fd5b505050506040513d602081101561055657600080fd5b5051905090565b50565b600054600160a060020a031633146105c75760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561062c5760408051600080516020611834833981519152815260206004820152601b60248201527f4d3a2041646472657373206d757374206e6f74206265206e756c6c0000000000604482015290519081900360640190fd5b600160a060020a03811660009081526001602052604090205460ff16151561055d57600160a060020a0381166000818152600160208190526040808320805460ff1916909217909155517f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a9190a250565b600254600160a060020a031690565b600054600160a060020a031633146107135760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03811660009081526001602081905260409091205460ff161515146107b45760408051600080516020611834833981519152815260206004820152602560248201527f4d3a20546172676574206d75737420626520616e206578697374696e67206d6160448201527f6e61676572000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a038116600081815260016020526040808220805460ff19169055517fe5def11e0516f317f9c37b8835aec29fc01db4d4b6d6fecaca339d3596a29bc19190a250565b600554600160a060020a031681565b7f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e281565b600454600160a060020a031681565b600054600160a060020a031681565b600054600160a060020a031633146108b55760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561091a5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60058054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f5b22021f5b1f5f8a744edb1f20f667875f22a1b29c4d9a46418ee25110c76cb89181900360200190a150565b60008061098661069d565b600160a060020a0316630178b8bf846040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1580156109ef57600080fd5b505af1158015610a03573d6000803e3d6000fd5b505050506040513d6020811015610a1957600080fd5b5051604080517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018690529051919250600160a060020a03831691633b3b57de916024808201926020929091908290030181600087803b158015610a8157600080fd5b505af1158015610a95573d6000803e3d6000fd5b505050506040513d6020811015610aab57600080fd5b50519392505050565b600054600160a060020a03163314610b1b5760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0381161515610b805760408051600080516020611834833981519152815260206004820152601860248201527f41646472657373206d757374206e6f74206265206e756c6c0000000000000000604482015290519081900360640190fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038316908117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b600654600160a060020a031681565b33600090815260016020819052604082205482916060918291849160ff16151514610c5e5760408051600080516020611834833981519152815260206004820152601260248201527f4d3a204d757374206265206d616e616765720000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038a161515610cc35760408051600080516020611834833981519152815260206004820152601860248201527f57463a206f776e65722063616e6e6f74206265206e756c6c0000000000000000604482015290519081900360640190fd5b60008811610d465760408051600080516020611834833981519152815260206004820152602960248201527f57463a2063616e6e6f742061737369676e2077697468206c657373207468616e60448201527f2031206d6f64756c650000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6003546040517f6bb18a54000000000000000000000000000000000000000000000000000000008152602060048201818152602483018c9052600160a060020a0390931692636bb18a54928d928d92918291604490910190859085028082843782019150509350505050602060405180830381600087803b158015610dca57600080fd5b505af1158015610dde573d6000803e3d6000fd5b505050506040513d6020811015610df457600080fd5b50511515610e775760408051600080516020611834833981519152815260206004820152602a60248201527f57463a206f6e65206f72206d6f7265206d6f64756c657320617265206e6f742060448201527f7265676973746572656400000000000000000000000000000000000000000000606482015290519081900360840190fd5b600454600160a060020a0316610e8b6116fc565b600160a060020a03909116815260405190819003602001906000f080158015610eb8573d6000803e3d6000fd5b50945084935086868080601f016020809104026020016040519081016040528093929190818152602001838380828437505084519497505092159250611126915050576040805160018a018082526020808202830101909252908015610f28578160200160208202803883390190505b50915030826000815181101515610f3b57fe5b600160a060020a039092166020928302909101909101525060005b87811015610faa57888882818110610f6a57fe5b90506020020135600160a060020a03168282600101815181101515610f8b57fe5b600160a060020a03909216602092830290910190910152600101610f56565b604080517f3c5a3cea000000000000000000000000000000000000000000000000000000008152600160a060020a038c8116600483019081526024830193845285516044840152855191881693633c5a3cea938f9388939291606401906020808601910280838360005b8381101561102c578181015183820152602001611014565b505050509050019350505050600060405180830381600087803b15801561105257600080fd5b505af1158015611066573d6000803e3d6000fd5b505050506110a48488888080601f01602080910402602001604051908101604052809392919081815260200183838082843750611491945050505050565b604080517f1f17732d0000000000000000000000000000000000000000000000000000000081523060048201526000602482018190529151600160a060020a03871692631f17732d926044808201939182900301818387803b15801561110957600080fd5b505af115801561111d573d6000803e3d6000fd5b505050506111c7565b604080517f3c5a3cea000000000000000000000000000000000000000000000000000000008152600160a060020a038c81166004830190815260248301938452604483018c905290871692633c5a3cea928e928e928e926064018460208502808284378201915050945050505050600060405180830381600087803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050505b89600160a060020a031684600160a060020a03167f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f08160405160405180910390a350505050505050505050565b600354600160a060020a031681565b600054600160a060020a031633146112895760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03811615156112ee5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60048054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f06b03978f7966b1fbddfcf29d0c63594e116380be51c99e25506cbc85d5bb1a19181900360200190a150565b600054600160a060020a031633146113b65760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561141b5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60068054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f8bd878c65101d815c50829c7b19270ff5c19e91bd1ad6ebaa282c4a65a5baa5f9181900360200190a150565b60016020526000908152604090205460ff1681565b60055460065460408051600160a060020a03938416602482015291831660448084019190915281518084039091018152606490920190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0f5a546600000000000000000000000000000000000000000000000000000000179052908316638f6f033261152061049e565b6000846040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156115a9578181015183820152602001611591565b50505050905090810190601f1680156115d65780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156115f757600080fd5b505af115801561160b573d6000803e3d6000fd5b5050600554604080517f1e59c529000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660248301526004820192835287516044830152875193169450631e59c529935086928892918291606490910190602086019080838360005b8381101561169257818101518382015260200161167a565b50505050905090810190601f1680156116bf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b50505050505050565b6040516101278061170d833901905600608060405234801561001057600080fd5b50604051602080610127833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905560d6806100516000396000f30060806040523615801560115750600034115b156082573373ffffffffffffffffffffffffffffffffffffffff16347f606834f57405380c4fb88d1f4850326ad3885f014bab3b568dfbf7a041eef7386000366040518080602001828103825284848281815260200192508082843760405192018290039550909350505050a360a8565b6000543660008037600080366000845af43d6000803e80801560a3573d6000f35b3d6000fd5b0000a165627a7a7230582009ad600070879c5d9739059132e69cc1b5b90d2b945f553b3f45ceea43d65c8f002908c379a000000000000000000000000000000000000000000000000000000000a165627a7a723058200bf0893748cb2a7f9392a3642a9ff3b8d7504b0dfa76c21a9a96981c95a65d790029000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105000000000000000000000000b1dd690cc9af7bb1a906a9b5a94f94191cc553ce00000000000000000000000030b406dd3cc461112bcd0dd2a2eaf0641c1a1d62000000000000000000000000da1756bb923af5d1a05e277cb1e54f1d0a127890
Deployed Bytecode
0x6080604052600436106101065763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166308d668bc811461010b57806309d734421461012e57806319ab453c1461015f5780632d06177a146101805780632f680795146101a1578063377e32e6146101b65780635a6971f9146101d75780637cf8a2eb146101ec5780638117abc1146102135780638da5cb5b1461022857806390ed991c1461023d5780639eb869c71461025e578063a6f9dae114610276578063adce1c5f14610297578063aff18575146102ac578063b95459e4146102e5578063c799cd11146102fa578063fb4199991461031b578063fdff9b4d1461033c575b600080fd5b34801561011757600080fd5b5061012c600160a060020a0360043516610371565b005b34801561013a57600080fd5b5061014361049e565b60408051600160a060020a039092168252519081900360200190f35b34801561016b57600080fd5b5061012c600160a060020a036004351661055d565b34801561018c57600080fd5b5061012c600160a060020a0360043516610560565b3480156101ad57600080fd5b5061014361069d565b3480156101c257600080fd5b5061012c600160a060020a03600435166106ac565b3480156101e357600080fd5b506101436107fd565b3480156101f857600080fd5b5061020161080c565b60408051918252519081900360200190f35b34801561021f57600080fd5b50610143610830565b34801561023457600080fd5b5061014361083f565b34801561024957600080fd5b5061012c600160a060020a036004351661084e565b34801561026a57600080fd5b5061014360043561097b565b34801561028257600080fd5b5061012c600160a060020a0360043516610ab4565b3480156102a357600080fd5b50610143610bd5565b3480156102b857600080fd5b5061012c60048035600160a060020a03169060248035808201929081013591604435908101910135610be4565b3480156102f157600080fd5b50610143611213565b34801561030657600080fd5b5061012c600160a060020a0360043516611222565b34801561032757600080fd5b5061012c600160a060020a036004351661134f565b34801561034857600080fd5b5061035d600160a060020a036004351661147c565b604080519115158252519081900360200190f35b600054600160a060020a031633146103d85760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561043d5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60038054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f9bf4baeb20b6008af8dfd7fed5c50dce707a05623b022e5d61a00c7db7f90c729181900360200190a150565b60006104a861069d565b604080517f02571be30000000000000000000000000000000000000000000000000000000081527f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e260048201529051600160a060020a0392909216916302571be3916024808201926020929091908290030181600087803b15801561052c57600080fd5b505af1158015610540573d6000803e3d6000fd5b505050506040513d602081101561055657600080fd5b5051905090565b50565b600054600160a060020a031633146105c75760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561062c5760408051600080516020611834833981519152815260206004820152601b60248201527f4d3a2041646472657373206d757374206e6f74206265206e756c6c0000000000604482015290519081900360640190fd5b600160a060020a03811660009081526001602052604090205460ff16151561055d57600160a060020a0381166000818152600160208190526040808320805460ff1916909217909155517f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a9190a250565b600254600160a060020a031690565b600054600160a060020a031633146107135760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03811660009081526001602081905260409091205460ff161515146107b45760408051600080516020611834833981519152815260206004820152602560248201527f4d3a20546172676574206d75737420626520616e206578697374696e67206d6160448201527f6e61676572000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600160a060020a038116600081815260016020526040808220805460ff19169055517fe5def11e0516f317f9c37b8835aec29fc01db4d4b6d6fecaca339d3596a29bc19190a250565b600554600160a060020a031681565b7f91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e281565b600454600160a060020a031681565b600054600160a060020a031681565b600054600160a060020a031633146108b55760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561091a5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60058054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f5b22021f5b1f5f8a744edb1f20f667875f22a1b29c4d9a46418ee25110c76cb89181900360200190a150565b60008061098661069d565b600160a060020a0316630178b8bf846040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050602060405180830381600087803b1580156109ef57600080fd5b505af1158015610a03573d6000803e3d6000fd5b505050506040513d6020811015610a1957600080fd5b5051604080517f3b3b57de000000000000000000000000000000000000000000000000000000008152600481018690529051919250600160a060020a03831691633b3b57de916024808201926020929091908290030181600087803b158015610a8157600080fd5b505af1158015610a95573d6000803e3d6000fd5b505050506040513d6020811015610aab57600080fd5b50519392505050565b600054600160a060020a03163314610b1b5760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0381161515610b805760408051600080516020611834833981519152815260206004820152601860248201527f41646472657373206d757374206e6f74206265206e756c6c0000000000000000604482015290519081900360640190fd5b6000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038316908117825560405190917fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3691a250565b600654600160a060020a031681565b33600090815260016020819052604082205482916060918291849160ff16151514610c5e5760408051600080516020611834833981519152815260206004820152601260248201527f4d3a204d757374206265206d616e616765720000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038a161515610cc35760408051600080516020611834833981519152815260206004820152601860248201527f57463a206f776e65722063616e6e6f74206265206e756c6c0000000000000000604482015290519081900360640190fd5b60008811610d465760408051600080516020611834833981519152815260206004820152602960248201527f57463a2063616e6e6f742061737369676e2077697468206c657373207468616e60448201527f2031206d6f64756c650000000000000000000000000000000000000000000000606482015290519081900360840190fd5b6003546040517f6bb18a54000000000000000000000000000000000000000000000000000000008152602060048201818152602483018c9052600160a060020a0390931692636bb18a54928d928d92918291604490910190859085028082843782019150509350505050602060405180830381600087803b158015610dca57600080fd5b505af1158015610dde573d6000803e3d6000fd5b505050506040513d6020811015610df457600080fd5b50511515610e775760408051600080516020611834833981519152815260206004820152602a60248201527f57463a206f6e65206f72206d6f7265206d6f64756c657320617265206e6f742060448201527f7265676973746572656400000000000000000000000000000000000000000000606482015290519081900360840190fd5b600454600160a060020a0316610e8b6116fc565b600160a060020a03909116815260405190819003602001906000f080158015610eb8573d6000803e3d6000fd5b50945084935086868080601f016020809104026020016040519081016040528093929190818152602001838380828437505084519497505092159250611126915050576040805160018a018082526020808202830101909252908015610f28578160200160208202803883390190505b50915030826000815181101515610f3b57fe5b600160a060020a039092166020928302909101909101525060005b87811015610faa57888882818110610f6a57fe5b90506020020135600160a060020a03168282600101815181101515610f8b57fe5b600160a060020a03909216602092830290910190910152600101610f56565b604080517f3c5a3cea000000000000000000000000000000000000000000000000000000008152600160a060020a038c8116600483019081526024830193845285516044840152855191881693633c5a3cea938f9388939291606401906020808601910280838360005b8381101561102c578181015183820152602001611014565b505050509050019350505050600060405180830381600087803b15801561105257600080fd5b505af1158015611066573d6000803e3d6000fd5b505050506110a48488888080601f01602080910402602001604051908101604052809392919081815260200183838082843750611491945050505050565b604080517f1f17732d0000000000000000000000000000000000000000000000000000000081523060048201526000602482018190529151600160a060020a03871692631f17732d926044808201939182900301818387803b15801561110957600080fd5b505af115801561111d573d6000803e3d6000fd5b505050506111c7565b604080517f3c5a3cea000000000000000000000000000000000000000000000000000000008152600160a060020a038c81166004830190815260248301938452604483018c905290871692633c5a3cea928e928e928e926064018460208502808284378201915050945050505050600060405180830381600087803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050505b89600160a060020a031684600160a060020a03167f5b03bfed1c14a02bdeceb5fa582eb1a5765fc0bc64ca0e6af4c20afc9487f08160405160405180910390a350505050505050505050565b600354600160a060020a031681565b600054600160a060020a031633146112895760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a03811615156112ee5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60048054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f06b03978f7966b1fbddfcf29d0c63594e116380be51c99e25506cbc85d5bb1a19181900360200190a150565b600054600160a060020a031633146113b65760408051600080516020611834833981519152815260206004820152600d60248201527f4d757374206265206f776e657200000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038116151561141b5760408051600080516020611834833981519152815260206004820152601a60248201527f57463a20616464726573732063616e6e6f74206265206e756c6c000000000000604482015290519081900360640190fd5b60068054600160a060020a03831673ffffffffffffffffffffffffffffffffffffffff19909116811790915560408051918252517f8bd878c65101d815c50829c7b19270ff5c19e91bd1ad6ebaa282c4a65a5baa5f9181900360200190a150565b60016020526000908152604090205460ff1681565b60055460065460408051600160a060020a03938416602482015291831660448084019190915281518084039091018152606490920190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0f5a546600000000000000000000000000000000000000000000000000000000179052908316638f6f033261152061049e565b6000846040518463ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b838110156115a9578181015183820152602001611591565b50505050905090810190601f1680156115d65780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b1580156115f757600080fd5b505af115801561160b573d6000803e3d6000fd5b5050600554604080517f1e59c529000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660248301526004820192835287516044830152875193169450631e59c529935086928892918291606490910190602086019080838360005b8381101561169257818101518382015260200161167a565b50505050905090810190601f1680156116bf5780820380516001836020036101000a031916815260200191505b509350505050600060405180830381600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b50505050505050565b6040516101278061170d833901905600608060405234801561001057600080fd5b50604051602080610127833981016040525160008054600160a060020a03909216600160a060020a031990921691909117905560d6806100516000396000f30060806040523615801560115750600034115b156082573373ffffffffffffffffffffffffffffffffffffffff16347f606834f57405380c4fb88d1f4850326ad3885f014bab3b568dfbf7a041eef7386000366040518080602001828103825284848281815260200192508082843760405192018290039550909350505050a360a8565b6000543660008037600080366000845af43d6000803e80801560a3573d6000f35b3d6000fd5b0000a165627a7a7230582009ad600070879c5d9739059132e69cc1b5b90d2b945f553b3f45ceea43d65c8f002908c379a000000000000000000000000000000000000000000000000000000000a165627a7a723058200bf0893748cb2a7f9392a3642a9ff3b8d7504b0dfa76c21a9a96981c95a65d790029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105000000000000000000000000b1dd690cc9af7bb1a906a9b5a94f94191cc553ce00000000000000000000000030b406dd3cc461112bcd0dd2a2eaf0641c1a1d62000000000000000000000000da1756bb923af5d1a05e277cb1e54f1d0a127890
-----Decoded View---------------
Arg [0] : _ensRegistry (address): 0x314159265dD8dbb310642f98f50C066173C1259b
Arg [1] : _moduleRegistry (address): 0xc17D432Bd8e8850Fd7b32B0270f5AfAc65DB0105
Arg [2] : _walletImplementation (address): 0xB1dD690Cc9AF7BB1a906A9B5A94F94191cc553Ce
Arg [3] : _ensManager (address): 0x30B406DD3Cc461112bCD0DD2a2EaF0641c1a1d62
Arg [4] : _ensResolver (address): 0xDa1756Bb923Af5d1a05E277CB1E54f1D0A127890
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000314159265dd8dbb310642f98f50c066173c1259b
Arg [1] : 000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105
Arg [2] : 000000000000000000000000b1dd690cc9af7bb1a906a9b5a94f94191cc553ce
Arg [3] : 00000000000000000000000030b406dd3cc461112bcd0dd2a2eaf0641c1a1d62
Arg [4] : 000000000000000000000000da1756bb923af5d1a05e277cb1e54f1d0a127890
Swarm Source
bzzr://0bf0893748cb2a7f9392a3642a9ff3b8d7504b0dfa76c21a9a96981c95a65d79
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.