Contract Address Details

0xA845C2f516013A7687D4b8bE52393f6E3ef75F00

Contract Name
Relay
Creator
0xe3bb74–93e799 at 0x24ebf3–13eefd
Balance
0.000011 CHZ ( )
Tokens
Fetching tokens...
Transactions
9 Transactions
Transfers
0 Transfers
Gas Used
1,068,497
Last Balance Update
8957157
Contract name:
Relay




Optimization enabled
true
Compiler version
v0.8.9+commit.e5eed63a




Optimization runs
200
EVM Version
default




Verified at
2023-11-19T02:09:10.539438Z

Constructor Arguments

0x000000000000000000000000e3bb74c0a5feb080c38621c3ddec96288393e799

Arg [0] (address) : 0xe3bb74c0a5feb080c38621c3ddec96288393e799

              

Relay.sol

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

import "./Types.sol";

contract Relay is Types {
    /// @dev Current set of business clients
    mapping(address => bool) public isBusiness;
    address[] public businesses;

    /// @dev Not yet added business clients
    address[] public pendingBusinesses;

    /// @dev Current set of managers
    mapping(address => bool) public isManager;
    address[] public managers;

    /// @dev Rewards the relay received for operations
    uint256 public rewards;

    /// @dev Current set of charity clients
    mapping(address => bool) public isCharity;
    address[] public charities;

    /// @dev Not yet added charity clients
    address[] public pendingCharities;

    uint256 public transactionsCount;

    mapping(uint256 => Transaction) public transactions;
    mapping(address => uint256[]) public clientToTransaction;

    event CharityApproved(
        address indexed charity
    );

    event PendingCharityAdded(
        address indexed charity
    );

    event CharityRemoved(
        address indexed charity
    );

    event BusinessApproved(
        address indexed business
    );

    event PendingBusinessAdded(
        address indexed charity
    );

    event BusinessRemoved(
        address indexed business
    );

    event ManagerAdded(
        address indexed manager
    );

    event TransactionAdded(
        uint256 indexed transactionId,
        address indexed business
    );

    event TransactionPaid(
        uint256 indexed transactionId,
        address indexed business
    );

    event Withdrawal(
        uint256 amount,
        address indexed manager
    );

    constructor(address manager) {
        isManager[manager] = true;
    }

    /// businesses management
    function addNewBusiness(address business) public {
        for (uint256 i = 0; i < pendingBusinesses.length; i++) {
            if (pendingBusinesses[i] == business) {
                revert("The business address is already pending");
            }
        }

        pendingBusinesses.push(business);
        emit PendingBusinessAdded(business);
    }

    function approveBusiness(address business) public onlyManager {
        if (isBusiness[business]) {
            return;
        }

        isBusiness[business] = true;
        businesses.push(business);

        emit BusinessApproved(business);

        if (pendingBusinesses.length == 0) {
            return;
        }

        for (uint256 i = 0; i < pendingBusinesses.length; i++) {
            if (pendingBusinesses[i] == business) {
                if (i != pendingBusinesses.length - 1) {
                    pendingBusinesses[i] = pendingBusinesses[pendingBusinesses.length - 1];
                }
                delete pendingBusinesses[pendingBusinesses.length - 1];
                break;
            }
        }
    }

    function removeBusiness(address business) public onlyManager {
        isBusiness[business] = false;

        emit BusinessRemoved(business);

        if (businesses.length == 0) {
            return;
        }

        for (uint256 i = 0; i < businesses.length; i++) {
            if (businesses[i] == business) {
                if (i != businesses.length - 1) {
                    businesses[i] = businesses[businesses.length - 1];
                }
                delete businesses[businesses.length - 1];
                break;
            }
        }
    }

    /// charities management
    function addNewCharity(address charity) public {
        for (uint256 i = 0; i < pendingCharities.length; i++) {
            if (pendingCharities[i] == charity) {
                revert("The charity address is already pending");
            }
        }

        pendingCharities.push(charity);
        emit PendingCharityAdded(charity);
    }

    function approveCharity(address charity) public onlyManager {
        if (isCharity[charity]) {
            return;
        }

        isCharity[charity] = true;
        charities.push(charity);

        emit CharityApproved(charity);

        if (pendingCharities.length == 0) {
            return;
        }

        for (uint256 i = 0; i < pendingCharities.length; i++) {
            if (pendingCharities[i] == charity) {
                if (i != pendingCharities.length - 1) {
                    pendingCharities[i] = pendingCharities[pendingCharities.length - 1];
                }
                delete pendingCharities[pendingCharities.length - 1];
                break;
            }
        }
    }

    function removeCharity(address charity) public onlyManager {
        isCharity[charity] = false;
        emit CharityRemoved(charity);

        if (charities.length == 0) {
            return;
        }

        for (uint256 i = 0; i < charities.length; i++) {
            if (charities[i] == charity) {
                if (i != charities.length - 1) {
                    charities[i] = charities[charities.length - 1];
                }
                delete charities[charities.length - 1];
                break;
            }
        }
    }

    /// manager management
    function addManager(address manager) public onlyManager {
        isManager[manager] = true;
        managers.push(manager);
        emit ManagerAdded(manager);
    }

    function pendingTransactions(
        address client
    ) public view returns (Transaction[] memory, uint256[] memory) {
        uint256 clientTransactions = clientToTransaction[client].length;
        Transaction[] memory returnTransactions = new Transaction[](clientTransactions);
        uint256[] memory returnTransactionsIds = new uint256[](clientTransactions);
        for (uint256 i = 0; i < clientTransactions; i++) {
            returnTransactionsIds[i] = clientToTransaction[client][i];
            returnTransactions[i] = transactions[returnTransactionsIds[i]];
        }
        return (returnTransactions, returnTransactionsIds);
    }

    function generateTransaction(
        address client,
        TransactionPiece[] memory pieces,
        uint256 fee
    ) public onlyManager {
        require(pieces.length > 0, "Charities are empty");
        require(isBusiness[client], "Client is not our client");

        transactions[transactionsCount].client = client;
        transactions[transactionsCount].fee = fee;
        transactions[transactionsCount].piecesCount = pieces.length;
        transactions[transactionsCount].paid = false;

        for (uint256 i = 0; i < pieces.length; i++) {
            require(isCharity[pieces[i].destination], "One of the destinations is not an approved charity");
            require(pieces[i].value > 0, "Donations should be non-zero");
            transactions[transactionsCount].pieces.push(pieces[i]);
        }

        clientToTransaction[client].push(transactionsCount);

        emit TransactionAdded(transactionsCount, client);
        transactionsCount++;
    }

    function executeTransaction(
        uint256 transactionId
    ) public payable onlyBusiness transactionExists(transactionId) {
        Transaction storage transaction = transactions[transactionId];

        require(transaction.client == msg.sender, "The transaction is for another client");
        require(!transaction.paid, "Transaction is paid already");

        uint256 totalPayment = 0;
        for (uint256 i = 0; i < transaction.piecesCount; i++) {
            totalPayment += transaction.pieces[i].value;
        }

        require(totalPayment + transaction.fee <= msg.value, "The value is not enough to cover the transaction");

        for (uint256 i = 0; i < transaction.piecesCount; i++) {
            _sendFundsTo(transaction.pieces[i].destination, transaction.pieces[i].value);
        }

        transaction.paid = true;
        rewards += msg.value - totalPayment;

        emit TransactionPaid(transactionId, transaction.client);
    }

    function withdraw() public onlyManager {
        require(rewards > 0, "Nothing to withdraw");

        emit Withdrawal(rewards, msg.sender);

        _sendFundsTo(msg.sender, rewards);
        rewards = 0;
    }

    fallback() external payable {}

    receive() external payable {}

    /**
     * @dev Internal function to send excess rewards back to the bridge
     */
    function _sendFundsTo(address to, uint256 _funds) internal {
        (bool sent, ) = to.call{value: _funds}("");

        require(sent, "Failed to send funds");
    }

    modifier onlyManager() {
        if (!isManager[msg.sender]) revert("Sender is not the approved manager");
        _;
    }

    modifier onlyBusiness() {
        if (!isBusiness[msg.sender]) revert("Sender is not the approved business");
        _;
    }

    modifier transactionExists(uint256 transactionId) {
        if (transactions[transactionId].client == address(0))
            revert("Transaction doesn't exist.");
        _;
    }
}
        

Types.sol

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

/// @title Types
/// @dev Source file that keeps type definitions
abstract contract Types {

    /// @dev Charity transaction proposal. For Clients to sign and execute
    struct TransactionPiece {
        address destination;
        uint256 value;
    }

    /// @dev Charity transaction proposal. For Clients to sign and execute
    struct Transaction {
        address client;
        TransactionPiece[] pieces;
        uint256 piecesCount;
        uint256 fee;
        bool paid;
    }
}
          

Contract ABI

[{"type":"constructor","inputs":[{"type":"address","name":"manager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addManager","inputs":[{"type":"address","name":"manager","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addNewBusiness","inputs":[{"type":"address","name":"business","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addNewCharity","inputs":[{"type":"address","name":"charity","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approveBusiness","inputs":[{"type":"address","name":"business","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approveCharity","inputs":[{"type":"address","name":"charity","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"businesses","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"charities","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"clientToTransaction","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"executeTransaction","inputs":[{"type":"uint256","name":"transactionId","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"generateTransaction","inputs":[{"type":"address","name":"client","internalType":"address"},{"type":"tuple[]","name":"pieces","internalType":"struct Types.TransactionPiece[]","components":[{"type":"address"},{"type":"uint256"}]},{"type":"uint256","name":"fee","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBusiness","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isCharity","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isManager","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"managers","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingBusinesses","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingCharities","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"","internalType":"struct Types.Transaction[]","components":[{"type":"address"},{"type":"tuple[]","components":[{"type":"address"},{"type":"uint256"}]},{"type":"uint256"},{"type":"uint256"},{"type":"bool"}]},{"type":"uint256[]","name":"","internalType":"uint256[]"}],"name":"pendingTransactions","inputs":[{"type":"address","name":"client","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeBusiness","inputs":[{"type":"address","name":"business","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeCharity","inputs":[{"type":"address","name":"charity","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewards","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"client","internalType":"address"},{"type":"uint256","name":"piecesCount","internalType":"uint256"},{"type":"uint256","name":"fee","internalType":"uint256"},{"type":"bool","name":"paid","internalType":"bool"}],"name":"transactions","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"transactionsCount","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdraw","inputs":[]},{"type":"event","name":"BusinessApproved","inputs":[{"type":"address","name":"business","indexed":true}],"anonymous":false},{"type":"event","name":"BusinessRemoved","inputs":[{"type":"address","name":"business","indexed":true}],"anonymous":false},{"type":"event","name":"CharityApproved","inputs":[{"type":"address","name":"charity","indexed":true}],"anonymous":false},{"type":"event","name":"CharityRemoved","inputs":[{"type":"address","name":"charity","indexed":true}],"anonymous":false},{"type":"event","name":"ManagerAdded","inputs":[{"type":"address","name":"manager","indexed":true}],"anonymous":false},{"type":"event","name":"PendingBusinessAdded","inputs":[{"type":"address","name":"charity","indexed":true}],"anonymous":false},{"type":"event","name":"PendingCharityAdded","inputs":[{"type":"address","name":"charity","indexed":true}],"anonymous":false},{"type":"event","name":"TransactionAdded","inputs":[{"type":"uint256","name":"transactionId","indexed":true},{"type":"address","name":"business","indexed":true}],"anonymous":false},{"type":"event","name":"TransactionPaid","inputs":[{"type":"uint256","name":"transactionId","indexed":true},{"type":"address","name":"business","indexed":true}],"anonymous":false},{"type":"event","name":"Withdrawal","inputs":[{"type":"uint256","name":"amount","indexed":false},{"type":"address","name":"manager","indexed":true}],"anonymous":false},{"type":"receive"},{"type":"fallback"}]
            

Deployed ByteCode

0x6080604052600436106101385760003560e01c80639ec5a894116100b0578063e81ffbef1161006c578063e81ffbef14610400578063ee22610b14610430578063f3ae241514610443578063fb709d2e14610473578063fd99a74614610493578063fddd4387146104a957005b80639ec5a8941461033c5780639ffd8fb814610352578063abefe59114610372578063b984c6ec14610392578063c127fd39146103b2578063e725a4be146103e057005b80633d39c260116100ff5780633d39c260146101fb578063418dff3d14610233578063419b96fa1461026157806345810583146102815780639ace38c2146102a15780639b0137b31461031c57005b80631466d01914610141578063166cd850146101865780631702e2dc146101a65780632d06177a146101c65780633ccfd60b146101e657005b3661013f57005b005b34801561014d57600080fd5b5061017161015c3660046119f9565b60006020819052908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561019257600080fd5b5061013f6101a13660046119f9565b6104c9565b3480156101b257600080fd5b5061013f6101c1366004611a8b565b6105f5565b3480156101d257600080fd5b5061013f6101e13660046119f9565b610944565b3480156101f257600080fd5b5061013f6109ff565b34801561020757600080fd5b5061021b610216366004611b7a565b610ac1565b6040516001600160a01b03909116815260200161017d565b34801561023f57600080fd5b5061025361024e366004611b93565b610aeb565b60405190815260200161017d565b34801561026d57600080fd5b5061013f61027c3660046119f9565b610b1c565b34801561028d57600080fd5b5061013f61029c3660046119f9565b610cc0565b3480156102ad57600080fd5b506102f06102bc366004611b7a565b600a6020526000908152604090208054600282015460038301546004909301546001600160a01b0390921692909160ff1684565b604080516001600160a01b0390951685526020850193909352918301521515606082015260800161017d565b34801561032857600080fd5b5061021b610337366004611b7a565b610e9d565b34801561034857600080fd5b5061025360055481565b34801561035e57600080fd5b5061021b61036d366004611b7a565b610ead565b34801561037e57600080fd5b5061013f61038d3660046119f9565b610ebd565b34801561039e57600080fd5b5061021b6103ad366004611b7a565b611033565b3480156103be57600080fd5b506103d26103cd3660046119f9565b611043565b60405161017d929190611bf8565b3480156103ec57600080fd5b5061013f6103fb3660046119f9565b6112ce565b34801561040c57600080fd5b5061017161041b3660046119f9565b60066020526000908152604090205460ff1681565b61013f61043e366004611b7a565b6113f6565b34801561044f57600080fd5b5061017161045e3660046119f9565b60036020526000908152604090205460ff1681565b34801561047f57600080fd5b5061021b61048e366004611b7a565b611752565b34801561049f57600080fd5b5061025360095481565b3480156104b557600080fd5b5061013f6104c43660046119f9565b611762565b60005b60085481101561057c57816001600160a01b0316600882815481106104f3576104f3611ce2565b6000918252602090912001546001600160a01b0316141561056a5760405162461bcd60e51b815260206004820152602660248201527f5468652063686172697479206164647265737320697320616c72656164792070604482015265656e64696e6760d01b60648201526084015b60405180910390fd5b8061057481611d0e565b9150506104cc565b506008805460018101825560009182527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30180546001600160a01b0319166001600160a01b03841690811790915560405190917fee010dc102da811e4fb2e0202db4865ca889bc73f30087b25cbda0729c63eff391a250565b3360009081526003602052604090205460ff166106245760405162461bcd60e51b815260040161056190611d29565b600082511161066b5760405162461bcd60e51b81526020600482015260136024820152724368617269746965732061726520656d70747960681b6044820152606401610561565b6001600160a01b03831660009081526020819052604090205460ff166106d35760405162461bcd60e51b815260206004820152601860248201527f436c69656e74206973206e6f74206f757220636c69656e7400000000000000006044820152606401610561565b600980546000908152600a602052604080822080546001600160a01b0319166001600160a01b038816179055825482528082206003018490558451835483528183206002015591548152908120600401805460ff191690555b82518110156108cc576006600084838151811061074b5761074b611ce2565b602090810291909101810151516001600160a01b031682528101919091526040016000205460ff166107da5760405162461bcd60e51b815260206004820152603260248201527f4f6e65206f66207468652064657374696e6174696f6e73206973206e6f7420616044820152716e20617070726f766564206368617269747960701b6064820152608401610561565b60008382815181106107ee576107ee611ce2565b602002602001015160200151116108475760405162461bcd60e51b815260206004820152601c60248201527f446f6e6174696f6e732073686f756c64206265206e6f6e2d7a65726f000000006044820152606401610561565b600a6000600954815260200190815260200160002060010183828151811061087157610871611ce2565b602090810291909101810151825460018082018555600094855293839020825160029092020180546001600160a01b0319166001600160a01b03909216919091178155910151910155806108c481611d0e565b91505061072c565b506001600160a01b0383166000818152600b60209081526040808320600980548254600181018455928652938520909101929092559054905190917f5fd655308280ca8f5b685114cfe87b25b8f728b401240adcc0a98e877e3e29cd91a36009805490600061093a83611d0e565b9190505550505050565b3360009081526003602052604090205460ff166109735760405162461bcd60e51b815260040161056190611d29565b6001600160a01b038116600081815260036020526040808220805460ff1916600190811790915560048054918201815583527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b03191684179055517f3b4a40cccf2058c593542587329dd385be4f0b588db5471fbd9598e56dd7093a9190a250565b3360009081526003602052604090205460ff16610a2e5760405162461bcd60e51b815260040161056190611d29565b600060055411610a765760405162461bcd60e51b81526020600482015260136024820152724e6f7468696e6720746f20776974686472617760681b6044820152606401610561565b60055460405190815233907fd964a27d45f595739c13d8b1160b57491050cacf3a2e5602207277d6228f64ee9060200160405180910390a2610aba3360055461193e565b6000600555565b60048181548110610ad157600080fd5b6000918252602090912001546001600160a01b0316905081565b600b6020528160005260406000208181548110610b0757600080fd5b90600052602060002001600091509150505481565b3360009081526003602052604090205460ff16610b4b5760405162461bcd60e51b815260040161056190611d29565b6001600160a01b038116600081815260208190526040808220805460ff19169055517f53c1bf54b1856bd715700f661ff046b40ed055bd0b5d09654df4cb6dc7fb2cfd9190a2600154610b9b5750565b60005b600154811015610cbc57816001600160a01b031660018281548110610bc557610bc5611ce2565b6000918252602090912001546001600160a01b03161415610caa5760018054610bee9190611d6b565b8114610c6e5760018054610c03908290611d6b565b81548110610c1357610c13611ce2565b600091825260209091200154600180546001600160a01b039092169183908110610c3f57610c3f611ce2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60018054610c7d908290611d6b565b81548110610c8d57610c8d611ce2565b600091825260209091200180546001600160a01b03191690555050565b80610cb481611d0e565b915050610b9e565b5050565b3360009081526003602052604090205460ff16610cef5760405162461bcd60e51b815260040161056190611d29565b6001600160a01b03811660009081526006602052604090205460ff1615610d135750565b6001600160a01b038116600081815260066020526040808220805460ff1916600190811790915560078054918201815583527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b03191684179055517f28675749c11847be30a3b822f80f286058475c5f4977dcb99798b5b0ff2cbe5e9190a2600854610da65750565b60005b600854811015610cbc57816001600160a01b031660088281548110610dd057610dd0611ce2565b6000918252602090912001546001600160a01b03161415610e8b57600854610dfa90600190611d6b565b8114610e7b5760088054610e1090600190611d6b565b81548110610e2057610e20611ce2565b600091825260209091200154600880546001600160a01b039092169183908110610e4c57610e4c611ce2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60088054610c7d90600190611d6b565b80610e9581611d0e565b915050610da9565b60088181548110610ad157600080fd5b60028181548110610ad157600080fd5b3360009081526003602052604090205460ff16610eec5760405162461bcd60e51b815260040161056190611d29565b6001600160a01b038116600081815260066020526040808220805460ff19169055517f7db8df158d85e9475e8dd97a5e3e193c67dc6d977d2fc4f7321049b6c0b70e939190a2600754610f3c5750565b60005b600754811015610cbc57816001600160a01b031660078281548110610f6657610f66611ce2565b6000918252602090912001546001600160a01b0316141561102157600754610f9090600190611d6b565b81146110115760078054610fa690600190611d6b565b81548110610fb657610fb6611ce2565b600091825260209091200154600780546001600160a01b039092169183908110610fe257610fe2611ce2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60078054610c7d90600190611d6b565b8061102b81611d0e565b915050610f3f565b60018181548110610ad157600080fd5b6001600160a01b0381166000908152600b60205260408120546060918291908167ffffffffffffffff81111561107b5761107b611a1b565b6040519080825280602002602001820160405280156110e957816020015b6110d66040518060a0016040528060006001600160a01b031681526020016060815260200160008152602001600081526020016000151581525090565b8152602001906001900390816110995790505b50905060008267ffffffffffffffff81111561110757611107611a1b565b604051908082528060200260200182016040528015611130578160200160208202803683370190505b50905060005b838110156112c2576001600160a01b0387166000908152600b6020526040902080548290811061116857611168611ce2565b906000526020600020015482828151811061118557611185611ce2565b602002602001018181525050600a60008383815181106111a7576111a7611ce2565b602002602001015181526020019081526020016000206040518060a00160405290816000820160009054906101000a90046001600160a01b03166001600160a01b03166001600160a01b0316815260200160018201805480602002602001604051908101604052809291908181526020016000905b82821015611264576000848152602090819020604080518082019091526002850290910180546001600160a01b0316825260019081015482840152908352909201910161121c565b50505090825250600282015460208201526003820154604082015260049091015460ff16151560609091015283518490839081106112a4576112a4611ce2565b602002602001018190525080806112ba90611d0e565b915050611136565b50909590945092505050565b60005b60025481101561137d57816001600160a01b0316600282815481106112f8576112f8611ce2565b6000918252602090912001546001600160a01b0316141561136b5760405162461bcd60e51b815260206004820152602760248201527f54686520627573696e657373206164647265737320697320616c72656164792060448201526670656e64696e6760c81b6064820152608401610561565b8061137581611d0e565b9150506112d1565b506002805460018101825560009182527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0319166001600160a01b03841690811790915560405190917f8887e6f603275db1e771ec0f4ef66986dd7f78c8b354787c2055c5f56665602991a250565b3360009081526020819052604090205460ff166114615760405162461bcd60e51b815260206004820152602360248201527f53656e646572206973206e6f742074686520617070726f76656420627573696e60448201526265737360e81b6064820152608401610561565b6000818152600a602052604090205481906001600160a01b03166114c75760405162461bcd60e51b815260206004820152601a60248201527f5472616e73616374696f6e20646f65736e27742065786973742e0000000000006044820152606401610561565b6000828152600a6020526040902080546001600160a01b0316331461153c5760405162461bcd60e51b815260206004820152602560248201527f546865207472616e73616374696f6e20697320666f7220616e6f7468657220636044820152641b1a595b9d60da1b6064820152608401610561565b600481015460ff16156115915760405162461bcd60e51b815260206004820152601b60248201527f5472616e73616374696f6e206973207061696420616c726561647900000000006044820152606401610561565b6000805b82600201548110156115e7578260010181815481106115b6576115b6611ce2565b906000526020600020906002020160010154826115d39190611d82565b9150806115df81611d0e565b915050611595565b50348260030154826115f99190611d82565b11156116605760405162461bcd60e51b815260206004820152603060248201527f5468652076616c7565206973206e6f7420656e6f75676820746f20636f76657260448201526f103a3432903a3930b739b0b1ba34b7b760811b6064820152608401610561565b60005b82600201548110156116e3576116d183600101828154811061168757611687611ce2565b60009182526020909120600290910201546001850180546001600160a01b0390921691849081106116ba576116ba611ce2565b90600052602060002090600202016001015461193e565b806116db81611d0e565b915050611663565b5060048201805460ff191660011790556116fd8134611d6b565b6005600082825461170e9190611d82565b909155505081546040516001600160a01b039091169085907f1048322214c2376910cb9740dec280cf85a1375be08c0db6dd0413edc8c49c8e90600090a350505050565b60078181548110610ad157600080fd5b3360009081526003602052604090205460ff166117915760405162461bcd60e51b815260040161056190611d29565b6001600160a01b03811660009081526020819052604090205460ff16156117b55750565b6001600160a01b038116600081815260208190526040808220805460ff19166001908117909155805480820182559083527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b03191684179055517faf1d127970278f3e2c952d5839b66d23f63c89edc514c3c4e96afbc3e0c9510f9190a26002546118475750565b60005b600254811015610cbc57816001600160a01b03166002828154811061187157611871611ce2565b6000918252602090912001546001600160a01b0316141561192c5760025461189b90600190611d6b565b811461191c57600280546118b190600190611d6b565b815481106118c1576118c1611ce2565b600091825260209091200154600280546001600160a01b0390921691839081106118ed576118ed611ce2565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b60028054610c7d90600190611d6b565b8061193681611d0e565b91505061184a565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461198b576040519150601f19603f3d011682016040523d82523d6000602084013e611990565b606091505b50509050806119d85760405162461bcd60e51b81526020600482015260146024820152734661696c656420746f2073656e642066756e647360601b6044820152606401610561565b505050565b80356001600160a01b03811681146119f457600080fd5b919050565b600060208284031215611a0b57600080fd5b611a14826119dd565b9392505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611a5457611a54611a1b565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611a8357611a83611a1b565b604052919050565b600080600060608486031215611aa057600080fd5b611aa9846119dd565b925060208085013567ffffffffffffffff80821115611ac757600080fd5b818701915087601f830112611adb57600080fd5b813581811115611aed57611aed611a1b565b611afb848260051b01611a5a565b818152848101925060069190911b830184019089821115611b1b57600080fd5b928401925b81841015611b65576040848b031215611b395760008081fd5b611b41611a31565b611b4a856119dd565b81528486013586820152835260409093019291840191611b20565b96999698505050506040949094013593505050565b600060208284031215611b8c57600080fd5b5035919050565b60008060408385031215611ba657600080fd5b611baf836119dd565b946020939093013593505050565b600081518084526020808501945080840160005b83811015611bed57815187529582019590820190600101611bd1565b509495945050505050565b60006040808301818452808651808352606092508286019150828160051b8701016020808a016000805b85811015611cc1578a8503605f19018752825180516001600160a01b0390811687528582015160a0878901819052815190890181905260c0890192918801919086905b80821015611c905783518051841686528a01518a860152938e01939289019260019190910190611c65565b50505050818b0151878c0152898201518a880152608091820151151591909601529583019591830191600101611c22565b50505087820390880152611cd58189611bbd565b9998505050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415611d2257611d22611cf8565b5060010190565b60208082526022908201527f53656e646572206973206e6f742074686520617070726f766564206d616e616760408201526132b960f11b606082015260800190565b600082821015611d7d57611d7d611cf8565b500390565b60008219821115611d9557611d95611cf8565b50019056fea26469706673582212203e734d20d8252911314462a51aac0ca42d1d7352ac5a12d9703951bdb6b2ab1564736f6c63430008090033