Transactions
Token Transfers
Tokens
Internal Transactions
Coin Balance History
Logs
Code
Read Contract
Write Contract
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- PromoVault
- Optimization enabled
- false
- Compiler version
- v0.8.19+commit.7dd6d404
- EVM Version
- default
- Verified at
- 2024-09-26T15:33:47.798239Z
Contract source code
// SPDX-License-Identifier: No License (None)
pragma solidity 0.8.19;
// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferETH(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}
abstract contract Ownable {
address internal _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () {
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == msg.sender, "Ownable: caller is not the owner");
_;
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
contract PromoVault is Ownable {
using TransferHelper for address;
address public authority; // address of authority (backend) which sign token transfer data
mapping(address user => uint256 nonce) public nonces; // returns nonce for specific user
event VaultTransfer(address indexed token, address indexed from, address to, uint256 value);
event Rescue(address _token, uint256 _amount);
/*
// to sign message on the server-side use:
var vault = new web3.eth.Contract(VaultContractABI, VaultContractAddress);
var nonce = await vault.methods.nonces(from).call();
var messageHash = web3.utils.soliditySha3(token, from, to, value, nonce, ChainId, VaultContractAddress);
var signature = web3.eth.accounts.sign(messageHash, PrivateKey);
*/
// transfer promo tokens from vault.
function vaultTransfer(
address token, // token to transfer
address from, // transfer from user's virtual account
address to, // transfer to address
uint256 value, // amount of tokens to transfer
bytes memory signature
) external {
bytes32 messageHash = keccak256(
abi.encodePacked(
token,
from,
to,
value,
nonces[from],
block.chainid,
address(this)
)
);
messageHash = prefixed(messageHash);
require(authority == recoverSigner(messageHash, signature), "wrong signature");
nonces[from]++;
token.safeTransfer(to, value);
emit VaultTransfer(token, from, to, value);
}
function setAuthority(address _authority) external onlyOwner {
require(_authority != address(0));
authority = _authority;
}
function splitSignature(bytes memory sig)
internal
pure
returns (
uint8 v,
bytes32 r,
bytes32 s
)
{
require(sig.length == 65);
assembly {
// first 32 bytes, after the length prefix
r := mload(add(sig, 32))
// second 32 bytes
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes)
v := byte(0, mload(add(sig, 96)))
}
}
function recoverSigner(bytes32 message, bytes memory sig)
internal
pure
returns (address)
{
uint8 v;
bytes32 r;
bytes32 s;
(v, r, s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
// Builds a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return
keccak256(
abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)
);
}
function tokenReceived(address, uint, bytes calldata) external pure returns(bytes4) {
return this.tokenReceived.selector;
}
function rescueTokens(address token, uint256 amount) onlyOwner external {
if (token == address(0)) {
msg.sender.safeTransferETH(amount);
} else {
token.safeTransfer(msg.sender, amount);
}
emit Rescue(token, amount);
}
}
Contract ABI
[{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Rescue","inputs":[{"type":"address","name":"_token","internalType":"address","indexed":false},{"type":"uint256","name":"_amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"VaultTransfer","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"authority","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"nonce","internalType":"uint256"}],"name":"nonces","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueTokens","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAuthority","inputs":[{"type":"address","name":"_authority","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes4","name":"","internalType":"bytes4"}],"name":"tokenReceived","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"},{"type":"bytes","name":"","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"vaultTransfer","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36115ab806100bb6000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610125578063bf7e214f14610143578063d055e95114610161578063f2fde38b1461017d57610088565b8063573761981461008d5780637a9e5e4b146100a95780637ecebe00146100c55780638943ec02146100f5575b600080fd5b6100a760048036038101906100a29190610ba5565b610199565b005b6100c360048036038101906100be9190610be5565b6102d9565b005b6100df60048036038101906100da9190610be5565b6103cb565b6040516100ec9190610c21565b60405180910390f35b61010f600480360381019061010a9190610ca1565b6103e3565b60405161011c9190610d50565b60405180910390f35b61012d6103f7565b60405161013a9190610d7a565b60405180910390f35b61014b610420565b6040516101589190610d7a565b60405180910390f35b61017b60048036038101906101769190610ed6565b610446565b005b61019760048036038101906101929190610be5565b61064f565b005b3373ffffffffffffffffffffffffffffffffffffffff166101b86103f7565b73ffffffffffffffffffffffffffffffffffffffff161461020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020590610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036102705761026b813373ffffffffffffffffffffffffffffffffffffffff166107f090919063ffffffff16565b61029c565b61029b33828473ffffffffffffffffffffffffffffffffffffffff166108f09092919063ffffffff16565b5b7f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af282826040516102cd929190610fea565b60405180910390a15050565b3373ffffffffffffffffffffffffffffffffffffffff166102f86103f7565b73ffffffffffffffffffffffffffffffffffffffff161461034e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034590610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361038757600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60026020528060005260406000206000915090505481565b6000638943ec0260e01b9050949350505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600085858585600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205446306040516020016104a4979695949392919061107c565b6040516020818303038152906040528051906020012090506104c581610a26565b90506104d18183610a56565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610560576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161055790611149565b60405180910390fd5b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906105b090611198565b91905055506105e084848873ffffffffffffffffffffffffffffffffffffffff166108f09092919063ffffffff16565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fc4298a5beffbb92832adef4bde23a2148eea5117fee88fd06e963ddcb4a523f4868660405161063f929190610fea565b60405180910390a3505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1661066e6103f7565b73ffffffffffffffffffffffffffffffffffffffff16146106c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bb90610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610733576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072a90611252565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008273ffffffffffffffffffffffffffffffffffffffff1682600067ffffffffffffffff81111561082557610824610dab565b5b6040519080825280601f01601f1916602001820160405280156108575781602001600182028036833780820191505090505b5060405161086591906112e3565b60006040518083038185875af1925050503d80600081146108a2576040519150601f19603f3d011682016040523d82523d6000602084013e6108a7565b606091505b50509050806108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e29061136c565b60405180910390fd5b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401610922929190610fea565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161097091906112e3565b6000604051808303816000865af19150503d80600081146109ad576040519150601f19603f3d011682016040523d82523d6000602084013e6109b2565b606091505b50915091508180156109e057506000815114806109df5750808060200190518101906109de91906113c4565b5b5b610a1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a169061143d565b60405180910390fd5b5050505050565b600081604051602001610a3991906114df565b604051602081830303815290604052805190602001209050919050565b600080600080610a6585610acb565b80935081945082955050505060018684848460405160008152602001604052604051610a949493929190611530565b6020604051602081039080840390855afa158015610ab6573d6000803e3d6000fd5b50505060206040510351935050505092915050565b60008060006041845114610ade57600080fd5b6020840151915060408401519050606084015160001a92509193909250565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610b3c82610b11565b9050919050565b610b4c81610b31565b8114610b5757600080fd5b50565b600081359050610b6981610b43565b92915050565b6000819050919050565b610b8281610b6f565b8114610b8d57600080fd5b50565b600081359050610b9f81610b79565b92915050565b60008060408385031215610bbc57610bbb610b07565b5b6000610bca85828601610b5a565b9250506020610bdb85828601610b90565b9150509250929050565b600060208284031215610bfb57610bfa610b07565b5b6000610c0984828501610b5a565b91505092915050565b610c1b81610b6f565b82525050565b6000602082019050610c366000830184610c12565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610c6157610c60610c3c565b5b8235905067ffffffffffffffff811115610c7e57610c7d610c41565b5b602083019150836001820283011115610c9a57610c99610c46565b5b9250929050565b60008060008060608587031215610cbb57610cba610b07565b5b6000610cc987828801610b5a565b9450506020610cda87828801610b90565b935050604085013567ffffffffffffffff811115610cfb57610cfa610b0c565b5b610d0787828801610c4b565b925092505092959194509250565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610d4a81610d15565b82525050565b6000602082019050610d656000830184610d41565b92915050565b610d7481610b31565b82525050565b6000602082019050610d8f6000830184610d6b565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610de382610d9a565b810181811067ffffffffffffffff82111715610e0257610e01610dab565b5b80604052505050565b6000610e15610afd565b9050610e218282610dda565b919050565b600067ffffffffffffffff821115610e4157610e40610dab565b5b610e4a82610d9a565b9050602081019050919050565b82818337600083830152505050565b6000610e79610e7484610e26565b610e0b565b905082815260208101848484011115610e9557610e94610d95565b5b610ea0848285610e57565b509392505050565b600082601f830112610ebd57610ebc610c3c565b5b8135610ecd848260208601610e66565b91505092915050565b600080600080600060a08688031215610ef257610ef1610b07565b5b6000610f0088828901610b5a565b9550506020610f1188828901610b5a565b9450506040610f2288828901610b5a565b9350506060610f3388828901610b90565b925050608086013567ffffffffffffffff811115610f5457610f53610b0c565b5b610f6088828901610ea8565b9150509295509295909350565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610fb4602083610f6d565b9150610fbf82610f7e565b602082019050919050565b60006020820190508181036000830152610fe381610fa7565b9050919050565b6000604082019050610fff6000830185610d6b565b61100c6020830184610c12565b9392505050565b60008160601b9050919050565b600061102b82611013565b9050919050565b600061103d82611020565b9050919050565b61105561105082610b31565b611032565b82525050565b6000819050919050565b61107661107182610b6f565b61105b565b82525050565b6000611088828a611044565b6014820191506110988289611044565b6014820191506110a88288611044565b6014820191506110b88287611065565b6020820191506110c88286611065565b6020820191506110d88285611065565b6020820191506110e88284611044565b60148201915081905098975050505050505050565b7f77726f6e67207369676e61747572650000000000000000000000000000000000600082015250565b6000611133600f83610f6d565b915061113e826110fd565b602082019050919050565b6000602082019050818103600083015261116281611126565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006111a382610b6f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111d5576111d4611169565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061123c602683610f6d565b9150611247826111e0565b604082019050919050565b6000602082019050818103600083015261126b8161122f565b9050919050565b600081519050919050565b600081905092915050565b60005b838110156112a657808201518184015260208101905061128b565b60008484015250505050565b60006112bd82611272565b6112c7818561127d565b93506112d7818560208601611288565b80840191505092915050565b60006112ef82846112b2565b915081905092915050565b7f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960008201527f4c45440000000000000000000000000000000000000000000000000000000000602082015250565b6000611356602383610f6d565b9150611361826112fa565b604082019050919050565b6000602082019050818103600083015261138581611349565b9050919050565b60008115159050919050565b6113a18161138c565b81146113ac57600080fd5b50565b6000815190506113be81611398565b92915050565b6000602082840312156113da576113d9610b07565b5b60006113e8848285016113af565b91505092915050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000611427601f83610f6d565b9150611432826113f1565b602082019050919050565b600060208201905081810360008301526114568161141a565b9050919050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061149e601c8361145d565b91506114a982611468565b601c82019050919050565b6000819050919050565b6000819050919050565b6114d96114d4826114b4565b6114be565b82525050565b60006114ea82611491565b91506114f682846114c8565b60208201915081905092915050565b61150e816114b4565b82525050565b600060ff82169050919050565b61152a81611514565b82525050565b60006080820190506115456000830187611505565b6115526020830186611521565b61155f6040830185611505565b61156c6060830184611505565b9594505050505056fea2646970667358221220fa4739c2e9ef06ff3fe5717bdd274f0d8fe04cca7911a6cb2378aea9c866e4c364736f6c63430008130033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c80638da5cb5b1161005b5780638da5cb5b14610125578063bf7e214f14610143578063d055e95114610161578063f2fde38b1461017d57610088565b8063573761981461008d5780637a9e5e4b146100a95780637ecebe00146100c55780638943ec02146100f5575b600080fd5b6100a760048036038101906100a29190610ba5565b610199565b005b6100c360048036038101906100be9190610be5565b6102d9565b005b6100df60048036038101906100da9190610be5565b6103cb565b6040516100ec9190610c21565b60405180910390f35b61010f600480360381019061010a9190610ca1565b6103e3565b60405161011c9190610d50565b60405180910390f35b61012d6103f7565b60405161013a9190610d7a565b60405180910390f35b61014b610420565b6040516101589190610d7a565b60405180910390f35b61017b60048036038101906101769190610ed6565b610446565b005b61019760048036038101906101929190610be5565b61064f565b005b3373ffffffffffffffffffffffffffffffffffffffff166101b86103f7565b73ffffffffffffffffffffffffffffffffffffffff161461020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161020590610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036102705761026b813373ffffffffffffffffffffffffffffffffffffffff166107f090919063ffffffff16565b61029c565b61029b33828473ffffffffffffffffffffffffffffffffffffffff166108f09092919063ffffffff16565b5b7f542fa6bfee3b4746210fbdd1d83f9e49b65adde3639f8d8f165dd18347938af282826040516102cd929190610fea565b60405180910390a15050565b3373ffffffffffffffffffffffffffffffffffffffff166102f86103f7565b73ffffffffffffffffffffffffffffffffffffffff161461034e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161034590610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361038757600080fd5b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60026020528060005260406000206000915090505481565b6000638943ec0260e01b9050949350505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600085858585600260008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205446306040516020016104a4979695949392919061107c565b6040516020818303038152906040528051906020012090506104c581610a26565b90506104d18183610a56565b73ffffffffffffffffffffffffffffffffffffffff16600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610560576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161055790611149565b60405180910390fd5b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906105b090611198565b91905055506105e084848873ffffffffffffffffffffffffffffffffffffffff166108f09092919063ffffffff16565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fc4298a5beffbb92832adef4bde23a2148eea5117fee88fd06e963ddcb4a523f4868660405161063f929190610fea565b60405180910390a3505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1661066e6103f7565b73ffffffffffffffffffffffffffffffffffffffff16146106c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106bb90610fca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610733576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072a90611252565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008273ffffffffffffffffffffffffffffffffffffffff1682600067ffffffffffffffff81111561082557610824610dab565b5b6040519080825280601f01601f1916602001820160405280156108575781602001600182028036833780820191505090505b5060405161086591906112e3565b60006040518083038185875af1925050503d80600081146108a2576040519150601f19603f3d011682016040523d82523d6000602084013e6108a7565b606091505b50509050806108eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e29061136c565b60405180910390fd5b505050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401610922929190610fea565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161097091906112e3565b6000604051808303816000865af19150503d80600081146109ad576040519150601f19603f3d011682016040523d82523d6000602084013e6109b2565b606091505b50915091508180156109e057506000815114806109df5750808060200190518101906109de91906113c4565b5b5b610a1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a169061143d565b60405180910390fd5b5050505050565b600081604051602001610a3991906114df565b604051602081830303815290604052805190602001209050919050565b600080600080610a6585610acb565b80935081945082955050505060018684848460405160008152602001604052604051610a949493929190611530565b6020604051602081039080840390855afa158015610ab6573d6000803e3d6000fd5b50505060206040510351935050505092915050565b60008060006041845114610ade57600080fd5b6020840151915060408401519050606084015160001a92509193909250565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610b3c82610b11565b9050919050565b610b4c81610b31565b8114610b5757600080fd5b50565b600081359050610b6981610b43565b92915050565b6000819050919050565b610b8281610b6f565b8114610b8d57600080fd5b50565b600081359050610b9f81610b79565b92915050565b60008060408385031215610bbc57610bbb610b07565b5b6000610bca85828601610b5a565b9250506020610bdb85828601610b90565b9150509250929050565b600060208284031215610bfb57610bfa610b07565b5b6000610c0984828501610b5a565b91505092915050565b610c1b81610b6f565b82525050565b6000602082019050610c366000830184610c12565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610c6157610c60610c3c565b5b8235905067ffffffffffffffff811115610c7e57610c7d610c41565b5b602083019150836001820283011115610c9a57610c99610c46565b5b9250929050565b60008060008060608587031215610cbb57610cba610b07565b5b6000610cc987828801610b5a565b9450506020610cda87828801610b90565b935050604085013567ffffffffffffffff811115610cfb57610cfa610b0c565b5b610d0787828801610c4b565b925092505092959194509250565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610d4a81610d15565b82525050565b6000602082019050610d656000830184610d41565b92915050565b610d7481610b31565b82525050565b6000602082019050610d8f6000830184610d6b565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610de382610d9a565b810181811067ffffffffffffffff82111715610e0257610e01610dab565b5b80604052505050565b6000610e15610afd565b9050610e218282610dda565b919050565b600067ffffffffffffffff821115610e4157610e40610dab565b5b610e4a82610d9a565b9050602081019050919050565b82818337600083830152505050565b6000610e79610e7484610e26565b610e0b565b905082815260208101848484011115610e9557610e94610d95565b5b610ea0848285610e57565b509392505050565b600082601f830112610ebd57610ebc610c3c565b5b8135610ecd848260208601610e66565b91505092915050565b600080600080600060a08688031215610ef257610ef1610b07565b5b6000610f0088828901610b5a565b9550506020610f1188828901610b5a565b9450506040610f2288828901610b5a565b9350506060610f3388828901610b90565b925050608086013567ffffffffffffffff811115610f5457610f53610b0c565b5b610f6088828901610ea8565b9150509295509295909350565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b6000610fb4602083610f6d565b9150610fbf82610f7e565b602082019050919050565b60006020820190508181036000830152610fe381610fa7565b9050919050565b6000604082019050610fff6000830185610d6b565b61100c6020830184610c12565b9392505050565b60008160601b9050919050565b600061102b82611013565b9050919050565b600061103d82611020565b9050919050565b61105561105082610b31565b611032565b82525050565b6000819050919050565b61107661107182610b6f565b61105b565b82525050565b6000611088828a611044565b6014820191506110988289611044565b6014820191506110a88288611044565b6014820191506110b88287611065565b6020820191506110c88286611065565b6020820191506110d88285611065565b6020820191506110e88284611044565b60148201915081905098975050505050505050565b7f77726f6e67207369676e61747572650000000000000000000000000000000000600082015250565b6000611133600f83610f6d565b915061113e826110fd565b602082019050919050565b6000602082019050818103600083015261116281611126565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006111a382610b6f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036111d5576111d4611169565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061123c602683610f6d565b9150611247826111e0565b604082019050919050565b6000602082019050818103600083015261126b8161122f565b9050919050565b600081519050919050565b600081905092915050565b60005b838110156112a657808201518184015260208101905061128b565b60008484015250505050565b60006112bd82611272565b6112c7818561127d565b93506112d7818560208601611288565b80840191505092915050565b60006112ef82846112b2565b915081905092915050565b7f5472616e7366657248656c7065723a204554485f5452414e534645525f46414960008201527f4c45440000000000000000000000000000000000000000000000000000000000602082015250565b6000611356602383610f6d565b9150611361826112fa565b604082019050919050565b6000602082019050818103600083015261138581611349565b9050919050565b60008115159050919050565b6113a18161138c565b81146113ac57600080fd5b50565b6000815190506113be81611398565b92915050565b6000602082840312156113da576113d9610b07565b5b60006113e8848285016113af565b91505092915050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b6000611427601f83610f6d565b9150611432826113f1565b602082019050919050565b600060208201905081810360008301526114568161141a565b9050919050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061149e601c8361145d565b91506114a982611468565b601c82019050919050565b6000819050919050565b6000819050919050565b6114d96114d4826114b4565b6114be565b82525050565b60006114ea82611491565b91506114f682846114c8565b60208201915081905092915050565b61150e816114b4565b82525050565b600060ff82169050919050565b61152a81611514565b82525050565b60006080820190506115456000830187611505565b6115526020830186611521565b61155f6040830185611505565b61156c6060830184611505565b9594505050505056fea2646970667358221220fa4739c2e9ef06ff3fe5717bdd274f0d8fe04cca7911a6cb2378aea9c866e4c364736f6c63430008130033