Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- GnosisSafeL2
- Optimization enabled
- true
- Compiler version
- v0.7.6+commit.7338295f
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-11-08T09:30:58.606712Z
contracts/GnosisSafeL2.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "./GnosisSafe.sol";
/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract GnosisSafeL2 is GnosisSafe {
event SafeMultiSigTransaction(
address to,
uint256 value,
bytes data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes signatures,
// We combine nonce, sender and threshold into one to avoid stack too deep
// Dev note: additionalInfo should not contain `bytes`, as this complicates decoding
bytes additionalInfo
);
event SafeModuleTransaction(address module, address to, uint256 value, bytes data, Enum.Operation operation);
/// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
/// Note: The fees are always transferred, even if the user transaction fails.
/// @param to Destination address of Safe transaction.
/// @param value Ether value of Safe transaction.
/// @param data Data payload of Safe transaction.
/// @param operation Operation type of Safe transaction.
/// @param safeTxGas Gas that should be used for the Safe transaction.
/// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
/// @param gasPrice Gas price that should be used for the payment calculation.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
function execTransaction(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures
) public payable override returns (bool) {
bytes memory additionalInfo;
{
additionalInfo = abi.encode(nonce, msg.sender, threshold);
}
emit SafeMultiSigTransaction(
to,
value,
data,
operation,
safeTxGas,
baseGas,
gasPrice,
gasToken,
refundReceiver,
signatures,
additionalInfo
);
return super.execTransaction(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, signatures);
}
/// @dev Allows a Module to execute a Safe transaction without any further confirmations.
/// @param to Destination address of module transaction.
/// @param value Ether value of module transaction.
/// @param data Data payload of module transaction.
/// @param operation Operation type of module transaction.
function execTransactionFromModule(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) public override returns (bool success) {
emit SafeModuleTransaction(msg.sender, to, value, data, operation);
success = super.execTransactionFromModule(to, value, data, operation);
}
}
contracts/GnosisSafe.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "./base/ModuleManager.sol";
import "./base/OwnerManager.sol";
import "./base/FallbackManager.sol";
import "./base/GuardManager.sol";
import "./common/EtherPaymentFallback.sol";
import "./common/Singleton.sol";
import "./common/SignatureDecoder.sol";
import "./common/SecuredTokenTransfer.sol";
import "./common/StorageAccessible.sol";
import "../interfaces/ISignatureValidator.sol";
import "../libraries/GnosisSafeMath.sol";
/// @title Gnosis Safe - A multisignature wallet with support for confirmations using signed messages based on ERC191.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract GnosisSafe is
EtherPaymentFallback,
Singleton,
ModuleManager,
OwnerManager,
SignatureDecoder,
SecuredTokenTransfer,
ISignatureValidatorConstants,
FallbackManager,
StorageAccessible,
GuardManager
{
using GnosisSafeMath for uint256;
string public constant VERSION = "1.3.0";
// keccak256(
// "EIP712Domain(uint256 chainId,address verifyingContract)"
// );
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218;
// keccak256(
// "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)"
// );
bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8;
event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler);
event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
event SignMsg(bytes32 indexed msgHash);
event ExecutionFailure(bytes32 txHash, uint256 payment);
event ExecutionSuccess(bytes32 txHash, uint256 payment);
uint256 public nonce;
bytes32 private _deprecatedDomainSeparator;
// Mapping to keep track of all message hashes that have been approve by ALL REQUIRED owners
mapping(bytes32 => uint256) public signedMessages;
// Mapping to keep track of all hashes (message or transaction) that have been approve by ANY owners
mapping(address => mapping(bytes32 => uint256)) public approvedHashes;
// This constructor ensures that this contract can only be used as a master copy for Proxy contracts
constructor() {
// By setting the threshold it is not possible to call setup anymore,
// so we create a Safe with 0 owners and threshold 1.
// This is an unusable Safe, perfect for the singleton
threshold = 1;
}
/// @dev Setup function sets initial storage of contract.
/// @param _owners List of Safe owners.
/// @param _threshold Number of required confirmations for a Safe transaction.
/// @param to Contract address for optional delegate call.
/// @param data Data payload for optional delegate call.
/// @param fallbackHandler Handler for fallback calls to this contract
/// @param paymentToken Token that should be used for the payment (0 is ETH)
/// @param payment Value that should be paid
/// @param paymentReceiver Adddress that should receive the payment (or 0 if tx.origin)
function setup(
address[] calldata _owners,
uint256 _threshold,
address to,
bytes calldata data,
address fallbackHandler,
address paymentToken,
uint256 payment,
address payable paymentReceiver
) external {
// setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice
setupOwners(_owners, _threshold);
if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler);
// As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules
setupModules(to, data);
if (payment > 0) {
// To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself)
// baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment
handlePayment(payment, 0, 1, paymentToken, paymentReceiver);
}
emit SafeSetup(msg.sender, _owners, _threshold, to, fallbackHandler);
}
/// @dev Allows to execute a Safe transaction confirmed by required number of owners and then pays the account that submitted the transaction.
/// Note: The fees are always transferred, even if the user transaction fails.
/// @param to Destination address of Safe transaction.
/// @param value Ether value of Safe transaction.
/// @param data Data payload of Safe transaction.
/// @param operation Operation type of Safe transaction.
/// @param safeTxGas Gas that should be used for the Safe transaction.
/// @param baseGas Gas costs that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
/// @param gasPrice Gas price that should be used for the payment calculation.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
function execTransaction(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures
) public payable virtual returns (bool success) {
bytes32 txHash;
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
bytes memory txHashData =
encodeTransactionData(
// Transaction info
to,
value,
data,
operation,
safeTxGas,
// Payment info
baseGas,
gasPrice,
gasToken,
refundReceiver,
// Signature info
nonce
);
// Increase nonce and execute transaction.
nonce++;
txHash = keccak256(txHashData);
checkSignatures(txHash, txHashData, signatures);
}
address guard = getGuard();
{
if (guard != address(0)) {
Guard(guard).checkTransaction(
// Transaction info
to,
value,
data,
operation,
safeTxGas,
// Payment info
baseGas,
gasPrice,
gasToken,
refundReceiver,
// Signature info
signatures,
msg.sender
);
}
}
// We require some gas to emit the events (at least 2500) after the execution and some to perform code until the execution (500)
// We also include the 1/64 in the check that is not send along with a call to counteract potential shortings because of EIP-150
require(gasleft() >= ((safeTxGas * 64) / 63).max(safeTxGas + 2500) + 500, "GS010");
// Use scope here to limit variable lifetime and prevent `stack too deep` errors
{
uint256 gasUsed = gasleft();
// If the gasPrice is 0 we assume that nearly all available gas can be used (it is always more than safeTxGas)
// We only substract 2500 (compared to the 3000 before) to ensure that the amount passed is still higher than safeTxGas
success = execute(to, value, data, operation, gasPrice == 0 ? (gasleft() - 2500) : safeTxGas);
gasUsed = gasUsed.sub(gasleft());
// If no safeTxGas and no gasPrice was set (e.g. both are 0), then the internal tx is required to be successful
// This makes it possible to use `estimateGas` without issues, as it searches for the minimum gas where the tx doesn't revert
require(success || safeTxGas != 0 || gasPrice != 0, "GS013");
// We transfer the calculated tx costs to the tx.origin to avoid sending it to intermediate contracts that have made calls
uint256 payment = 0;
if (gasPrice > 0) {
payment = handlePayment(gasUsed, baseGas, gasPrice, gasToken, refundReceiver);
}
if (success) emit ExecutionSuccess(txHash, payment);
else emit ExecutionFailure(txHash, payment);
}
{
if (guard != address(0)) {
Guard(guard).checkAfterExecution(txHash, success);
}
}
}
function handlePayment(
uint256 gasUsed,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver
) private returns (uint256 payment) {
// solhint-disable-next-line avoid-tx-origin
address payable receiver = refundReceiver == address(0) ? payable(tx.origin) : refundReceiver;
if (gasToken == address(0)) {
// For ETH we will only adjust the gas price to not be higher than the actual used gas price
payment = gasUsed.add(baseGas).mul(gasPrice < tx.gasprice ? gasPrice : tx.gasprice);
require(receiver.send(payment), "GS011");
} else {
payment = gasUsed.add(baseGas).mul(gasPrice);
require(transferToken(gasToken, receiver, payment), "GS012");
}
}
/**
* @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
* @param dataHash Hash of the data (could be either a message hash or transaction hash)
* @param data That should be signed (this is passed to an external validator contract)
* @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
*/
function checkSignatures(
bytes32 dataHash,
bytes memory data,
bytes memory signatures
) public view {
// Load threshold to avoid multiple storage loads
uint256 _threshold = threshold;
// Check that a threshold is set
require(_threshold > 0, "GS001");
checkNSignatures(dataHash, data, signatures, _threshold);
}
/**
* @dev Checks whether the signature provided is valid for the provided data, hash. Will revert otherwise.
* @param dataHash Hash of the data (could be either a message hash or transaction hash)
* @param data That should be signed (this is passed to an external validator contract)
* @param signatures Signature data that should be verified. Can be ECDSA signature, contract signature (EIP-1271) or approved hash.
* @param requiredSignatures Amount of required valid signatures.
*/
function checkNSignatures(
bytes32 dataHash,
bytes memory data,
bytes memory signatures,
uint256 requiredSignatures
) public view {
// Check that the provided signature data is not too short
require(signatures.length >= requiredSignatures.mul(65), "GS020");
// There cannot be an owner with address 0.
address lastOwner = address(0);
address currentOwner;
uint8 v;
bytes32 r;
bytes32 s;
uint256 i;
for (i = 0; i < requiredSignatures; i++) {
(v, r, s) = signatureSplit(signatures, i);
if (v == 0) {
// If v is 0 then it is a contract signature
// When handling contract signatures the address of the contract is encoded into r
currentOwner = address(uint160(uint256(r)));
// Check that signature data pointer (s) is not pointing inside the static part of the signatures bytes
// This check is not completely accurate, since it is possible that more signatures than the threshold are send.
// Here we only check that the pointer is not pointing inside the part that is being processed
require(uint256(s) >= requiredSignatures.mul(65), "GS021");
// Check that signature data pointer (s) is in bounds (points to the length of data -> 32 bytes)
require(uint256(s).add(32) <= signatures.length, "GS022");
// Check if the contract signature is in bounds: start of data is s + 32 and end is start + signature length
uint256 contractSignatureLen;
// solhint-disable-next-line no-inline-assembly
assembly {
contractSignatureLen := mload(add(add(signatures, s), 0x20))
}
require(uint256(s).add(32).add(contractSignatureLen) <= signatures.length, "GS023");
// Check signature
bytes memory contractSignature;
// solhint-disable-next-line no-inline-assembly
assembly {
// The signature data for contract signatures is appended to the concatenated signatures and the offset is stored in s
contractSignature := add(add(signatures, s), 0x20)
}
require(ISignatureValidator(currentOwner).isValidSignature(data, contractSignature) == EIP1271_MAGIC_VALUE, "GS024");
} else if (v == 1) {
// If v is 1 then it is an approved hash
// When handling approved hashes the address of the approver is encoded into r
currentOwner = address(uint160(uint256(r)));
// Hashes are automatically approved by the sender of the message or when they have been pre-approved via a separate transaction
require(msg.sender == currentOwner || approvedHashes[currentOwner][dataHash] != 0, "GS025");
} else if (v > 30) {
// If v > 30 then default va (27,28) has been adjusted for eth_sign flow
// To support eth_sign and similar we adjust v and hash the messageHash with the Ethereum message prefix before applying ecrecover
currentOwner = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", dataHash)), v - 4, r, s);
} else {
// Default is the ecrecover flow with the provided data hash
// Use ecrecover with the messageHash for EOA signatures
currentOwner = ecrecover(dataHash, v, r, s);
}
require(currentOwner > lastOwner && owners[currentOwner] != address(0) && currentOwner != SENTINEL_OWNERS, "GS026");
lastOwner = currentOwner;
}
}
/// @dev Allows to estimate a Safe transaction.
/// This method is only meant for estimation purpose, therefore the call will always revert and encode the result in the revert data.
/// Since the `estimateGas` function includes refunds, call this method to get an estimated of the costs that are deducted from the safe with `execTransaction`
/// @param to Destination address of Safe transaction.
/// @param value Ether value of Safe transaction.
/// @param data Data payload of Safe transaction.
/// @param operation Operation type of Safe transaction.
/// @return Estimate without refunds and overhead fees (base transaction and payload data gas costs).
/// @notice Deprecated in favor of common/StorageAccessible.sol and will be removed in next version.
function requiredTxGas(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation
) external returns (uint256) {
uint256 startGas = gasleft();
// We don't provide an error message here, as we use it to return the estimate
require(execute(to, value, data, operation, gasleft()));
uint256 requiredGas = startGas - gasleft();
// Convert response to string and return via error message
revert(string(abi.encodePacked(requiredGas)));
}
/**
* @dev Marks a hash as approved. This can be used to validate a hash that is used by a signature.
* @param hashToApprove The hash that should be marked as approved for signatures that are verified by this contract.
*/
function approveHash(bytes32 hashToApprove) external {
require(owners[msg.sender] != address(0), "GS030");
approvedHashes[msg.sender][hashToApprove] = 1;
emit ApproveHash(hashToApprove, msg.sender);
}
/// @dev Returns the chain id used by this contract.
function getChainId() public view returns (uint256) {
uint256 id;
// solhint-disable-next-line no-inline-assembly
assembly {
id := chainid()
}
return id;
}
function domainSeparator() public view returns (bytes32) {
return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, getChainId(), this));
}
/// @dev Returns the bytes that are hashed to be signed by owners.
/// @param to Destination address.
/// @param value Ether value.
/// @param data Data payload.
/// @param operation Operation type.
/// @param safeTxGas Gas that should be used for the safe transaction.
/// @param baseGas Gas costs for that are independent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
/// @param gasPrice Maximum gas price that should be used for this transaction.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param _nonce Transaction nonce.
/// @return Transaction hash bytes.
function encodeTransactionData(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) public view returns (bytes memory) {
bytes32 safeTxHash =
keccak256(
abi.encode(
SAFE_TX_TYPEHASH,
to,
value,
keccak256(data),
operation,
safeTxGas,
baseGas,
gasPrice,
gasToken,
refundReceiver,
_nonce
)
);
return abi.encodePacked(bytes1(0x19), bytes1(0x01), domainSeparator(), safeTxHash);
}
/// @dev Returns hash to be signed by owners.
/// @param to Destination address.
/// @param value Ether value.
/// @param data Data payload.
/// @param operation Operation type.
/// @param safeTxGas Fas that should be used for the safe transaction.
/// @param baseGas Gas costs for data used to trigger the safe transaction.
/// @param gasPrice Maximum gas price that should be used for this transaction.
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
/// @param _nonce Transaction nonce.
/// @return Transaction hash.
function getTransactionHash(
address to,
uint256 value,
bytes calldata data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) public view returns (bytes32) {
return keccak256(encodeTransactionData(to, value, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, _nonce));
}
}
contracts/base/Executor.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
/// @title Executor - A contract that can execute transactions
/// @author Richard Meissner - <richard@gnosis.pm>
contract Executor {
function execute(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 txGas
) internal returns (bool success) {
if (operation == Enum.Operation.DelegateCall) {
// solhint-disable-next-line no-inline-assembly
assembly {
success := delegatecall(txGas, to, add(data, 0x20), mload(data), 0, 0)
}
} else {
// solhint-disable-next-line no-inline-assembly
assembly {
success := call(txGas, to, value, add(data, 0x20), mload(data), 0, 0)
}
}
}
}
contracts/base/FallbackManager.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "../common/SelfAuthorized.sol";
/// @title Fallback Manager - A contract that manages fallback calls made to this contract
/// @author Richard Meissner - <richard@gnosis.pm>
contract FallbackManager is SelfAuthorized {
event ChangedFallbackHandler(address handler);
// keccak256("fallback_manager.handler.address")
bytes32 internal constant FALLBACK_HANDLER_STORAGE_SLOT = 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5;
function internalSetFallbackHandler(address handler) internal {
bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, handler)
}
}
/// @dev Allows to add a contract to handle fallback calls.
/// Only fallback calls without value and with data will be forwarded.
/// This can only be done via a Safe transaction.
/// @param handler contract to handle fallbacks calls.
function setFallbackHandler(address handler) public authorized {
internalSetFallbackHandler(handler);
emit ChangedFallbackHandler(handler);
}
// solhint-disable-next-line payable-fallback,no-complex-fallback
fallback() external {
bytes32 slot = FALLBACK_HANDLER_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
let handler := sload(slot)
if iszero(handler) {
return(0, 0)
}
calldatacopy(0, 0, calldatasize())
// The msg.sender address is shifted to the left by 12 bytes to remove the padding
// Then the address without padding is stored right after the calldata
mstore(calldatasize(), shl(96, caller()))
// Add 20 bytes for the address appended add the end
let success := call(gas(), handler, 0, 0, add(calldatasize(), 20), 0, 0)
returndatacopy(0, 0, returndatasize())
if iszero(success) {
revert(0, returndatasize())
}
return(0, returndatasize())
}
}
}
contracts/base/GuardManager.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
interface Guard {
function checkTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address payable refundReceiver,
bytes memory signatures,
address msgSender
) external;
function checkAfterExecution(bytes32 txHash, bool success) external;
}
/// @title Fallback Manager - A contract that manages fallback calls made to this contract
/// @author Richard Meissner - <richard@gnosis.pm>
contract GuardManager is SelfAuthorized {
event ChangedGuard(address guard);
// keccak256("guard_manager.guard.address")
bytes32 internal constant GUARD_STORAGE_SLOT = 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8;
/// @dev Set a guard that checks transactions before execution
/// @param guard The address of the guard to be used or the 0 address to disable the guard
function setGuard(address guard) external authorized {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
sstore(slot, guard)
}
emit ChangedGuard(guard);
}
function getGuard() internal view returns (address guard) {
bytes32 slot = GUARD_STORAGE_SLOT;
// solhint-disable-next-line no-inline-assembly
assembly {
guard := sload(slot)
}
}
}
contracts/base/ModuleManager.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
import "./Executor.sol";
/// @title Module Manager - A contract that manages modules that can execute transactions via this contract
/// @author Stefan George - <stefan@gnosis.pm>
/// @author Richard Meissner - <richard@gnosis.pm>
contract ModuleManager is SelfAuthorized, Executor {
event EnabledModule(address module);
event DisabledModule(address module);
event ExecutionFromModuleSuccess(address indexed module);
event ExecutionFromModuleFailure(address indexed module);
address internal constant SENTINEL_MODULES = address(0x1);
mapping(address => address) internal modules;
function setupModules(address to, bytes memory data) internal {
require(modules[SENTINEL_MODULES] == address(0), "GS100");
modules[SENTINEL_MODULES] = SENTINEL_MODULES;
if (to != address(0))
// Setup has to complete successfully or transaction fails.
require(execute(to, 0, data, Enum.Operation.DelegateCall, gasleft()), "GS000");
}
/// @dev Allows to add a module to the whitelist.
/// This can only be done via a Safe transaction.
/// @notice Enables the module `module` for the Safe.
/// @param module Module to be whitelisted.
function enableModule(address module) public authorized {
// Module address cannot be null or sentinel.
require(module != address(0) && module != SENTINEL_MODULES, "GS101");
// Module cannot be added twice.
require(modules[module] == address(0), "GS102");
modules[module] = modules[SENTINEL_MODULES];
modules[SENTINEL_MODULES] = module;
emit EnabledModule(module);
}
/// @dev Allows to remove a module from the whitelist.
/// This can only be done via a Safe transaction.
/// @notice Disables the module `module` for the Safe.
/// @param prevModule Module that pointed to the module to be removed in the linked list
/// @param module Module to be removed.
function disableModule(address prevModule, address module) public authorized {
// Validate module address and check that it corresponds to module index.
require(module != address(0) && module != SENTINEL_MODULES, "GS101");
require(modules[prevModule] == module, "GS103");
modules[prevModule] = modules[module];
modules[module] = address(0);
emit DisabledModule(module);
}
/// @dev Allows a Module to execute a Safe transaction without any further confirmations.
/// @param to Destination address of module transaction.
/// @param value Ether value of module transaction.
/// @param data Data payload of module transaction.
/// @param operation Operation type of module transaction.
function execTransactionFromModule(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) public virtual returns (bool success) {
// Only whitelisted modules are allowed.
require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104");
// Execute transaction without further confirmations.
success = execute(to, value, data, operation, gasleft());
if (success) emit ExecutionFromModuleSuccess(msg.sender);
else emit ExecutionFromModuleFailure(msg.sender);
}
/// @dev Allows a Module to execute a Safe transaction without any further confirmations and return data
/// @param to Destination address of module transaction.
/// @param value Ether value of module transaction.
/// @param data Data payload of module transaction.
/// @param operation Operation type of module transaction.
function execTransactionFromModuleReturnData(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation
) public returns (bool success, bytes memory returnData) {
success = execTransactionFromModule(to, value, data, operation);
// solhint-disable-next-line no-inline-assembly
assembly {
// Load free memory location
let ptr := mload(0x40)
// We allocate memory for the return data by setting the free memory location to
// current free memory location + data size + 32 bytes for data size value
mstore(0x40, add(ptr, add(returndatasize(), 0x20)))
// Store the size
mstore(ptr, returndatasize())
// Store the data
returndatacopy(add(ptr, 0x20), 0, returndatasize())
// Point the return data to the correct memory location
returnData := ptr
}
}
/// @dev Returns if an module is enabled
/// @return True if the module is enabled
function isModuleEnabled(address module) public view returns (bool) {
return SENTINEL_MODULES != module && modules[module] != address(0);
}
/// @dev Returns array of modules.
/// @param start Start of the page.
/// @param pageSize Maximum number of modules that should be returned.
/// @return array Array of modules.
/// @return next Start of the next page.
function getModulesPaginated(address start, uint256 pageSize) external view returns (address[] memory array, address next) {
// Init array with max page size
array = new address[](pageSize);
// Populate return array
uint256 moduleCount = 0;
address currentModule = modules[start];
while (currentModule != address(0x0) && currentModule != SENTINEL_MODULES && moduleCount < pageSize) {
array[moduleCount] = currentModule;
currentModule = modules[currentModule];
moduleCount++;
}
next = currentModule;
// Set correct size of returned array
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(array, moduleCount)
}
}
}
contracts/base/OwnerManager.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "../common/SelfAuthorized.sol";
/// @title OwnerManager - Manages a set of owners and a threshold to perform actions.
/// @author Stefan George - <stefan@gnosis.pm>
/// @author Richard Meissner - <richard@gnosis.pm>
contract OwnerManager is SelfAuthorized {
event AddedOwner(address owner);
event RemovedOwner(address owner);
event ChangedThreshold(uint256 threshold);
address internal constant SENTINEL_OWNERS = address(0x1);
mapping(address => address) internal owners;
uint256 internal ownerCount;
uint256 internal threshold;
/// @dev Setup function sets initial storage of contract.
/// @param _owners List of Safe owners.
/// @param _threshold Number of required confirmations for a Safe transaction.
function setupOwners(address[] memory _owners, uint256 _threshold) internal {
// Threshold can only be 0 at initialization.
// Check ensures that setup function can only be called once.
require(threshold == 0, "GS200");
// Validate that threshold is smaller than number of added owners.
require(_threshold <= _owners.length, "GS201");
// There has to be at least one Safe owner.
require(_threshold >= 1, "GS202");
// Initializing Safe owners.
address currentOwner = SENTINEL_OWNERS;
for (uint256 i = 0; i < _owners.length; i++) {
// Owner address cannot be null.
address owner = _owners[i];
require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this) && currentOwner != owner, "GS203");
// No duplicate owners allowed.
require(owners[owner] == address(0), "GS204");
owners[currentOwner] = owner;
currentOwner = owner;
}
owners[currentOwner] = SENTINEL_OWNERS;
ownerCount = _owners.length;
threshold = _threshold;
}
/// @dev Allows to add a new owner to the Safe and update the threshold at the same time.
/// This can only be done via a Safe transaction.
/// @notice Adds the owner `owner` to the Safe and updates the threshold to `_threshold`.
/// @param owner New owner address.
/// @param _threshold New threshold.
function addOwnerWithThreshold(address owner, uint256 _threshold) public authorized {
// Owner address cannot be null, the sentinel or the Safe itself.
require(owner != address(0) && owner != SENTINEL_OWNERS && owner != address(this), "GS203");
// No duplicate owners allowed.
require(owners[owner] == address(0), "GS204");
owners[owner] = owners[SENTINEL_OWNERS];
owners[SENTINEL_OWNERS] = owner;
ownerCount++;
emit AddedOwner(owner);
// Change threshold if threshold was changed.
if (threshold != _threshold) changeThreshold(_threshold);
}
/// @dev Allows to remove an owner from the Safe and update the threshold at the same time.
/// This can only be done via a Safe transaction.
/// @notice Removes the owner `owner` from the Safe and updates the threshold to `_threshold`.
/// @param prevOwner Owner that pointed to the owner to be removed in the linked list
/// @param owner Owner address to be removed.
/// @param _threshold New threshold.
function removeOwner(
address prevOwner,
address owner,
uint256 _threshold
) public authorized {
// Only allow to remove an owner, if threshold can still be reached.
require(ownerCount - 1 >= _threshold, "GS201");
// Validate owner address and check that it corresponds to owner index.
require(owner != address(0) && owner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == owner, "GS205");
owners[prevOwner] = owners[owner];
owners[owner] = address(0);
ownerCount--;
emit RemovedOwner(owner);
// Change threshold if threshold was changed.
if (threshold != _threshold) changeThreshold(_threshold);
}
/// @dev Allows to swap/replace an owner from the Safe with another address.
/// This can only be done via a Safe transaction.
/// @notice Replaces the owner `oldOwner` in the Safe with `newOwner`.
/// @param prevOwner Owner that pointed to the owner to be replaced in the linked list
/// @param oldOwner Owner address to be replaced.
/// @param newOwner New owner address.
function swapOwner(
address prevOwner,
address oldOwner,
address newOwner
) public authorized {
// Owner address cannot be null, the sentinel or the Safe itself.
require(newOwner != address(0) && newOwner != SENTINEL_OWNERS && newOwner != address(this), "GS203");
// No duplicate owners allowed.
require(owners[newOwner] == address(0), "GS204");
// Validate oldOwner address and check that it corresponds to owner index.
require(oldOwner != address(0) && oldOwner != SENTINEL_OWNERS, "GS203");
require(owners[prevOwner] == oldOwner, "GS205");
owners[newOwner] = owners[oldOwner];
owners[prevOwner] = newOwner;
owners[oldOwner] = address(0);
emit RemovedOwner(oldOwner);
emit AddedOwner(newOwner);
}
/// @dev Allows to update the number of required confirmations by Safe owners.
/// This can only be done via a Safe transaction.
/// @notice Changes the threshold of the Safe to `_threshold`.
/// @param _threshold New threshold.
function changeThreshold(uint256 _threshold) public authorized {
// Validate that threshold is smaller than number of owners.
require(_threshold <= ownerCount, "GS201");
// There has to be at least one Safe owner.
require(_threshold >= 1, "GS202");
threshold = _threshold;
emit ChangedThreshold(threshold);
}
function getThreshold() public view returns (uint256) {
return threshold;
}
function isOwner(address owner) public view returns (bool) {
return owner != SENTINEL_OWNERS && owners[owner] != address(0);
}
/// @dev Returns array of owners.
/// @return Array of Safe owners.
function getOwners() public view returns (address[] memory) {
address[] memory array = new address[](ownerCount);
// populate return array
uint256 index = 0;
address currentOwner = owners[SENTINEL_OWNERS];
while (currentOwner != SENTINEL_OWNERS) {
array[index] = currentOwner;
currentOwner = owners[currentOwner];
index++;
}
return array;
}
}
contracts/common/Enum.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title Enum - Collection of enums
/// @author Richard Meissner - <richard@gnosis.pm>
contract Enum {
enum Operation {Call, DelegateCall}
}
contracts/common/EtherPaymentFallback.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title EtherPaymentFallback - A contract that has a fallback to accept ether payments
/// @author Richard Meissner - <richard@gnosis.pm>
contract EtherPaymentFallback {
event SafeReceived(address indexed sender, uint256 value);
/// @dev Fallback function accepts Ether transactions.
receive() external payable {
emit SafeReceived(msg.sender, msg.value);
}
}
contracts/common/SecuredTokenTransfer.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title SecuredTokenTransfer - Secure token transfer
/// @author Richard Meissner - <richard@gnosis.pm>
contract SecuredTokenTransfer {
/// @dev Transfers a token and returns if it was a success
/// @param token Token that should be transferred
/// @param receiver Receiver to whom the token should be transferred
/// @param amount The amount of tokens that should be transferred
function transferToken(
address token,
address receiver,
uint256 amount
) internal returns (bool transferred) {
// 0xa9059cbb - keccack("transfer(address,uint256)")
bytes memory data = abi.encodeWithSelector(0xa9059cbb, receiver, amount);
// solhint-disable-next-line no-inline-assembly
assembly {
// We write the return value to scratch space.
// See https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory
let success := call(sub(gas(), 10000), token, 0, add(data, 0x20), mload(data), 0, 0x20)
switch returndatasize()
case 0 {
transferred := success
}
case 0x20 {
transferred := iszero(or(iszero(success), iszero(mload(0))))
}
default {
transferred := 0
}
}
}
}
contracts/common/SelfAuthorized.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title SelfAuthorized - authorizes current contract to perform actions
/// @author Richard Meissner - <richard@gnosis.pm>
contract SelfAuthorized {
function requireSelfCall() private view {
require(msg.sender == address(this), "GS031");
}
modifier authorized() {
// This is a function call as it minimized the bytecode size
requireSelfCall();
_;
}
}
contracts/common/SignatureDecoder.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title SignatureDecoder - Decodes signatures that a encoded as bytes
/// @author Richard Meissner - <richard@gnosis.pm>
contract SignatureDecoder {
/// @dev divides bytes signature into `uint8 v, bytes32 r, bytes32 s`.
/// @notice Make sure to peform a bounds check for @param pos, to avoid out of bounds access on @param signatures
/// @param pos which signature to read. A prior bounds check of this parameter should be performed, to avoid out of bounds access
/// @param signatures concatenated rsv signatures
function signatureSplit(bytes memory signatures, uint256 pos)
internal
pure
returns (
uint8 v,
bytes32 r,
bytes32 s
)
{
// The signature format is a compact form of:
// {bytes32 r}{bytes32 s}{uint8 v}
// Compact means, uint8 is not padded to 32 bytes.
// solhint-disable-next-line no-inline-assembly
assembly {
let signaturePos := mul(0x41, pos)
r := mload(add(signatures, add(signaturePos, 0x20)))
s := mload(add(signatures, add(signaturePos, 0x40)))
// Here we are loading the last 32 bytes, including 31 bytes
// of 's'. There is no 'mload8' to do this.
//
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
v := and(mload(add(signatures, add(signaturePos, 0x41))), 0xff)
}
}
}
contracts/common/Singleton.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title Singleton - Base for singleton contracts (should always be first super contract)
/// This contract is tightly coupled to our proxy contract (see `proxies/GnosisSafeProxy.sol`)
/// @author Richard Meissner - <richard@gnosis.io>
contract Singleton {
// singleton always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.
// It should also always be ensured that the address is stored alone (uses a full word)
address private singleton;
}
contracts/common/StorageAccessible.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
/// @notice See https://github.com/gnosis/util-contracts/blob/bb5fe5fb5df6d8400998094fb1b32a178a47c3a1/contracts/StorageAccessible.sol
contract StorageAccessible {
/**
* @dev Reads `length` bytes of storage in the currents contract
* @param offset - the offset in the current contract's storage in words to start reading from
* @param length - the number of words (32 bytes) of data to read
* @return the bytes that were read.
*/
function getStorageAt(uint256 offset, uint256 length) public view returns (bytes memory) {
bytes memory result = new bytes(length * 32);
for (uint256 index = 0; index < length; index++) {
// solhint-disable-next-line no-inline-assembly
assembly {
let word := sload(add(offset, index))
mstore(add(add(result, 0x20), mul(index, 0x20)), word)
}
}
return result;
}
/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static).
*
* This method reverts with data equal to `abi.encode(bool(success), bytes(response))`.
* Specifically, the `returndata` after a call to this method will be:
* `success:bool || response.length:uint256 || response:bytes`.
*
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateAndRevert(address targetContract, bytes memory calldataPayload) external {
// solhint-disable-next-line no-inline-assembly
assembly {
let success := delegatecall(gas(), targetContract, add(calldataPayload, 0x20), mload(calldataPayload), 0, 0)
mstore(0x00, success)
mstore(0x20, returndatasize())
returndatacopy(0x40, 0, returndatasize())
revert(0, add(returndatasize(), 0x40))
}
}
}
interfaces/ISignatureValidator.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract ISignatureValidatorConstants {
// bytes4(keccak256("isValidSignature(bytes,bytes)")
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
}
abstract contract ISignatureValidator is ISignatureValidatorConstants {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param _data Arbitrary length data signed on the behalf of address(this)
* @param _signature Signature byte array associated with _data
*
* MUST return the bytes4 magic value 0x20c13b0b when function passes.
* MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for solc > 0.5)
* MUST allow external calls
*/
function isValidSignature(bytes memory _data, bytes memory _signature) public view virtual returns (bytes4);
}
libraries/GnosisSafeMath.sol
// SPDX-License-Identifier: LGPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title GnosisSafeMath
* @dev Math operations with safety checks that revert on error
* Renamed from SafeMath to GnosisSafeMath to avoid conflicts
* TODO: remove once open zeppelin update to solc 0.5.0
*/
library GnosisSafeMath {
/**
* @dev Multiplies two numbers, reverts on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
/**
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
/**
* @dev Adds two numbers, reverts on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"event","name":"AddedOwner","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ApproveHash","inputs":[{"type":"bytes32","name":"approvedHash","internalType":"bytes32","indexed":true},{"type":"address","name":"owner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ChangedFallbackHandler","inputs":[{"type":"address","name":"handler","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ChangedGuard","inputs":[{"type":"address","name":"guard","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ChangedThreshold","inputs":[{"type":"uint256","name":"threshold","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"DisabledModule","inputs":[{"type":"address","name":"module","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"EnabledModule","inputs":[{"type":"address","name":"module","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionFailure","inputs":[{"type":"bytes32","name":"txHash","internalType":"bytes32","indexed":false},{"type":"uint256","name":"payment","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ExecutionFromModuleFailure","inputs":[{"type":"address","name":"module","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionFromModuleSuccess","inputs":[{"type":"address","name":"module","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ExecutionSuccess","inputs":[{"type":"bytes32","name":"txHash","internalType":"bytes32","indexed":false},{"type":"uint256","name":"payment","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RemovedOwner","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SafeModuleTransaction","inputs":[{"type":"address","name":"module","internalType":"address","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},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation","indexed":false}],"anonymous":false},{"type":"event","name":"SafeMultiSigTransaction","inputs":[{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"uint256","name":"value","internalType":"uint256","indexed":false},{"type":"bytes","name":"data","internalType":"bytes","indexed":false},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation","indexed":false},{"type":"uint256","name":"safeTxGas","internalType":"uint256","indexed":false},{"type":"uint256","name":"baseGas","internalType":"uint256","indexed":false},{"type":"uint256","name":"gasPrice","internalType":"uint256","indexed":false},{"type":"address","name":"gasToken","internalType":"address","indexed":false},{"type":"address","name":"refundReceiver","internalType":"address payable","indexed":false},{"type":"bytes","name":"signatures","internalType":"bytes","indexed":false},{"type":"bytes","name":"additionalInfo","internalType":"bytes","indexed":false}],"anonymous":false},{"type":"event","name":"SafeReceived","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SafeSetup","inputs":[{"type":"address","name":"initiator","internalType":"address","indexed":true},{"type":"address[]","name":"owners","internalType":"address[]","indexed":false},{"type":"uint256","name":"threshold","internalType":"uint256","indexed":false},{"type":"address","name":"initializer","internalType":"address","indexed":false},{"type":"address","name":"fallbackHandler","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"SignMsg","inputs":[{"type":"bytes32","name":"msgHash","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"fallback","stateMutability":"nonpayable"},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"VERSION","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addOwnerWithThreshold","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"approveHash","inputs":[{"type":"bytes32","name":"hashToApprove","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"approvedHashes","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeThreshold","inputs":[{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkNSignatures","inputs":[{"type":"bytes32","name":"dataHash","internalType":"bytes32"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes","name":"signatures","internalType":"bytes"},{"type":"uint256","name":"requiredSignatures","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[],"name":"checkSignatures","inputs":[{"type":"bytes32","name":"dataHash","internalType":"bytes32"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"bytes","name":"signatures","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableModule","inputs":[{"type":"address","name":"prevModule","internalType":"address"},{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"domainSeparator","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"enableModule","inputs":[{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"encodeTransactionData","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address"},{"type":"uint256","name":"_nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"execTransaction","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address payable"},{"type":"bytes","name":"signatures","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"success","internalType":"bool"}],"name":"execTransactionFromModule","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}],"name":"execTransactionFromModuleReturnData","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getChainId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"array","internalType":"address[]"},{"type":"address","name":"next","internalType":"address"}],"name":"getModulesPaginated","inputs":[{"type":"address","name":"start","internalType":"address"},{"type":"uint256","name":"pageSize","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getOwners","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"getStorageAt","inputs":[{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"length","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getTransactionHash","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"},{"type":"uint256","name":"safeTxGas","internalType":"uint256"},{"type":"uint256","name":"baseGas","internalType":"uint256"},{"type":"uint256","name":"gasPrice","internalType":"uint256"},{"type":"address","name":"gasToken","internalType":"address"},{"type":"address","name":"refundReceiver","internalType":"address"},{"type":"uint256","name":"_nonce","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isModuleEnabled","inputs":[{"type":"address","name":"module","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonce","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeOwner","inputs":[{"type":"address","name":"prevOwner","internalType":"address"},{"type":"address","name":"owner","internalType":"address"},{"type":"uint256","name":"_threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"requiredTxGas","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"uint8","name":"operation","internalType":"enum Enum.Operation"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFallbackHandler","inputs":[{"type":"address","name":"handler","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setGuard","inputs":[{"type":"address","name":"guard","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setup","inputs":[{"type":"address[]","name":"_owners","internalType":"address[]"},{"type":"uint256","name":"_threshold","internalType":"uint256"},{"type":"address","name":"to","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"},{"type":"address","name":"fallbackHandler","internalType":"address"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"uint256","name":"payment","internalType":"uint256"},{"type":"address","name":"paymentReceiver","internalType":"address payable"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signedMessages","inputs":[{"type":"bytes32","name":"","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"simulateAndRevert","inputs":[{"type":"address","name":"targetContract","internalType":"address"},{"type":"bytes","name":"calldataPayload","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"swapOwner","inputs":[{"type":"address","name":"prevOwner","internalType":"address"},{"type":"address","name":"oldOwner","internalType":"address"},{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x608060405234801561001057600080fd5b506001600455613688806100256000396000f3fe6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314611078578063f698da25146110ab578063f8dc5dd9146110c0578063ffa1ad741461110357610219565b8063e19a9dd914610f26578063e318b52b14610f59578063e75235b814610f9e578063e86637db14610fb357610219565b8063cc2f8452116100d1578063cc2f845214610d5f578063d4d9bdcd14610dfc578063d8d11f7814610e26578063e009cfde14610eeb57610219565b8063affed0e014610af6578063b4faba0914610b0b578063b63e800d14610bcc578063c4ca3a9c14610ccc57610219565b80635624b25b1161017a5780636a761202116101495780636a761202146107dd5780637d8329741461091b578063934f3a1114610954578063a0e67e2b14610a9157610219565b80635624b25b146106b15780635ae6bd3714610756578063610b592514610780578063694e80c3146107b357610219565b80632f54bf6e116101b65780632f54bf6e146104405780633408e47014610473578063468721a71461049a5780635229073f1461056557610219565b80630d582f131461027f57806312fb68e0146102ba5780632d9ad53d146103f957610219565b366102195760408051348152905133917f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d919081900360200190a2005b34801561022557600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061025057005b36600080373360601b365260008060143601600080855af190503d6000803e80610279573d6000fd5b503d6000f35b34801561028b57600080fd5b506102b8600480360360408110156102a257600080fd5b506001600160a01b038135169060200135611118565b005b3480156102c657600080fd5b506102b8600480360360808110156102dd57600080fd5b81359190810190604081016020820135600160201b8111156102fe57600080fd5b82018360208201111561031057600080fd5b803590602001918460018302840111600160201b8311171561033157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561038357600080fd5b82018360208201111561039557600080fd5b803590602001918460018302840111600160201b831117156103b657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925061129a915050565b34801561040557600080fd5b5061042c6004803603602081101561041c57600080fd5b50356001600160a01b03166117f8565b604080519115158252519081900360200190f35b34801561044c57600080fd5b5061042c6004803603602081101561046357600080fd5b50356001600160a01b0316611833565b34801561047f57600080fd5b5061048861186b565b60408051918252519081900360200190f35b3480156104a657600080fd5b5061042c600480360360808110156104bd57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460018302840111600160201b8311171561051f57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061186f9050565b34801561057157600080fd5b506106306004803603608081101561058857600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156105b757600080fd5b8201836020820111156105c957600080fd5b803590602001918460018302840111600160201b831117156105ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061195c9050565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561067557818101518382015260200161065d565b50505050905090810190601f1680156106a25780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156106bd57600080fd5b506106e1600480360360408110156106d457600080fd5b5080359060200135611992565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561071b578181015183820152602001610703565b50505050905090810190601f1680156107485780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561076257600080fd5b506104886004803603602081101561077957600080fd5b5035611a06565b34801561078c57600080fd5b506102b8600480360360208110156107a357600080fd5b50356001600160a01b0316611a18565b3480156107bf57600080fd5b506102b8600480360360208110156107d657600080fd5b5035611b64565b61042c60048036036101408110156107f457600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561082357600080fd5b82018360208201111561083557600080fd5b803590602001918460018302840111600160201b8311171561085657600080fd5b9193909260ff833516926020810135926040820135926060830135926001600160a01b03608082013581169360a083013590911692909160e081019060c00135600160201b8111156108a757600080fd5b8201836020820111156108b957600080fd5b803590602001918460018302840111600160201b831117156108da57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c24945050505050565b34801561092757600080fd5b506104886004803603604081101561093e57600080fd5b506001600160a01b038135169060200135611e23565b34801561096057600080fd5b506102b86004803603606081101561097757600080fd5b81359190810190604081016020820135600160201b81111561099857600080fd5b8201836020820111156109aa57600080fd5b803590602001918460018302840111600160201b831117156109cb57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1d57600080fd5b820183602082011115610a2f57600080fd5b803590602001918460018302840111600160201b83111715610a5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e40945050505050565b348015610a9d57600080fd5b50610aa6611e8f565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610ae2578181015183820152602001610aca565b505050509050019250505060405180910390f35b348015610b0257600080fd5b50610488611f73565b348015610b1757600080fd5b506102b860048036036040811015610b2e57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610b5857600080fd5b820183602082011115610b6a57600080fd5b803590602001918460018302840111600160201b83111715610b8b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611f79945050505050565b348015610bd857600080fd5b506102b86004803603610100811015610bf057600080fd5b810190602081018135600160201b811115610c0a57600080fd5b820183602082011115610c1c57600080fd5b803590602001918460208302840111600160201b83111715610c3d57600080fd5b919390928235926001600160a01b03602082013516929190606081019060400135600160201b811115610c6f57600080fd5b820183602082011115610c8157600080fd5b803590602001918460018302840111600160201b83111715610ca257600080fd5b91935091506001600160a01b03813581169160208101358216916040820135916060013516611f9c565b348015610cd857600080fd5b5061048860048036036080811015610cef57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d1e57600080fd5b820183602082011115610d3057600080fd5b803590602001918460018302840111600160201b83111715610d5157600080fd5b91935091503560ff166120ec565b348015610d6b57600080fd5b50610d9860048036036040811015610d8257600080fd5b506001600160a01b0381351690602001356121e9565b6040518080602001836001600160a01b03168152602001828103825284818151815260200191508051906020019060200280838360005b83811015610de7578181015183820152602001610dcf565b50505050905001935050505060405180910390f35b348015610e0857600080fd5b506102b860048036036020811015610e1f57600080fd5b50356122d4565b348015610e3257600080fd5b506104886004803603610140811015610e4a57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610e7957600080fd5b820183602082011115610e8b57600080fd5b803590602001918460018302840111600160201b83111715610eac57600080fd5b919350915060ff813516906020810135906040810135906060810135906001600160a01b03608082013581169160a08101359091169060c0013561236e565b348015610ef757600080fd5b506102b860048036036040811015610f0e57600080fd5b506001600160a01b038135811691602001351661239b565b348015610f3257600080fd5b506102b860048036036020811015610f4957600080fd5b50356001600160a01b03166124d5565b348015610f6557600080fd5b506102b860048036036060811015610f7c57600080fd5b506001600160a01b038135811691602081013582169160409091013516612541565b348015610faa57600080fd5b5061048861278e565b348015610fbf57600080fd5b506106e16004803603610140811015610fd757600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561100657600080fd5b82018360208201111561101857600080fd5b803590602001918460018302840111600160201b8311171561103957600080fd5b919350915060ff813516906020810135906040810135906060810135906001600160a01b03608082013581169160a08101359091169060c00135612794565b34801561108457600080fd5b506102b86004803603602081101561109b57600080fd5b50356001600160a01b03166128d5565b3480156110b757600080fd5b50610488612925565b3480156110cc57600080fd5b506102b8600480360360608110156110e357600080fd5b506001600160a01b03813581169160208101359091169060400135612993565b34801561110f57600080fd5b506106e1612b2c565b611120612b4d565b6001600160a01b0382161580159061114257506001600160a01b038216600114155b801561115757506001600160a01b0382163014155b611190576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b0382811660009081526002602052604090205416156111e5576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b600260209081527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e080546001600160a01b03858116600081815260408082208054949095166001600160a01b031994851617909455600190819052845490921681179093556003805490910190558051918252517f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea26929181900390910190a180600454146112965761129681611b64565b5050565b6112a5816041612b8b565b825110156112e2576040805162461bcd60e51b8152602060048201526005602482015264047533032360dc1b604482015290519081900360640190fd5b6000808060008060005b868110156117ec576112fe8882612bb9565b9195509350915060ff841661159f57919350839161131d876041612b8b565b821015611359576040805162461bcd60e51b8152602060048201526005602482015264475330323160d81b604482015290519081900360640190fd5b8751611366836020612bd7565b11156113a1576040805162461bcd60e51b815260206004820152600560248201526423a998191960d91b604482015290519081900360640190fd5b6020828901810151895190916113c49083906113be908790612bd7565b90612bd7565b11156113ff576040805162461bcd60e51b8152602060048201526005602482015264475330323360d81b604482015290519081900360640190fd5b60606020848b010190506320c13b0b60e01b6001600160e01b031916876001600160a01b03166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561147c578181015183820152602001611464565b50505050905090810190601f1680156114a95780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156114dc5781810151838201526020016114c4565b50505050905090810190601f1680156115095780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561152857600080fd5b505afa15801561153c573d6000803e3d6000fd5b505050506040513d602081101561155257600080fd5b50516001600160e01b03191614611598576040805162461bcd60e51b815260206004820152600560248201526411d4cc0c8d60da1b604482015290519081900360640190fd5b5050611756565b8360ff1660011415611627579193508391336001600160a01b03841614806115e957506001600160a01b03851660009081526008602090815260408083208d845290915290205415155b611622576040805162461bcd60e51b8152602060048201526005602482015264475330323560d81b604482015290519081900360640190fd5b611756565b601e8460ff1611156116ef5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156116de573d6000803e3d6000fd5b505050602060405103519450611756565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611749573d6000803e3d6000fd5b5050506020604051035194505b856001600160a01b0316856001600160a01b031611801561179057506001600160a01b038581166000908152600260205260409020541615155b80156117a657506001600160a01b038516600114155b6117df576040805162461bcd60e51b815260206004820152600560248201526423a998191b60d91b604482015290519081900360640190fd5b93945084936001016112ec565b50505050505050505050565b600060016001600160a01b0383161480159061182d57506001600160a01b038281166000908152600160205260409020541615155b92915050565b60006001600160a01b03821660011480159061182d5750506001600160a01b0390811660009081526002602052604090205416151590565b4690565b60007fb648d3644f584ed1c2232d53c46d87e693586486ad0d1175f8656013110b714e338686868660405180866001600160a01b03168152602001856001600160a01b03168152602001848152602001806020018360018111156118cf57fe5b8152602001828103825284818151815260200191508051906020019080838360005b838110156119095781810151838201526020016118f1565b50505050905090810190601f1680156119365780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a161195385858585612be9565b95945050505050565b6000606061196c8686868661186f565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060008260200267ffffffffffffffff811180156119b057600080fd5b506040519080825280601f01601f1916602001820160405280156119db576020820181803683370190505b50905060005b838110156119fe57848101546020808302840101526001016119e1565b509392505050565b60076020526000908152604090205481565b611a20612b4d565b6001600160a01b03811615801590611a4257506001600160a01b038116600114155b611a7b576040805162461bcd60e51b8152602060048201526005602482015264475331303160d81b604482015290519081900360640190fd5b6001600160a01b038181166000908152600160205260409020541615611ad0576040805162461bcd60e51b815260206004820152600560248201526423a998981960d91b604482015290519081900360640190fd5b600160208181527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80546001600160a01b03858116600081815260408082208054949095166001600160a01b0319948516179094559590955282541684179091558051928352517fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f84409281900390910190a150565b611b6c612b4d565b600354811115611bab576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b6001811015611be9576040805162461bcd60e51b815260206004820152600560248201526423a999181960d91b604482015290519081900360640190fd5b60048190556040805182815290517f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939181900360200190a150565b600060606005543360045460405160200180848152602001836001600160a01b03168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed8d8d8d8d8d8d8d8d8d8d8d8c604051808d6001600160a01b031681526020018c8152602001806020018a6001811115611cbd57fe5b8152602001898152602001888152602001878152602001866001600160a01b03168152602001856001600160a01b03168152602001806020018060200184810384528e8e828181526020019250808284376000838201819052601f909101601f19169092018681038552885181528851602091820193918a019250908190849084905b83811015611d58578181015183820152602001611d40565b50505050905090810190601f168015611d855780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015611db8578181015183820152602001611da0565b50505050905090810190601f168015611de55780820380516001836020036101000a031916815260200191505b509f5050505050505050505050505050505060405180910390a1611e128d8d8d8d8d8d8d8d8d8d8d612cc5565b9d9c50505050505050505050505050565b600860209081526000928352604080842090915290825290205481565b60045480611e7d576040805162461bcd60e51b8152602060048201526005602482015264475330303160d81b604482015290519081900360640190fd5b611e898484848461129a565b50505050565b6060600060035467ffffffffffffffff81118015611eac57600080fd5b50604051908082528060200260200182016040528015611ed6578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e054919250906001600160a01b03165b6001600160a01b038116600114611f6b5780838381518110611f3157fe5b6001600160a01b03928316602091820292909201810191909152918116600090815260029092526040909120546001929092019116611f13565b509091505090565b60055481565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611fda8a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92506130c3915050565b6001600160a01b03841615611ff257611ff2846132fa565b6120328787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331e92505050565b81156120495761204782600060018685613422565b505b336001600160a01b03167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b896040518080602001858152602001846001600160a01b03168152602001836001600160a01b031681526020018281038252878782818152602001925060200280828437600083820152604051601f909101601f19169092018290039850909650505050505050a250505050505050505050565b6000805a9050612135878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925050505a613532565b61213e57600080fd5b60005a82039050806040516020018082815260200191505060405160208183030381529060405260405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156121ae578181015183820152602001612196565b50505050905090810190601f1680156121db5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b606060008267ffffffffffffffff8111801561220457600080fd5b5060405190808252806020026020018201604052801561222e578160200160208202803683370190505b506001600160a01b0380861660009081526001602052604081205492945091165b6001600160a01b0381161580159061227157506001600160a01b038116600114155b801561227c57508482105b156122c6578084838151811061228e57fe5b6001600160a01b039283166020918202929092018101919091529181166000908152600192839052604090205492909101911661224f565b908352919491935090915050565b336000908152600260205260409020546001600160a01b0316612326576040805162461bcd60e51b8152602060048201526005602482015264047533033360dc1b604482015290519081900360640190fd5b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b60006123838c8c8c8c8c8c8c8c8c8c8c612794565b8051906020012090509b9a5050505050505050505050565b6123a3612b4d565b6001600160a01b038116158015906123c557506001600160a01b038116600114155b6123fe576040805162461bcd60e51b8152602060048201526005602482015264475331303160d81b604482015290519081900360640190fd5b6001600160a01b03828116600090815260016020526040902054811690821614612457576040805162461bcd60e51b8152602060048201526005602482015264475331303360d81b604482015290519081900360640190fd5b6001600160a01b038181166000818152600160209081526040808320805488871685528285208054919097166001600160a01b031991821617909655928490528254909416909155825191825291517faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace4054276929181900390910190a15050565b6124dd612b4d565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8818155604080516001600160a01b038416815290517f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa29181900360200190a15050565b612549612b4d565b6001600160a01b0381161580159061256b57506001600160a01b038116600114155b801561258057506001600160a01b0381163014155b6125b9576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b03818116600090815260026020526040902054161561260e576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b6001600160a01b0382161580159061263057506001600160a01b038216600114155b612669576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b038381166000908152600260205260409020548116908316146126c2576040805162461bcd60e51b8152602060048201526005602482015264475332303560d81b604482015290519081900360640190fd5b6001600160a01b038281166000818152600260209081526040808320805487871680865283862080549289166001600160a01b0319938416179055968a16855282852080548216909717909655928490528254909416909155825191825291517ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf929181900390910190a1604080516001600160a01b038316815290517f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269181900360200190a1505050565b60045490565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b6001600160a01b031681526020018a815260200189815260200188600181111561281857fe5b8152602001878152602001868152602001858152602001846001600160a01b03168152602001836001600160a01b031681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b61288a612925565b604080516001600160f81b0319948516602082015292909316602183015260228201526042808201939093528151808203909301835260620190529c9b505050505050505050505050565b6128dd612b4d565b6128e6816132fa565b604080516001600160a01b038316815290517f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b09181900360200190a150565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921861295061186b565b3060405160200180848152602001838152602001826001600160a01b03168152602001935050505060405160208183030381529060405280519060200120905090565b61299b612b4d565b8060016003540310156129dd576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b6001600160a01b038216158015906129ff57506001600160a01b038216600114155b612a38576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b03838116600090815260026020526040902054811690831614612a91576040805162461bcd60e51b8152602060048201526005602482015264475332303560d81b604482015290519081900360640190fd5b6001600160a01b038281166000818152600260209081526040808320805489871685528285208054919097166001600160a01b03199182161790965592849052825490941690915560038054600019019055825191825291517ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf929181900390910190a18060045414612b2757612b2781611b64565b505050565b604051806040016040528060058152602001640312e332e360dc1b81525081565b333014612b89576040805162461bcd60e51b8152602060048201526005602482015264475330333160d81b604482015290519081900360640190fd5b565b600082612b9a5750600061182d565b82820282848281612ba757fe5b0414612bb257600080fd5b9392505050565b60419081029190910160208101516040820151919092015160ff1692565b600082820183811015612bb257600080fd5b600033600114801590612c135750336000908152600160205260409020546001600160a01b031615155b612c4c576040805162461bcd60e51b815260206004820152600560248201526411d4cc4c0d60da1b604482015290519081900360640190fd5b612c59858585855a613532565b90508015612c915760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a2612cbd565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b6000806000612cdf8e8e8e8e8e8e8e8e8e8e600554612794565b6005805460010190558051602082012092509050612cfe828286611e40565b506000612d09613572565b90506001600160a01b03811615612e8457806001600160a01b03166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d6001600160a01b031681526020018c8152602001806020018a6001811115612d6d57fe5b8152602001898152602001888152602001878152602001866001600160a01b03168152602001856001600160a01b0316815260200180602001846001600160a01b0316815260200183810383528d8d828181526020019250808284376000838201819052601f909101601f191690920185810384528751815287516020918201939189019250908190849084905b83811015612e13578181015183820152602001612dfb565b50505050905090810190601f168015612e405780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612e6b57600080fd5b505af1158015612e7f573d6000803e3d6000fd5b505050505b612e98603f60408b02046109c48b01613597565b6101f4015a1015612ed8576040805162461bcd60e51b8152602060048201526005602482015264047533031360dc1b604482015290519081900360640190fd5b60005a9050612f418f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c600014612f36578e612f3c565b6109c45a035b613532565b9350612f4e5a82906135ae565b90508380612f5b57508915155b80612f6557508715155b612f9e576040805162461bcd60e51b8152602060048201526005602482015264475330313360d81b604482015290519081900360640190fd5b60008815612fb657612fb3828b8b8b8b613422565b90505b8415612ffc57604080518581526020810183905281517f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e929181900390910190a1613038565b604080518581526020810183905281517f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23929181900390910190a15b50506001600160a01b038116156130b257806001600160a01b0316639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561309957600080fd5b505af11580156130ad573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b60045415613100576040805162461bcd60e51b8152602060048201526005602482015264047533230360dc1b604482015290519081900360640190fd5b815181111561313e576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b600181101561317c576040805162461bcd60e51b815260206004820152600560248201526423a999181960d91b604482015290519081900360640190fd5b600160005b83518110156132c757600084828151811061319857fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141580156131cf57506001600160a01b038116600114155b80156131e457506001600160a01b0381163014155b80156132025750806001600160a01b0316836001600160a01b031614155b61323b576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b038181166000908152600260205260409020541615613290576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b6001600160a01b03928316600090815260026020526040902080546001600160a01b03191693821693909317909255600101613181565b506001600160a01b0316600090815260026020526040902080546001600160a01b03191660011790559051600355600455565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f546001600160a01b03161561338d576040805162461bcd60e51b8152602060048201526005602482015264047533130360dc1b604482015290519081900360640190fd5b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80546001600160a01b03191690911790556001600160a01b03821615611296576133e98260008360015a613532565b611296576040805162461bcd60e51b8152602060048201526005602482015264047533030360dc1b604482015290519081900360640190fd5b6000806001600160a01b0383161561343a578261343c565b325b90506001600160a01b0384166134d45761346e3a861061345c573a61345e565b855b6134688989612bd7565b90612b8b565b6040519092506001600160a01b0382169083156108fc029084906000818181858888f193505050506134cf576040805162461bcd60e51b8152602060048201526005602482015264475330313160d81b604482015290519081900360640190fd5b613528565b6134e2856134688989612bd7565b91506134ef8482846135c3565b613528576040805162461bcd60e51b815260206004820152600560248201526423a998189960d91b604482015290519081900360640190fd5b5095945050505050565b6000600183600181111561354257fe5b141561355b576000808551602087018986f49050611953565b600080855160208701888a87f19695505050505050565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b6000818310156135a75781612bb2565b5090919050565b6000828211156135bd57600080fd5b50900390565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602081810180516001600160e01b031663a9059cbb60e01b1781528251600093929184919082896127105a03f13d8015613635576020811461363d5760009350613648565b819350613648565b600051158215171593505b505050939250505056fea26469706673582212207947c0d62abb804ea45f6e1e86f0c235b11fd82938acc25e17bd4035b641148464736f6c63430007060033
Deployed ByteCode
0x6080604052600436106101dc5760003560e01c8063affed0e011610102578063e19a9dd911610095578063f08a032311610064578063f08a032314611078578063f698da25146110ab578063f8dc5dd9146110c0578063ffa1ad741461110357610219565b8063e19a9dd914610f26578063e318b52b14610f59578063e75235b814610f9e578063e86637db14610fb357610219565b8063cc2f8452116100d1578063cc2f845214610d5f578063d4d9bdcd14610dfc578063d8d11f7814610e26578063e009cfde14610eeb57610219565b8063affed0e014610af6578063b4faba0914610b0b578063b63e800d14610bcc578063c4ca3a9c14610ccc57610219565b80635624b25b1161017a5780636a761202116101495780636a761202146107dd5780637d8329741461091b578063934f3a1114610954578063a0e67e2b14610a9157610219565b80635624b25b146106b15780635ae6bd3714610756578063610b592514610780578063694e80c3146107b357610219565b80632f54bf6e116101b65780632f54bf6e146104405780633408e47014610473578063468721a71461049a5780635229073f1461056557610219565b80630d582f131461027f57806312fb68e0146102ba5780632d9ad53d146103f957610219565b366102195760408051348152905133917f3d0ce9bfc3ed7d6862dbb28b2dea94561fe714a1b4d019aa8af39730d1ad7c3d919081900360200190a2005b34801561022557600080fd5b507f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d580548061025057005b36600080373360601b365260008060143601600080855af190503d6000803e80610279573d6000fd5b503d6000f35b34801561028b57600080fd5b506102b8600480360360408110156102a257600080fd5b506001600160a01b038135169060200135611118565b005b3480156102c657600080fd5b506102b8600480360360808110156102dd57600080fd5b81359190810190604081016020820135600160201b8111156102fe57600080fd5b82018360208201111561031057600080fd5b803590602001918460018302840111600160201b8311171561033157600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b81111561038357600080fd5b82018360208201111561039557600080fd5b803590602001918460018302840111600160201b831117156103b657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550509135925061129a915050565b34801561040557600080fd5b5061042c6004803603602081101561041c57600080fd5b50356001600160a01b03166117f8565b604080519115158252519081900360200190f35b34801561044c57600080fd5b5061042c6004803603602081101561046357600080fd5b50356001600160a01b0316611833565b34801561047f57600080fd5b5061048861186b565b60408051918252519081900360200190f35b3480156104a657600080fd5b5061042c600480360360808110156104bd57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156104ec57600080fd5b8201836020820111156104fe57600080fd5b803590602001918460018302840111600160201b8311171561051f57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061186f9050565b34801561057157600080fd5b506106306004803603608081101561058857600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b8111156105b757600080fd5b8201836020820111156105c957600080fd5b803590602001918460018302840111600160201b831117156105ea57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061195c9050565b60405180831515815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561067557818101518382015260200161065d565b50505050905090810190601f1680156106a25780820380516001836020036101000a031916815260200191505b50935050505060405180910390f35b3480156106bd57600080fd5b506106e1600480360360408110156106d457600080fd5b5080359060200135611992565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561071b578181015183820152602001610703565b50505050905090810190601f1680156107485780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561076257600080fd5b506104886004803603602081101561077957600080fd5b5035611a06565b34801561078c57600080fd5b506102b8600480360360208110156107a357600080fd5b50356001600160a01b0316611a18565b3480156107bf57600080fd5b506102b8600480360360208110156107d657600080fd5b5035611b64565b61042c60048036036101408110156107f457600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561082357600080fd5b82018360208201111561083557600080fd5b803590602001918460018302840111600160201b8311171561085657600080fd5b9193909260ff833516926020810135926040820135926060830135926001600160a01b03608082013581169360a083013590911692909160e081019060c00135600160201b8111156108a757600080fd5b8201836020820111156108b957600080fd5b803590602001918460018302840111600160201b831117156108da57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611c24945050505050565b34801561092757600080fd5b506104886004803603604081101561093e57600080fd5b506001600160a01b038135169060200135611e23565b34801561096057600080fd5b506102b86004803603606081101561097757600080fd5b81359190810190604081016020820135600160201b81111561099857600080fd5b8201836020820111156109aa57600080fd5b803590602001918460018302840111600160201b831117156109cb57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610a1d57600080fd5b820183602082011115610a2f57600080fd5b803590602001918460018302840111600160201b83111715610a5057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611e40945050505050565b348015610a9d57600080fd5b50610aa6611e8f565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610ae2578181015183820152602001610aca565b505050509050019250505060405180910390f35b348015610b0257600080fd5b50610488611f73565b348015610b1757600080fd5b506102b860048036036040811015610b2e57600080fd5b6001600160a01b038235169190810190604081016020820135600160201b811115610b5857600080fd5b820183602082011115610b6a57600080fd5b803590602001918460018302840111600160201b83111715610b8b57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611f79945050505050565b348015610bd857600080fd5b506102b86004803603610100811015610bf057600080fd5b810190602081018135600160201b811115610c0a57600080fd5b820183602082011115610c1c57600080fd5b803590602001918460208302840111600160201b83111715610c3d57600080fd5b919390928235926001600160a01b03602082013516929190606081019060400135600160201b811115610c6f57600080fd5b820183602082011115610c8157600080fd5b803590602001918460018302840111600160201b83111715610ca257600080fd5b91935091506001600160a01b03813581169160208101358216916040820135916060013516611f9c565b348015610cd857600080fd5b5061048860048036036080811015610cef57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610d1e57600080fd5b820183602082011115610d3057600080fd5b803590602001918460018302840111600160201b83111715610d5157600080fd5b91935091503560ff166120ec565b348015610d6b57600080fd5b50610d9860048036036040811015610d8257600080fd5b506001600160a01b0381351690602001356121e9565b6040518080602001836001600160a01b03168152602001828103825284818151815260200191508051906020019060200280838360005b83811015610de7578181015183820152602001610dcf565b50505050905001935050505060405180910390f35b348015610e0857600080fd5b506102b860048036036020811015610e1f57600080fd5b50356122d4565b348015610e3257600080fd5b506104886004803603610140811015610e4a57600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b811115610e7957600080fd5b820183602082011115610e8b57600080fd5b803590602001918460018302840111600160201b83111715610eac57600080fd5b919350915060ff813516906020810135906040810135906060810135906001600160a01b03608082013581169160a08101359091169060c0013561236e565b348015610ef757600080fd5b506102b860048036036040811015610f0e57600080fd5b506001600160a01b038135811691602001351661239b565b348015610f3257600080fd5b506102b860048036036020811015610f4957600080fd5b50356001600160a01b03166124d5565b348015610f6557600080fd5b506102b860048036036060811015610f7c57600080fd5b506001600160a01b038135811691602081013582169160409091013516612541565b348015610faa57600080fd5b5061048861278e565b348015610fbf57600080fd5b506106e16004803603610140811015610fd757600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561100657600080fd5b82018360208201111561101857600080fd5b803590602001918460018302840111600160201b8311171561103957600080fd5b919350915060ff813516906020810135906040810135906060810135906001600160a01b03608082013581169160a08101359091169060c00135612794565b34801561108457600080fd5b506102b86004803603602081101561109b57600080fd5b50356001600160a01b03166128d5565b3480156110b757600080fd5b50610488612925565b3480156110cc57600080fd5b506102b8600480360360608110156110e357600080fd5b506001600160a01b03813581169160208101359091169060400135612993565b34801561110f57600080fd5b506106e1612b2c565b611120612b4d565b6001600160a01b0382161580159061114257506001600160a01b038216600114155b801561115757506001600160a01b0382163014155b611190576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b0382811660009081526002602052604090205416156111e5576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b600260209081527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e080546001600160a01b03858116600081815260408082208054949095166001600160a01b031994851617909455600190819052845490921681179093556003805490910190558051918252517f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea26929181900390910190a180600454146112965761129681611b64565b5050565b6112a5816041612b8b565b825110156112e2576040805162461bcd60e51b8152602060048201526005602482015264047533032360dc1b604482015290519081900360640190fd5b6000808060008060005b868110156117ec576112fe8882612bb9565b9195509350915060ff841661159f57919350839161131d876041612b8b565b821015611359576040805162461bcd60e51b8152602060048201526005602482015264475330323160d81b604482015290519081900360640190fd5b8751611366836020612bd7565b11156113a1576040805162461bcd60e51b815260206004820152600560248201526423a998191960d91b604482015290519081900360640190fd5b6020828901810151895190916113c49083906113be908790612bd7565b90612bd7565b11156113ff576040805162461bcd60e51b8152602060048201526005602482015264475330323360d81b604482015290519081900360640190fd5b60606020848b010190506320c13b0b60e01b6001600160e01b031916876001600160a01b03166320c13b0b8d846040518363ffffffff1660e01b8152600401808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561147c578181015183820152602001611464565b50505050905090810190601f1680156114a95780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b838110156114dc5781810151838201526020016114c4565b50505050905090810190601f1680156115095780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b15801561152857600080fd5b505afa15801561153c573d6000803e3d6000fd5b505050506040513d602081101561155257600080fd5b50516001600160e01b03191614611598576040805162461bcd60e51b815260206004820152600560248201526411d4cc0c8d60da1b604482015290519081900360640190fd5b5050611756565b8360ff1660011415611627579193508391336001600160a01b03841614806115e957506001600160a01b03851660009081526008602090815260408083208d845290915290205415155b611622576040805162461bcd60e51b8152602060048201526005602482015264475330323560d81b604482015290519081900360640190fd5b611756565b601e8460ff1611156116ef5760018a60405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c018281526020019150506040516020818303038152906040528051906020012060048603858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156116de573d6000803e3d6000fd5b505050602060405103519450611756565b60018a85858560405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611749573d6000803e3d6000fd5b5050506020604051035194505b856001600160a01b0316856001600160a01b031611801561179057506001600160a01b038581166000908152600260205260409020541615155b80156117a657506001600160a01b038516600114155b6117df576040805162461bcd60e51b815260206004820152600560248201526423a998191b60d91b604482015290519081900360640190fd5b93945084936001016112ec565b50505050505050505050565b600060016001600160a01b0383161480159061182d57506001600160a01b038281166000908152600160205260409020541615155b92915050565b60006001600160a01b03821660011480159061182d5750506001600160a01b0390811660009081526002602052604090205416151590565b4690565b60007fb648d3644f584ed1c2232d53c46d87e693586486ad0d1175f8656013110b714e338686868660405180866001600160a01b03168152602001856001600160a01b03168152602001848152602001806020018360018111156118cf57fe5b8152602001828103825284818151815260200191508051906020019080838360005b838110156119095781810151838201526020016118f1565b50505050905090810190601f1680156119365780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a161195385858585612be9565b95945050505050565b6000606061196c8686868661186f565b915060405160203d0181016040523d81523d6000602083013e8091505094509492505050565b606060008260200267ffffffffffffffff811180156119b057600080fd5b506040519080825280601f01601f1916602001820160405280156119db576020820181803683370190505b50905060005b838110156119fe57848101546020808302840101526001016119e1565b509392505050565b60076020526000908152604090205481565b611a20612b4d565b6001600160a01b03811615801590611a4257506001600160a01b038116600114155b611a7b576040805162461bcd60e51b8152602060048201526005602482015264475331303160d81b604482015290519081900360640190fd5b6001600160a01b038181166000908152600160205260409020541615611ad0576040805162461bcd60e51b815260206004820152600560248201526423a998981960d91b604482015290519081900360640190fd5b600160208181527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80546001600160a01b03858116600081815260408082208054949095166001600160a01b0319948516179094559590955282541684179091558051928352517fecdf3a3effea5783a3c4c2140e677577666428d44ed9d474a0b3a4c9943f84409281900390910190a150565b611b6c612b4d565b600354811115611bab576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b6001811015611be9576040805162461bcd60e51b815260206004820152600560248201526423a999181960d91b604482015290519081900360640190fd5b60048190556040805182815290517f610f7ff2b304ae8903c3de74c60c6ab1f7d6226b3f52c5161905bb5ad4039c939181900360200190a150565b600060606005543360045460405160200180848152602001836001600160a01b03168152602001828152602001935050505060405160208183030381529060405290507f66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed8d8d8d8d8d8d8d8d8d8d8d8c604051808d6001600160a01b031681526020018c8152602001806020018a6001811115611cbd57fe5b8152602001898152602001888152602001878152602001866001600160a01b03168152602001856001600160a01b03168152602001806020018060200184810384528e8e828181526020019250808284376000838201819052601f909101601f19169092018681038552885181528851602091820193918a019250908190849084905b83811015611d58578181015183820152602001611d40565b50505050905090810190601f168015611d855780820380516001836020036101000a031916815260200191505b50848103825285518152855160209182019187019080838360005b83811015611db8578181015183820152602001611da0565b50505050905090810190601f168015611de55780820380516001836020036101000a031916815260200191505b509f5050505050505050505050505050505060405180910390a1611e128d8d8d8d8d8d8d8d8d8d8d612cc5565b9d9c50505050505050505050505050565b600860209081526000928352604080842090915290825290205481565b60045480611e7d576040805162461bcd60e51b8152602060048201526005602482015264475330303160d81b604482015290519081900360640190fd5b611e898484848461129a565b50505050565b6060600060035467ffffffffffffffff81118015611eac57600080fd5b50604051908082528060200260200182016040528015611ed6578160200160208202803683370190505b506001600090815260026020527fe90b7bceb6e7df5418fb78d8ee546e97c83a08bbccc01a0644d599ccd2a7c2e054919250906001600160a01b03165b6001600160a01b038116600114611f6b5780838381518110611f3157fe5b6001600160a01b03928316602091820292909201810191909152918116600090815260029092526040909120546001929092019116611f13565b509091505090565b60055481565b600080825160208401855af480600052503d6020523d600060403e60403d016000fd5b611fda8a8a808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c92506130c3915050565b6001600160a01b03841615611ff257611ff2846132fa565b6120328787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061331e92505050565b81156120495761204782600060018685613422565b505b336001600160a01b03167f141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a88b8b8b8b896040518080602001858152602001846001600160a01b03168152602001836001600160a01b031681526020018281038252878782818152602001925060200280828437600083820152604051601f909101601f19169092018290039850909650505050505050a250505050505050505050565b6000805a9050612135878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525089925050505a613532565b61213e57600080fd5b60005a82039050806040516020018082815260200191505060405160208183030381529060405260405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156121ae578181015183820152602001612196565b50505050905090810190601f1680156121db5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b606060008267ffffffffffffffff8111801561220457600080fd5b5060405190808252806020026020018201604052801561222e578160200160208202803683370190505b506001600160a01b0380861660009081526001602052604081205492945091165b6001600160a01b0381161580159061227157506001600160a01b038116600114155b801561227c57508482105b156122c6578084838151811061228e57fe5b6001600160a01b039283166020918202929092018101919091529181166000908152600192839052604090205492909101911661224f565b908352919491935090915050565b336000908152600260205260409020546001600160a01b0316612326576040805162461bcd60e51b8152602060048201526005602482015264047533033360dc1b604482015290519081900360640190fd5b336000818152600860209081526040808320858452909152808220600190555183917ff2a0eb156472d1440255b0d7c1e19cc07115d1051fe605b0dce69acfec884d9c91a350565b60006123838c8c8c8c8c8c8c8c8c8c8c612794565b8051906020012090509b9a5050505050505050505050565b6123a3612b4d565b6001600160a01b038116158015906123c557506001600160a01b038116600114155b6123fe576040805162461bcd60e51b8152602060048201526005602482015264475331303160d81b604482015290519081900360640190fd5b6001600160a01b03828116600090815260016020526040902054811690821614612457576040805162461bcd60e51b8152602060048201526005602482015264475331303360d81b604482015290519081900360640190fd5b6001600160a01b038181166000818152600160209081526040808320805488871685528285208054919097166001600160a01b031991821617909655928490528254909416909155825191825291517faab4fa2b463f581b2b32cb3b7e3b704b9ce37cc209b5fb4d77e593ace4054276929181900390910190a15050565b6124dd612b4d565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8818155604080516001600160a01b038416815290517f1151116914515bc0891ff9047a6cb32cf902546f83066499bcf8ba33d2353fa29181900360200190a15050565b612549612b4d565b6001600160a01b0381161580159061256b57506001600160a01b038116600114155b801561258057506001600160a01b0381163014155b6125b9576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b03818116600090815260026020526040902054161561260e576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b6001600160a01b0382161580159061263057506001600160a01b038216600114155b612669576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b038381166000908152600260205260409020548116908316146126c2576040805162461bcd60e51b8152602060048201526005602482015264475332303560d81b604482015290519081900360640190fd5b6001600160a01b038281166000818152600260209081526040808320805487871680865283862080549289166001600160a01b0319938416179055968a16855282852080548216909717909655928490528254909416909155825191825291517ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf929181900390910190a1604080516001600160a01b038316815290517f9465fa0c962cc76958e6373a993326400c1c94f8be2fe3a952adfa7f60b2ea269181900360200190a1505050565b60045490565b606060007fbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d860001b8d8d8d8d60405180838380828437808301925050509250505060405180910390208c8c8c8c8c8c8c604051602001808c81526020018b6001600160a01b031681526020018a815260200189815260200188600181111561281857fe5b8152602001878152602001868152602001858152602001846001600160a01b03168152602001836001600160a01b031681526020018281526020019b505050505050505050505050604051602081830303815290604052805190602001209050601960f81b600160f81b61288a612925565b604080516001600160f81b0319948516602082015292909316602183015260228201526042808201939093528151808203909301835260620190529c9b505050505050505050505050565b6128dd612b4d565b6128e6816132fa565b604080516001600160a01b038316815290517f5ac6c46c93c8d0e53714ba3b53db3e7c046da994313d7ed0d192028bc7c228b09181900360200190a150565b60007f47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a7946921861295061186b565b3060405160200180848152602001838152602001826001600160a01b03168152602001935050505060405160208183030381529060405280519060200120905090565b61299b612b4d565b8060016003540310156129dd576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b6001600160a01b038216158015906129ff57506001600160a01b038216600114155b612a38576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b03838116600090815260026020526040902054811690831614612a91576040805162461bcd60e51b8152602060048201526005602482015264475332303560d81b604482015290519081900360640190fd5b6001600160a01b038281166000818152600260209081526040808320805489871685528285208054919097166001600160a01b03199182161790965592849052825490941690915560038054600019019055825191825291517ff8d49fc529812e9a7c5c50e69c20f0dccc0db8fa95c98bc58cc9a4f1c1299eaf929181900390910190a18060045414612b2757612b2781611b64565b505050565b604051806040016040528060058152602001640312e332e360dc1b81525081565b333014612b89576040805162461bcd60e51b8152602060048201526005602482015264475330333160d81b604482015290519081900360640190fd5b565b600082612b9a5750600061182d565b82820282848281612ba757fe5b0414612bb257600080fd5b9392505050565b60419081029190910160208101516040820151919092015160ff1692565b600082820183811015612bb257600080fd5b600033600114801590612c135750336000908152600160205260409020546001600160a01b031615155b612c4c576040805162461bcd60e51b815260206004820152600560248201526411d4cc4c0d60da1b604482015290519081900360640190fd5b612c59858585855a613532565b90508015612c915760405133907f6895c13664aa4f67288b25d7a21d7aaa34916e355fb9b6fae0a139a9085becb890600090a2612cbd565b60405133907facd2c8702804128fdb0db2bb49f6d127dd0181c13fd45dbfe16de0930e2bd37590600090a25b949350505050565b6000806000612cdf8e8e8e8e8e8e8e8e8e8e600554612794565b6005805460010190558051602082012092509050612cfe828286611e40565b506000612d09613572565b90506001600160a01b03811615612e8457806001600160a01b03166375f0bb528f8f8f8f8f8f8f8f8f8f8f336040518d63ffffffff1660e01b8152600401808d6001600160a01b031681526020018c8152602001806020018a6001811115612d6d57fe5b8152602001898152602001888152602001878152602001866001600160a01b03168152602001856001600160a01b0316815260200180602001846001600160a01b0316815260200183810383528d8d828181526020019250808284376000838201819052601f909101601f191690920185810384528751815287516020918201939189019250908190849084905b83811015612e13578181015183820152602001612dfb565b50505050905090810190601f168015612e405780820380516001836020036101000a031916815260200191505b509e505050505050505050505050505050600060405180830381600087803b158015612e6b57600080fd5b505af1158015612e7f573d6000803e3d6000fd5b505050505b612e98603f60408b02046109c48b01613597565b6101f4015a1015612ed8576040805162461bcd60e51b8152602060048201526005602482015264047533031360dc1b604482015290519081900360640190fd5b60005a9050612f418f8f8f8f8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508e8c600014612f36578e612f3c565b6109c45a035b613532565b9350612f4e5a82906135ae565b90508380612f5b57508915155b80612f6557508715155b612f9e576040805162461bcd60e51b8152602060048201526005602482015264475330313360d81b604482015290519081900360640190fd5b60008815612fb657612fb3828b8b8b8b613422565b90505b8415612ffc57604080518581526020810183905281517f442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e929181900390910190a1613038565b604080518581526020810183905281517f23428b18acfb3ea64b08dc0c1d296ea9c09702c09083ca5272e64d115b687d23929181900390910190a15b50506001600160a01b038116156130b257806001600160a01b0316639327136883856040518363ffffffff1660e01b815260040180838152602001821515815260200192505050600060405180830381600087803b15801561309957600080fd5b505af11580156130ad573d6000803e3d6000fd5b505050505b50509b9a5050505050505050505050565b60045415613100576040805162461bcd60e51b8152602060048201526005602482015264047533230360dc1b604482015290519081900360640190fd5b815181111561313e576040805162461bcd60e51b8152602060048201526005602482015264475332303160d81b604482015290519081900360640190fd5b600181101561317c576040805162461bcd60e51b815260206004820152600560248201526423a999181960d91b604482015290519081900360640190fd5b600160005b83518110156132c757600084828151811061319857fe5b6020026020010151905060006001600160a01b0316816001600160a01b0316141580156131cf57506001600160a01b038116600114155b80156131e457506001600160a01b0381163014155b80156132025750806001600160a01b0316836001600160a01b031614155b61323b576040805162461bcd60e51b8152602060048201526005602482015264475332303360d81b604482015290519081900360640190fd5b6001600160a01b038181166000908152600260205260409020541615613290576040805162461bcd60e51b815260206004820152600560248201526411d4cc8c0d60da1b604482015290519081900360640190fd5b6001600160a01b03928316600090815260026020526040902080546001600160a01b03191693821693909317909255600101613181565b506001600160a01b0316600090815260026020526040902080546001600160a01b03191660011790559051600355600455565b7f6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d555565b600160008190526020527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f546001600160a01b03161561338d576040805162461bcd60e51b8152602060048201526005602482015264047533130360dc1b604482015290519081900360640190fd5b6001600081905260208190527fcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f80546001600160a01b03191690911790556001600160a01b03821615611296576133e98260008360015a613532565b611296576040805162461bcd60e51b8152602060048201526005602482015264047533030360dc1b604482015290519081900360640190fd5b6000806001600160a01b0383161561343a578261343c565b325b90506001600160a01b0384166134d45761346e3a861061345c573a61345e565b855b6134688989612bd7565b90612b8b565b6040519092506001600160a01b0382169083156108fc029084906000818181858888f193505050506134cf576040805162461bcd60e51b8152602060048201526005602482015264475330313160d81b604482015290519081900360640190fd5b613528565b6134e2856134688989612bd7565b91506134ef8482846135c3565b613528576040805162461bcd60e51b815260206004820152600560248201526423a998189960d91b604482015290519081900360640190fd5b5095945050505050565b6000600183600181111561354257fe5b141561355b576000808551602087018986f49050611953565b600080855160208701888a87f19695505050505050565b7f4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c85490565b6000818310156135a75781612bb2565b5090919050565b6000828211156135bd57600080fd5b50900390565b604080516001600160a01b03841660248201526044808201849052825180830390910181526064909101909152602081810180516001600160e01b031663a9059cbb60e01b1781528251600093929184919082896127105a03f13d8015613635576020811461363d5760009350613648565b819350613648565b600051158215171593505b505050939250505056fea26469706673582212207947c0d62abb804ea45f6e1e86f0c235b11fd82938acc25e17bd4035b641148464736f6c63430007060033