false
false
0

Contract Address Details

0x85A23a07b674dEf0C509cdfb6c6f6005fC79eB14

Contract Name
MultisigWallet
Creator
0xc7d98c–7f3521 at 0xab1f4f–479b43
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
16289166
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
MultisigWallet




Optimization enabled
true
Compiler version
v0.8.18+commit.87f61d96




Optimization runs
200
EVM Version
default




Verified at
2024-09-26T15:33:21.197494Z

Constructor Arguments

0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000ba96f0c205d382407bd3e6385dd6a3735dd0589000000000000000000000000088636732ffc13f626ac9a6de7c6a1741a307e7c30000000000000000000000008dd282fd271fcc23d6b04a5cb8b1293865083d07
              

Contract source code

// SPDX-License-Identifier: No License (None)
pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256`
 * (`UintSet`) are supported.
 */
library EnumerableSet {

    struct AddressSet {
        // Storage of set values
        address[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (address => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        if (!contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            address lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Replace a current value from a set with the new value.
     *
     * Returns true if the value was replaced, and false if newValue already in set or currentValue is not in set
     */
    function replace(AddressSet storage set, address currentValue, address newValue) internal returns (bool) {
        uint256 currentIndex = set._indexes[currentValue];
        if (contains(set, newValue) || currentIndex == 0) {
            return false;
        } else {
            set._values[currentIndex - 1] = newValue;
            set._indexes[newValue] = currentIndex;
            delete set._indexes[currentValue];
            return true;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns 1-based index of value in the set. O(1).
     */
    function indexOf(AddressSet storage set, address value) internal view returns (uint256) {
        return set._indexes[value];
    }


    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }
}

contract MultisigWallet {
    using EnumerableSet for EnumerableSet.AddressSet;
    struct Ballot {
        uint128 votes;      // bitmap of unique votes (max 127 votes)
        uint64 expire;      // time when ballot expire
        uint8 yea;          // number of votes `Yea`
    }

    EnumerableSet.AddressSet owners; // founders may transfer contract's ownership
    uint256 public ownersSetCounter;   // each time when change owners increase the counter
    uint256 public expirePeriod = 3 days;
    mapping(bytes32 => Ballot) public ballots;
    uint256 public minRequired; // minimum voters required to approve. If 0 then required 50% + 1 vote.
 
    event SetOwner(address owner, bool isEnable);
    event CreateBallot(bytes32 ballotHash, uint256 expired);
    event Execute(bytes32 ballotHash, address to, uint256 value, bytes data);


    modifier onlyThis() {
        require(address(this) == msg.sender, "Only multisig allowed");
        _;
    }
    
    // add list of owners and minimum voters required to approve (if 0 then required 50% + 1 vote).
    constructor (address[] memory _owners, uint256 _minRequired) {
        for (uint i = 0; i < _owners.length; i++) {
            require(_owners[i] != address(0), "Zero address");
            owners.add(_owners[i]);
        }
        require(_minRequired <= owners.length(), "_minRequired too big");
        minRequired = _minRequired;
    }

    // get number of owners
    function getOwnersNumber() external view returns(uint256) {
        return owners.length();
    }

    // returns list of owners addresses
    function getOwners() external view returns(address[] memory) {
        return owners._values;
    }

    // add owner
    function addOwner(address owner) external onlyThis{
        require(owner != address(0), "Zero address");
        require(owners.length() < 127, "Too many owners");
        require(owners.add(owner), "Owner already added");
        ownersSetCounter++; // change owners set
        emit SetOwner(owner, true);
    }

    // remove owner
    function removeOwner(address owner) external onlyThis{
        require(owners.length() > 1, "Remove all owners is not allowed");
        require(owners.remove(owner), "Owner does not exist");
        ownersSetCounter++; // change owners set
        emit SetOwner(owner, false);
    }
    
    // change owner address
    function changeOwnerAddress(address currentAddress, address newAddress) external onlyThis{
        require(newAddress != address(0), "Zero address");
        require(owners.replace(currentAddress, newAddress), "currentAddress does not exist or newAddress already exist");
        emit SetOwner(currentAddress, false);
        emit SetOwner(newAddress, true);
    }

    // set minimum voters required to approve (if 0 then required 50% + 1 vote).
    function setMinRequired(uint256 _minRequired) external onlyThis{
        require(_minRequired <= owners.length(), "_minRequired too big");
        minRequired = _minRequired;
    }

    function setExpirePeriod(uint256 period) external onlyThis {
        require(period >= 1 days, "Too short period");  // avoid deadlock in case of set too short period
        expirePeriod = period;
    }

    function vote(address to, uint256 value, bytes calldata data) external {
        uint256 index = owners.indexOf(msg.sender);
        require(index != 0, "Only owner");
        bytes32 ballotHash = keccak256(abi.encodePacked(to, value, data, ownersSetCounter));
        Ballot memory b = ballots[ballotHash];
        if (b.expire == 0 || b.expire < uint64(block.timestamp)) { // if no ballot or ballot expired - create new ballot
            b.expire = uint64(block.timestamp + expirePeriod);
            b.votes = 0;
            b.yea = 0;
            emit CreateBallot(ballotHash, b.expire);
        }
        uint256 mask = 1 << index;
        if (b.votes & mask == 0) {  // this owner don't vote yet.
            b.votes = uint128(b.votes | mask); // record owner's vote
            b.yea += 1; // increase total votes "Yea"
        }

        if (isApproved(b.yea)) {   
            delete ballots[ballotHash];
            execute(to, value, data);
            emit Execute(ballotHash, to, value, data);
        } else {
            // update ballot
            ballots[ballotHash] = b;
        }
    }

    function isApproved(uint256 votesYea) internal view returns(bool) {
        // use local variables to save gas
        uint256 _minRequired = minRequired;
        uint256 _ownersLength = owners.length();
        if (_minRequired == 0 || _minRequired > _ownersLength) { // to avoid deadlock minRequired can't be bigger than number of owners.
            return (votesYea >= _ownersLength / 2 + 1); // vote "Yea" > 50% of owners
        } else {
            return (votesYea >= _minRequired); // vote "Yea" >= minimum required
        }
    }

    function execute(address to, uint256 value, bytes memory data) internal {
        (bool success,) = to.call{value: value}(data);
        require(success, "Execute error");
    }

    // allow receive ERC223 tokens
    function tokenReceived(address _from, uint _value, bytes calldata _data) external {} 
    // allow receive ERC721 tokens (NFT)
    function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external pure returns(bytes4) {
        return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
    }
    // allow receive coin
    receive() external payable {}
}
        

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_minRequired","internalType":"uint256"}]},{"type":"event","name":"CreateBallot","inputs":[{"type":"bytes32","name":"ballotHash","internalType":"bytes32","indexed":false},{"type":"uint256","name":"expired","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Execute","inputs":[{"type":"bytes32","name":"ballotHash","internalType":"bytes32","indexed":false},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"SetOwner","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":false},{"type":"bool","name":"isEnable","internalType":"bool","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint128","name":"votes","internalType":"uint128"},{"type":"uint64","name":"expire","internalType":"uint64"},{"type":"uint8","name":"yea","internalType":"uint8"}],"name":"ballots","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeOwnerAddress","inputs":[{"type":"address","name":"currentAddress","internalType":"address"},{"type":"address","name":"newAddress","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"expirePeriod","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOwners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getOwnersNumber","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minRequired","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"onERC721Received","inputs":[{"type":"address","name":"_operator","internalType":"address"},{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_tokenId","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"ownersSetCounter","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setExpirePeriod","inputs":[{"type":"uint256","name":"period","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinRequired","inputs":[{"type":"uint256","name":"_minRequired","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"tokenReceived","inputs":[{"type":"address","name":"_from","internalType":"address"},{"type":"uint256","name":"_value","internalType":"uint256"},{"type":"bytes","name":"_data","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vote","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

Verify & Publish
0x60806040526203f4806003553480156200001857600080fd5b5060405162001558380380620015588339810160408190526200003b9162000228565b60005b8251811015620001085760006001600160a01b031683828151811062000068576200006862000302565b60200260200101516001600160a01b031603620000bb5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b60448201526064015b60405180910390fd5b620000f2838281518110620000d457620000d462000302565b602002602001015160006200017b60201b62000adb1790919060201c565b5080620000ff8162000318565b9150506200003e565b50620001206000620001f160201b62000b4f1760201c565b811115620001715760405162461bcd60e51b815260206004820152601460248201527f5f6d696e526571756972656420746f6f206269670000000000000000000000006044820152606401620000b2565b6005555062000340565b6001600160a01b0381166000908152600183016020526040812054620001e757508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155620001eb565b5060005b92915050565b5490565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200022357600080fd5b919050565b600080604083850312156200023c57600080fd5b82516001600160401b03808211156200025457600080fd5b818501915085601f8301126200026957600080fd5b8151602082821115620002805762000280620001f5565b8160051b604051601f19603f83011681018181108682111715620002a857620002a8620001f5565b604052928352818301935084810182019289841115620002c757600080fd5b948201945b83861015620002f057620002e0866200020b565b85529482019493820193620002cc565b97909101519698969750505050505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200033957634e487b7160e01b600052601160045260246000fd5b5060010190565b61120880620003506000396000f3fe6080604052600436106100e15760003560e01c80637dd0dd161161007f5780638943ec02116100595780638943ec02146102bc578063a0e67e2b146102dd578063c1d74a4c146102ff578063d7a52fa91461031f57600080fd5b80637dd0dd16146102025780638638fb5a1461028757806386cbaed81461029c57600080fd5b8063173825d9116100bb578063173825d91461018a57806321407e53146101ac5780632203d796146101c25780637065cb48146101e257600080fd5b806313e26d58146100ed578063150b7a0214610116578063163d262f1461017457600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010360055481565b6040519081526020015b60405180910390f35b34801561012257600080fd5b5061015b610131366004610e98565b7f150b7a023d4804d13e8c85fb27262cb750cf6ba9f9dd3bb30d90f482ceeb4b1f95945050505050565b6040516001600160e01b0319909116815260200161010d565b34801561018057600080fd5b5061010360025481565b34801561019657600080fd5b506101aa6101a5366004610f07565b61033f565b005b3480156101b857600080fd5b5061010360035481565b3480156101ce57600080fd5b506101aa6101dd366004610f22565b610456565b3480156101ee57600080fd5b506101aa6101fd366004610f07565b6104c3565b34801561020e57600080fd5b5061025661021d366004610f22565b6004602052600090815260409020546001600160801b03811690600160801b810467ffffffffffffffff1690600160c01b900460ff1683565b604080516001600160801b03909416845267ffffffffffffffff909216602084015260ff169082015260600161010d565b34801561029357600080fd5b50600054610103565b3480156102a857600080fd5b506101aa6102b7366004610f3b565b610600565b3480156102c857600080fd5b506101aa6102d7366004610f3b565b50505050565b3480156102e957600080fd5b506102f26108c7565b60405161010d9190610f95565b34801561030b57600080fd5b506101aa61031a366004610fe2565b61092b565b34801561032b57600080fd5b506101aa61033a366004610f22565b610a71565b3033146103675760405162461bcd60e51b815260040161035e90611015565b60405180910390fd5b600161037260005490565b116103bf5760405162461bcd60e51b815260206004820181905260248201527f52656d6f766520616c6c206f776e657273206973206e6f7420616c6c6f776564604482015260640161035e565b6103ca600082610b53565b61040d5760405162461bcd60e51b815260206004820152601460248201527313dddb995c88191bd95cc81b9bdd08195e1a5cdd60621b604482015260640161035e565b6002805490600061041d8361105a565b9091555050604080516001600160a01b0383168152600060208201526000805160206111b383398151915291015b60405180910390a150565b3033146104755760405162461bcd60e51b815260040161035e90611015565b6000548111156104be5760405162461bcd60e51b81526020600482015260146024820152735f6d696e526571756972656420746f6f2062696760601b604482015260640161035e565b600555565b3033146104e25760405162461bcd60e51b815260040161035e90611015565b6001600160a01b0381166105275760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b604482015260640161035e565b607f61053260005490565b106105715760405162461bcd60e51b815260206004820152600f60248201526e546f6f206d616e79206f776e65727360881b604482015260640161035e565b61057c600082610adb565b6105be5760405162461bcd60e51b815260206004820152601360248201527213dddb995c88185b1c9958591e481859191959606a1b604482015260640161035e565b600280549060006105ce8361105a565b9091555050604080516001600160a01b0383168152600160208201526000805160206111b3833981519152910161044b565b336000908152600160205260408120549081900361064d5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015260640161035e565b60008585858560025460405160200161066a959493929190611073565b60408051808303601f190181528282528051602091820120600081815260048352839020606085018452546001600160801b0381168552600160801b810467ffffffffffffffff16928501839052600160c01b900460ff169284019290925290925015806106ef57504267ffffffffffffffff16816020015167ffffffffffffffff16105b156107595760035461070190426110a7565b67ffffffffffffffff16602082810182905260008084526040808501919091528051858152918201929092527fdba396e3f86ba92c12e944cda2d787eea52a24f6babcbd54c8ffb2d369bca7c9910160405180910390a15b80516001841b9081166001600160801b03166000036107a05781516001600160801b038083169116178252604082018051600191906107999083906110ba565b60ff169052505b6107b0826040015160ff16610c95565b156108575760008381526004602090815260409182902080546001600160c81b03191690558151601f8801829004820281018201909252868252610813918a918a91908a908a9081908401838280828437600092019190915250610ce292505050565b7fc75495e0be082158e5855c35d211235055bf668ec3933eb9f3cf757c6493ee6d838989898960405161084a9594939291906110d3565b60405180910390a16108bd565b60008381526004602090815260409182902084518154928601519386015160ff16600160c01b0260ff60c01b1967ffffffffffffffff909516600160801b026001600160c01b03199094166001600160801b039092169190911792909217929092161790555b5050505050505050565b60606000800180548060200260200160405190810160405280929190818152602001828054801561092157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610903575b5050505050905090565b30331461094a5760405162461bcd60e51b815260040161035e90611015565b6001600160a01b03811661098f5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b604482015260640161035e565b61099b60008383610d80565b610a0d5760405162461bcd60e51b815260206004820152603960248201527f63757272656e744164647265737320646f6573206e6f74206578697374206f7260448201527f206e65774164647265737320616c726561647920657869737400000000000000606482015260840161035e565b604080516001600160a01b0384168152600060208201526000805160206111b3833981519152910160405180910390a1604080516001600160a01b0383168152600160208201526000805160206111b3833981519152910160405180910390a15050565b303314610a905760405162461bcd60e51b815260040161035e90611015565b62015180811015610ad65760405162461bcd60e51b815260206004820152601060248201526f151bdbc81cda1bdc9d081c195c9a5bd960821b604482015260640161035e565b600355565b6001600160a01b0381166000908152600183016020526040812054610b4557508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155610b49565b5060005b92915050565b5490565b6001600160a01b03811660009081526001830160205260408120548015610c8b576000610b81600183611122565b8554909150600090610b9590600190611122565b90506000866000018281548110610bae57610bae611135565b60009182526020909120015487546001600160a01b0390911691508190889085908110610bdd57610bdd611135565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055610c118360016110a7565b6001600160a01b03821660009081526001890160205260409020558654879080610c3d57610c3d61114b565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450610b499350505050565b6000915050610b49565b60055460009081610ca4815490565b9050811580610cb257508082115b15610cd857610cc2600282611161565b610ccd9060016110a7565b909310159392505050565b5090911015919050565b6000836001600160a01b03168383604051610cfd9190611183565b60006040518083038185875af1925050503d8060008114610d3a576040519150601f19603f3d011682016040523d82523d6000602084013e610d3f565b606091505b50509050806102d75760405162461bcd60e51b815260206004820152600d60248201526c22bc32b1baba329032b93937b960991b604482015260640161035e565b6001600160a01b038281166000908152600185016020526040808220549284168252812054909190151580610db3575080155b15610dc2576000915050610e2c565b8285610dcf600184611122565b81548110610ddf57610ddf611135565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790558583168252600188810190915260408083209490945591861681529182209190915590505b9392505050565b80356001600160a01b0381168114610e4a57600080fd5b919050565b60008083601f840112610e6157600080fd5b50813567ffffffffffffffff811115610e7957600080fd5b602083019150836020828501011115610e9157600080fd5b9250929050565b600080600080600060808688031215610eb057600080fd5b610eb986610e33565b9450610ec760208701610e33565b935060408601359250606086013567ffffffffffffffff811115610eea57600080fd5b610ef688828901610e4f565b969995985093965092949392505050565b600060208284031215610f1957600080fd5b610e2c82610e33565b600060208284031215610f3457600080fd5b5035919050565b60008060008060608587031215610f5157600080fd5b610f5a85610e33565b935060208501359250604085013567ffffffffffffffff811115610f7d57600080fd5b610f8987828801610e4f565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015610fd65783516001600160a01b031683529284019291840191600101610fb1565b50909695505050505050565b60008060408385031215610ff557600080fd5b610ffe83610e33565b915061100c60208401610e33565b90509250929050565b60208082526015908201527413db9b1e481b5d5b1d1a5cda59c8185b1b1bddd959605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60006001820161106c5761106c611044565b5060010190565b6bffffffffffffffffffffffff198660601b1681528460148201528284603483013760349201918201526054019392505050565b80820180821115610b4957610b49611044565b60ff8181168382160190811115610b4957610b49611044565b8581526001600160a01b0385166020820152604081018490526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b81810381811115610b4957610b49611044565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60008261117e57634e487b7160e01b600052601260045260246000fd5b500490565b6000825160005b818110156111a4576020818601810151858301520161118a565b50600092019182525091905056fe5501576e82029b0850ec7c74ac25b5a46839bf523772a6ac579cc55b092281c8a26469706673582212209552de418fc0b643d306ed2bd129a8e50a7106e6a0cde5953546fa2a6446ee4b64736f6c63430008120033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000ba96f0c205d382407bd3e6385dd6a3735dd0589000000000000000000000000088636732ffc13f626ac9a6de7c6a1741a307e7c30000000000000000000000008dd282fd271fcc23d6b04a5cb8b1293865083d07

Deployed ByteCode

0x6080604052600436106100e15760003560e01c80637dd0dd161161007f5780638943ec02116100595780638943ec02146102bc578063a0e67e2b146102dd578063c1d74a4c146102ff578063d7a52fa91461031f57600080fd5b80637dd0dd16146102025780638638fb5a1461028757806386cbaed81461029c57600080fd5b8063173825d9116100bb578063173825d91461018a57806321407e53146101ac5780632203d796146101c25780637065cb48146101e257600080fd5b806313e26d58146100ed578063150b7a0214610116578063163d262f1461017457600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010360055481565b6040519081526020015b60405180910390f35b34801561012257600080fd5b5061015b610131366004610e98565b7f150b7a023d4804d13e8c85fb27262cb750cf6ba9f9dd3bb30d90f482ceeb4b1f95945050505050565b6040516001600160e01b0319909116815260200161010d565b34801561018057600080fd5b5061010360025481565b34801561019657600080fd5b506101aa6101a5366004610f07565b61033f565b005b3480156101b857600080fd5b5061010360035481565b3480156101ce57600080fd5b506101aa6101dd366004610f22565b610456565b3480156101ee57600080fd5b506101aa6101fd366004610f07565b6104c3565b34801561020e57600080fd5b5061025661021d366004610f22565b6004602052600090815260409020546001600160801b03811690600160801b810467ffffffffffffffff1690600160c01b900460ff1683565b604080516001600160801b03909416845267ffffffffffffffff909216602084015260ff169082015260600161010d565b34801561029357600080fd5b50600054610103565b3480156102a857600080fd5b506101aa6102b7366004610f3b565b610600565b3480156102c857600080fd5b506101aa6102d7366004610f3b565b50505050565b3480156102e957600080fd5b506102f26108c7565b60405161010d9190610f95565b34801561030b57600080fd5b506101aa61031a366004610fe2565b61092b565b34801561032b57600080fd5b506101aa61033a366004610f22565b610a71565b3033146103675760405162461bcd60e51b815260040161035e90611015565b60405180910390fd5b600161037260005490565b116103bf5760405162461bcd60e51b815260206004820181905260248201527f52656d6f766520616c6c206f776e657273206973206e6f7420616c6c6f776564604482015260640161035e565b6103ca600082610b53565b61040d5760405162461bcd60e51b815260206004820152601460248201527313dddb995c88191bd95cc81b9bdd08195e1a5cdd60621b604482015260640161035e565b6002805490600061041d8361105a565b9091555050604080516001600160a01b0383168152600060208201526000805160206111b383398151915291015b60405180910390a150565b3033146104755760405162461bcd60e51b815260040161035e90611015565b6000548111156104be5760405162461bcd60e51b81526020600482015260146024820152735f6d696e526571756972656420746f6f2062696760601b604482015260640161035e565b600555565b3033146104e25760405162461bcd60e51b815260040161035e90611015565b6001600160a01b0381166105275760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b604482015260640161035e565b607f61053260005490565b106105715760405162461bcd60e51b815260206004820152600f60248201526e546f6f206d616e79206f776e65727360881b604482015260640161035e565b61057c600082610adb565b6105be5760405162461bcd60e51b815260206004820152601360248201527213dddb995c88185b1c9958591e481859191959606a1b604482015260640161035e565b600280549060006105ce8361105a565b9091555050604080516001600160a01b0383168152600160208201526000805160206111b3833981519152910161044b565b336000908152600160205260408120549081900361064d5760405162461bcd60e51b815260206004820152600a60248201526927b7363c9037bbb732b960b11b604482015260640161035e565b60008585858560025460405160200161066a959493929190611073565b60408051808303601f190181528282528051602091820120600081815260048352839020606085018452546001600160801b0381168552600160801b810467ffffffffffffffff16928501839052600160c01b900460ff169284019290925290925015806106ef57504267ffffffffffffffff16816020015167ffffffffffffffff16105b156107595760035461070190426110a7565b67ffffffffffffffff16602082810182905260008084526040808501919091528051858152918201929092527fdba396e3f86ba92c12e944cda2d787eea52a24f6babcbd54c8ffb2d369bca7c9910160405180910390a15b80516001841b9081166001600160801b03166000036107a05781516001600160801b038083169116178252604082018051600191906107999083906110ba565b60ff169052505b6107b0826040015160ff16610c95565b156108575760008381526004602090815260409182902080546001600160c81b03191690558151601f8801829004820281018201909252868252610813918a918a91908a908a9081908401838280828437600092019190915250610ce292505050565b7fc75495e0be082158e5855c35d211235055bf668ec3933eb9f3cf757c6493ee6d838989898960405161084a9594939291906110d3565b60405180910390a16108bd565b60008381526004602090815260409182902084518154928601519386015160ff16600160c01b0260ff60c01b1967ffffffffffffffff909516600160801b026001600160c01b03199094166001600160801b039092169190911792909217929092161790555b5050505050505050565b60606000800180548060200260200160405190810160405280929190818152602001828054801561092157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610903575b5050505050905090565b30331461094a5760405162461bcd60e51b815260040161035e90611015565b6001600160a01b03811661098f5760405162461bcd60e51b815260206004820152600c60248201526b5a65726f206164647265737360a01b604482015260640161035e565b61099b60008383610d80565b610a0d5760405162461bcd60e51b815260206004820152603960248201527f63757272656e744164647265737320646f6573206e6f74206578697374206f7260448201527f206e65774164647265737320616c726561647920657869737400000000000000606482015260840161035e565b604080516001600160a01b0384168152600060208201526000805160206111b3833981519152910160405180910390a1604080516001600160a01b0383168152600160208201526000805160206111b3833981519152910160405180910390a15050565b303314610a905760405162461bcd60e51b815260040161035e90611015565b62015180811015610ad65760405162461bcd60e51b815260206004820152601060248201526f151bdbc81cda1bdc9d081c195c9a5bd960821b604482015260640161035e565b600355565b6001600160a01b0381166000908152600183016020526040812054610b4557508154600180820184556000848152602080822090930180546001600160a01b0319166001600160a01b03861690811790915585549082528286019093526040902091909155610b49565b5060005b92915050565b5490565b6001600160a01b03811660009081526001830160205260408120548015610c8b576000610b81600183611122565b8554909150600090610b9590600190611122565b90506000866000018281548110610bae57610bae611135565b60009182526020909120015487546001600160a01b0390911691508190889085908110610bdd57610bdd611135565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055610c118360016110a7565b6001600160a01b03821660009081526001890160205260409020558654879080610c3d57610c3d61114b565b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b0388168252600189810190915260408220919091559450610b499350505050565b6000915050610b49565b60055460009081610ca4815490565b9050811580610cb257508082115b15610cd857610cc2600282611161565b610ccd9060016110a7565b909310159392505050565b5090911015919050565b6000836001600160a01b03168383604051610cfd9190611183565b60006040518083038185875af1925050503d8060008114610d3a576040519150601f19603f3d011682016040523d82523d6000602084013e610d3f565b606091505b50509050806102d75760405162461bcd60e51b815260206004820152600d60248201526c22bc32b1baba329032b93937b960991b604482015260640161035e565b6001600160a01b038281166000908152600185016020526040808220549284168252812054909190151580610db3575080155b15610dc2576000915050610e2c565b8285610dcf600184611122565b81548110610ddf57610ddf611135565b600091825260208083209190910180546001600160a01b0319166001600160a01b039485161790558583168252600188810190915260408083209490945591861681529182209190915590505b9392505050565b80356001600160a01b0381168114610e4a57600080fd5b919050565b60008083601f840112610e6157600080fd5b50813567ffffffffffffffff811115610e7957600080fd5b602083019150836020828501011115610e9157600080fd5b9250929050565b600080600080600060808688031215610eb057600080fd5b610eb986610e33565b9450610ec760208701610e33565b935060408601359250606086013567ffffffffffffffff811115610eea57600080fd5b610ef688828901610e4f565b969995985093965092949392505050565b600060208284031215610f1957600080fd5b610e2c82610e33565b600060208284031215610f3457600080fd5b5035919050565b60008060008060608587031215610f5157600080fd5b610f5a85610e33565b935060208501359250604085013567ffffffffffffffff811115610f7d57600080fd5b610f8987828801610e4f565b95989497509550505050565b6020808252825182820181905260009190848201906040850190845b81811015610fd65783516001600160a01b031683529284019291840191600101610fb1565b50909695505050505050565b60008060408385031215610ff557600080fd5b610ffe83610e33565b915061100c60208401610e33565b90509250929050565b60208082526015908201527413db9b1e481b5d5b1d1a5cda59c8185b1b1bddd959605a1b604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60006001820161106c5761106c611044565b5060010190565b6bffffffffffffffffffffffff198660601b1681528460148201528284603483013760349201918201526054019392505050565b80820180821115610b4957610b49611044565b60ff8181168382160190811115610b4957610b49611044565b8581526001600160a01b0385166020820152604081018490526080606082018190528101829052818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b81810381811115610b4957610b49611044565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60008261117e57634e487b7160e01b600052601260045260246000fd5b500490565b6000825160005b818110156111a4576020818601810151858301520161118a565b50600092019182525091905056fe5501576e82029b0850ec7c74ac25b5a46839bf523772a6ac579cc55b092281c8a26469706673582212209552de418fc0b643d306ed2bd129a8e50a7106e6a0cde5953546fa2a6446ee4b64736f6c63430008120033