Transaction Hash:
Block:
10478648 at Jul-17-2020 06:42:00 PM +UTC
Transaction Fee:
0.007020216000125361 ETH
$11.23
Gas Used:
125,361 Gas / 56.000000001 Gwei
Emitted Events:
109 |
MultiSigWalletWithDailyLimit.Confirmation( sender=[Sender] 0x1f4f5967df6b5b70a2d7f1d031e12e7f4fc6e56c, transactionId=51 )
|
110 |
TokenOWLProxy.Transfer( from=[Receiver] MultiSigWalletWithDailyLimit, to=0x6d7f519a18e903b1642FdEB6419907B2b912CFbc, value=50050000000000000000000 )
|
111 |
MultiSigWalletWithDailyLimit.Execution( transactionId=51 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x04668Ec2...D451c8F7F
Miner
| (zhizhu.top) | 3,953.234677798063809879 Eth | 3,953.24169801406393524 Eth | 0.007020216000125361 | |
0x1A5F9352...6370d82e4 | |||||
0x1F4f5967...f4fC6E56c |
1.311195877300771689 Eth
Nonce: 58
|
1.304175661300646328 Eth
Nonce: 59
| 0.007020216000125361 | ||
0x31CbA7aD...5736a9615 |
Execution Trace
MultiSigWalletWithDailyLimit.confirmTransaction( transactionId=51 )
-
TokenOWLProxy.transfer( to=0x6d7f519a18e903b1642FdEB6419907B2b912CFbc, value=50050000000000000000000 ) => ( True )
confirmTransaction[MultiSigWallet (ln:197)]
Confirmation[MultiSigWallet (ln:204)]
executeTransaction[MultiSigWallet (ln:205)]
isConfirmed[MultiSigWallet (ln:226)]
value[MultiSigWallet (ln:229)]
Execution[MultiSigWallet (ln:230)]
ExecutionFailure[MultiSigWallet (ln:232)]
File 1 of 2: MultiSigWalletWithDailyLimit
File 2 of 2: TokenOWLProxy
pragma solidity 0.4.4; /// @title Multisignature wallet - Allows multiple parties to agree on transactions before execution. /// @author Stefan George - <[email protected]> contract MultiSigWallet { uint constant public MAX_OWNER_COUNT = 50; event Confirmation(address indexed sender, uint indexed transactionId); event Revocation(address indexed sender, uint indexed transactionId); event Submission(uint indexed transactionId); event Execution(uint indexed transactionId); event ExecutionFailure(uint indexed transactionId); event Deposit(address indexed sender, uint value); event OwnerAddition(address indexed owner); event OwnerRemoval(address indexed owner); event RequirementChange(uint required); mapping (uint => Transaction) public transactions; mapping (uint => mapping (address => bool)) public confirmations; mapping (address => bool) public isOwner; address[] public owners; uint public required; uint public transactionCount; struct Transaction { address destination; uint value; bytes data; bool executed; } modifier onlyWallet() { if (msg.sender != address(this)) throw; _; } modifier ownerDoesNotExist(address owner) { if (isOwner[owner]) throw; _; } modifier ownerExists(address owner) { if (!isOwner[owner]) throw; _; } modifier transactionExists(uint transactionId) { if (transactions[transactionId].destination == 0) throw; _; } modifier confirmed(uint transactionId, address owner) { if (!confirmations[transactionId][owner]) throw; _; } modifier notConfirmed(uint transactionId, address owner) { if (confirmations[transactionId][owner]) throw; _; } modifier notExecuted(uint transactionId) { if (transactions[transactionId].executed) throw; _; } modifier notNull(address _address) { if (_address == 0) throw; _; } modifier validRequirement(uint ownerCount, uint _required) { if ( ownerCount > MAX_OWNER_COUNT || _required > ownerCount || _required == 0 || ownerCount == 0) throw; _; } /// @dev Fallback function allows to deposit ether. function() payable { if (msg.value > 0) Deposit(msg.sender, msg.value); } /* * Public functions */ /// @dev Contract constructor sets initial owners and required number of confirmations. /// @param _owners List of initial owners. /// @param _required Number of required confirmations. function MultiSigWallet(address[] _owners, uint _required) public validRequirement(_owners.length, _required) { for (uint i=0; i<_owners.length; i++) { if (isOwner[_owners[i]] || _owners[i] == 0) throw; isOwner[_owners[i]] = true; } owners = _owners; required = _required; } /// @dev Allows to add a new owner. Transaction has to be sent by wallet. /// @param owner Address of new owner. function addOwner(address owner) public onlyWallet ownerDoesNotExist(owner) notNull(owner) validRequirement(owners.length + 1, required) { isOwner[owner] = true; owners.push(owner); OwnerAddition(owner); } /// @dev Allows to remove an owner. Transaction has to be sent by wallet. /// @param owner Address of owner. function removeOwner(address owner) public onlyWallet ownerExists(owner) { isOwner[owner] = false; for (uint i=0; i<owners.length - 1; i++) if (owners[i] == owner) { owners[i] = owners[owners.length - 1]; break; } owners.length -= 1; if (required > owners.length) changeRequirement(owners.length); OwnerRemoval(owner); } /// @dev Allows to replace an owner with a new owner. Transaction has to be sent by wallet. /// @param owner Address of owner to be replaced. /// @param owner Address of new owner. function replaceOwner(address owner, address newOwner) public onlyWallet ownerExists(owner) ownerDoesNotExist(newOwner) { for (uint i=0; i<owners.length; i++) if (owners[i] == owner) { owners[i] = newOwner; break; } isOwner[owner] = false; isOwner[newOwner] = true; OwnerRemoval(owner); OwnerAddition(newOwner); } /// @dev Allows to change the number of required confirmations. Transaction has to be sent by wallet. /// @param _required Number of required confirmations. function changeRequirement(uint _required) public onlyWallet validRequirement(owners.length, _required) { required = _required; RequirementChange(_required); } /// @dev Allows an owner to submit and confirm a transaction. /// @param destination Transaction target address. /// @param value Transaction ether value. /// @param data Transaction data payload. /// @return Returns transaction ID. function submitTransaction(address destination, uint value, bytes data) public returns (uint transactionId) { transactionId = addTransaction(destination, value, data); confirmTransaction(transactionId); } /// @dev Allows an owner to confirm a transaction. /// @param transactionId Transaction ID. function confirmTransaction(uint transactionId) public ownerExists(msg.sender) transactionExists(transactionId) notConfirmed(transactionId, msg.sender) { confirmations[transactionId][msg.sender] = true; Confirmation(msg.sender, transactionId); executeTransaction(transactionId); } /// @dev Allows an owner to revoke a confirmation for a transaction. /// @param transactionId Transaction ID. function revokeConfirmation(uint transactionId) public ownerExists(msg.sender) confirmed(transactionId, msg.sender) notExecuted(transactionId) { confirmations[transactionId][msg.sender] = false; Revocation(msg.sender, transactionId); } /// @dev Allows anyone to execute a confirmed transaction. /// @param transactionId Transaction ID. function executeTransaction(uint transactionId) public notExecuted(transactionId) { if (isConfirmed(transactionId)) { Transaction tx = transactions[transactionId]; tx.executed = true; if (tx.destination.call.value(tx.value)(tx.data)) Execution(transactionId); else { ExecutionFailure(transactionId); tx.executed = false; } } } /// @dev Returns the confirmation status of a transaction. /// @param transactionId Transaction ID. /// @return Confirmation status. function isConfirmed(uint transactionId) public constant returns (bool) { uint count = 0; for (uint i=0; i<owners.length; i++) { if (confirmations[transactionId][owners[i]]) count += 1; if (count == required) return true; } } /* * Internal functions */ /// @dev Adds a new transaction to the transaction mapping, if transaction does not exist yet. /// @param destination Transaction target address. /// @param value Transaction ether value. /// @param data Transaction data payload. /// @return Returns transaction ID. function addTransaction(address destination, uint value, bytes data) internal notNull(destination) returns (uint transactionId) { transactionId = transactionCount; transactions[transactionId] = Transaction({ destination: destination, value: value, data: data, executed: false }); transactionCount += 1; Submission(transactionId); } /* * Web3 call functions */ /// @dev Returns number of confirmations of a transaction. /// @param transactionId Transaction ID. /// @return Number of confirmations. function getConfirmationCount(uint transactionId) public constant returns (uint count) { for (uint i=0; i<owners.length; i++) if (confirmations[transactionId][owners[i]]) count += 1; } /// @dev Returns total number of transactions after filers are applied. /// @param pending Include pending transactions. /// @param executed Include executed transactions. /// @return Total number of transactions after filters are applied. function getTransactionCount(bool pending, bool executed) public constant returns (uint count) { for (uint i=0; i<transactionCount; i++) if ( pending && !transactions[i].executed || executed && transactions[i].executed) count += 1; } /// @dev Returns list of owners. /// @return List of owner addresses. function getOwners() public constant returns (address[]) { return owners; } /// @dev Returns array with owner addresses, which confirmed transaction. /// @param transactionId Transaction ID. /// @return Returns array of owner addresses. function getConfirmations(uint transactionId) public constant returns (address[] _confirmations) { address[] memory confirmationsTemp = new address[](owners.length); uint count = 0; uint i; for (i=0; i<owners.length; i++) if (confirmations[transactionId][owners[i]]) { confirmationsTemp[count] = owners[i]; count += 1; } _confirmations = new address[](count); for (i=0; i<count; i++) _confirmations[i] = confirmationsTemp[i]; } /// @dev Returns list of transaction IDs in defined range. /// @param from Index start position of transaction array. /// @param to Index end position of transaction array. /// @param pending Include pending transactions. /// @param executed Include executed transactions. /// @return Returns array of transaction IDs. function getTransactionIds(uint from, uint to, bool pending, bool executed) public constant returns (uint[] _transactionIds) { uint[] memory transactionIdsTemp = new uint[](transactionCount); uint count = 0; uint i; for (i=0; i<transactionCount; i++) if ( pending && !transactions[i].executed || executed && transactions[i].executed) { transactionIdsTemp[count] = i; count += 1; } _transactionIds = new uint[](to - from); for (i=from; i<to; i++) _transactionIds[i - from] = transactionIdsTemp[i]; } } /// @title Multisignature wallet with daily limit - Allows an owner to withdraw a daily limit without multisig. /// @author Stefan George - <[email protected]> contract MultiSigWalletWithDailyLimit is MultiSigWallet { event DailyLimitChange(uint dailyLimit); uint public dailyLimit; uint public lastDay; uint public spentToday; /* * Public functions */ /// @dev Contract constructor sets initial owners, required number of confirmations and daily withdraw limit. /// @param _owners List of initial owners. /// @param _required Number of required confirmations. /// @param _dailyLimit Amount in wei, which can be withdrawn without confirmations on a daily basis. function MultiSigWalletWithDailyLimit(address[] _owners, uint _required, uint _dailyLimit) public MultiSigWallet(_owners, _required) { dailyLimit = _dailyLimit; } /// @dev Allows to change the daily limit. Transaction has to be sent by wallet. /// @param _dailyLimit Amount in wei. function changeDailyLimit(uint _dailyLimit) public onlyWallet { dailyLimit = _dailyLimit; DailyLimitChange(_dailyLimit); } /// @dev Allows anyone to execute a confirmed transaction or ether withdraws until daily limit is reached. /// @param transactionId Transaction ID. function executeTransaction(uint transactionId) public notExecuted(transactionId) { Transaction tx = transactions[transactionId]; bool confirmed = isConfirmed(transactionId); if (confirmed || tx.data.length == 0 && isUnderLimit(tx.value)) { tx.executed = true; if (!confirmed) spentToday += tx.value; if (tx.destination.call.value(tx.value)(tx.data)) Execution(transactionId); else { ExecutionFailure(transactionId); tx.executed = false; if (!confirmed) spentToday -= tx.value; } } } /* * Internal functions */ /// @dev Returns if amount is within daily limit and resets spentToday after one day. /// @param amount Amount to withdraw. /// @return Returns if amount is under daily limit. function isUnderLimit(uint amount) internal returns (bool) { if (now > lastDay + 24 hours) { lastDay = now; spentToday = 0; } if (spentToday + amount > dailyLimit || spentToday + amount < spentToday) return false; return true; } /* * Web3 call functions */ /// @dev Returns maximum withdraw amount. /// @return Returns amount. function calcMaxWithdraw() public constant returns (uint) { if (now > lastDay + 24 hours) return dailyLimit; return dailyLimit - spentToday; } }
File 2 of 2: TokenOWLProxy
pragma solidity ^0.4.21; // File: @gnosis.pm/util-contracts/contracts/Proxy.sol /// @title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy. /// @author Alan Lu - <[email protected]> contract Proxied { address public masterCopy; } /// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract. /// @author Stefan George - <[email protected]> contract Proxy is Proxied { /// @dev Constructor function sets address of master copy contract. /// @param _masterCopy Master copy address. function Proxy(address _masterCopy) public { require(_masterCopy != 0); masterCopy = _masterCopy; } /// @dev Fallback function forwards all transactions and returns all received return data. function () external payable { address _masterCopy = masterCopy; assembly { calldatacopy(0, 0, calldatasize()) let success := delegatecall(not(0), _masterCopy, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch success case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } } // File: @gnosis.pm/util-contracts/contracts/Math.sol /// @title Math library - Allows calculation of logarithmic and exponential functions /// @author Alan Lu - <[email protected]> /// @author Stefan George - <[email protected]> library Math { /* * Constants */ // This is equal to 1 in our calculations uint public constant ONE = 0x10000000000000000; uint public constant LN2 = 0xb17217f7d1cf79ac; uint public constant LOG2_E = 0x171547652b82fe177; /* * Public functions */ /// @dev Returns natural exponential function value of given x /// @param x x /// @return e**x function exp(int x) public pure returns (uint) { // revert if x is > MAX_POWER, where // MAX_POWER = int(mp.floor(mp.log(mpf(2**256 - 1) / ONE) * ONE)) require(x <= 2454971259878909886679); // return 0 if exp(x) is tiny, using // MIN_POWER = int(mp.floor(mp.log(mpf(1) / ONE) * ONE)) if (x < -818323753292969962227) return 0; // Transform so that e^x -> 2^x x = x * int(ONE) / int(LN2); // 2^x = 2^whole(x) * 2^frac(x) // ^^^^^^^^^^ is a bit shift // so Taylor expand on z = frac(x) int shift; uint z; if (x >= 0) { shift = x / int(ONE); z = uint(x % int(ONE)); } else { shift = x / int(ONE) - 1; z = ONE - uint(-x % int(ONE)); } // 2^x = 1 + (ln 2) x + (ln 2)^2/2! x^2 + ... // // Can generate the z coefficients using mpmath and the following lines // >>> from mpmath import mp // >>> mp.dps = 100 // >>> ONE = 0x10000000000000000 // >>> print('\n'.join(hex(int(mp.log(2)**i / mp.factorial(i) * ONE)) for i in range(1, 7))) // 0xb17217f7d1cf79ab // 0x3d7f7bff058b1d50 // 0xe35846b82505fc5 // 0x276556df749cee5 // 0x5761ff9e299cc4 // 0xa184897c363c3 uint zpow = z; uint result = ONE; result += 0xb17217f7d1cf79ab * zpow / ONE; zpow = zpow * z / ONE; result += 0x3d7f7bff058b1d50 * zpow / ONE; zpow = zpow * z / ONE; result += 0xe35846b82505fc5 * zpow / ONE; zpow = zpow * z / ONE; result += 0x276556df749cee5 * zpow / ONE; zpow = zpow * z / ONE; result += 0x5761ff9e299cc4 * zpow / ONE; zpow = zpow * z / ONE; result += 0xa184897c363c3 * zpow / ONE; zpow = zpow * z / ONE; result += 0xffe5fe2c4586 * zpow / ONE; zpow = zpow * z / ONE; result += 0x162c0223a5c8 * zpow / ONE; zpow = zpow * z / ONE; result += 0x1b5253d395e * zpow / ONE; zpow = zpow * z / ONE; result += 0x1e4cf5158b * zpow / ONE; zpow = zpow * z / ONE; result += 0x1e8cac735 * zpow / ONE; zpow = zpow * z / ONE; result += 0x1c3bd650 * zpow / ONE; zpow = zpow * z / ONE; result += 0x1816193 * zpow / ONE; zpow = zpow * z / ONE; result += 0x131496 * zpow / ONE; zpow = zpow * z / ONE; result += 0xe1b7 * zpow / ONE; zpow = zpow * z / ONE; result += 0x9c7 * zpow / ONE; if (shift >= 0) { if (result >> (256-shift) > 0) return (2**256-1); return result << shift; } else return result >> (-shift); } /// @dev Returns natural logarithm value of given x /// @param x x /// @return ln(x) function ln(uint x) public pure returns (int) { require(x > 0); // binary search for floor(log2(x)) int ilog2 = floorLog2(x); int z; if (ilog2 < 0) z = int(x << uint(-ilog2)); else z = int(x >> uint(ilog2)); // z = x * 2^-⌊log₂x⌋ // so 1 <= z < 2 // and ln z = ln x - ⌊log₂x⌋/log₂e // so just compute ln z using artanh series // and calculate ln x from that int term = (z - int(ONE)) * int(ONE) / (z + int(ONE)); int halflnz = term; int termpow = term * term / int(ONE) * term / int(ONE); halflnz += termpow / 3; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 5; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 7; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 9; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 11; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 13; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 15; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 17; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 19; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 21; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 23; termpow = termpow * term / int(ONE) * term / int(ONE); halflnz += termpow / 25; return (ilog2 * int(ONE)) * int(ONE) / int(LOG2_E) + 2 * halflnz; } /// @dev Returns base 2 logarithm value of given x /// @param x x /// @return logarithmic value function floorLog2(uint x) public pure returns (int lo) { lo = -64; int hi = 193; // I use a shift here instead of / 2 because it floors instead of rounding towards 0 int mid = (hi + lo) >> 1; while((lo + 1) < hi) { if (mid < 0 && x << uint(-mid) < ONE || mid >= 0 && x >> uint(mid) < ONE) hi = mid; else lo = mid; mid = (hi + lo) >> 1; } } /// @dev Returns maximum of an array /// @param nums Numbers to look through /// @return Maximum number function max(int[] nums) public pure returns (int maxNum) { require(nums.length > 0); maxNum = -2**255; for (uint i = 0; i < nums.length; i++) if (nums[i] > maxNum) maxNum = nums[i]; } /// @dev Returns whether an add operation causes an overflow /// @param a First addend /// @param b Second addend /// @return Did no overflow occur? function safeToAdd(uint a, uint b) internal pure returns (bool) { return a + b >= a; } /// @dev Returns whether a subtraction operation causes an underflow /// @param a Minuend /// @param b Subtrahend /// @return Did no underflow occur? function safeToSub(uint a, uint b) internal pure returns (bool) { return a >= b; } /// @dev Returns whether a multiply operation causes an overflow /// @param a First factor /// @param b Second factor /// @return Did no overflow occur? function safeToMul(uint a, uint b) internal pure returns (bool) { return b == 0 || a * b / b == a; } /// @dev Returns sum if no overflow occurred /// @param a First addend /// @param b Second addend /// @return Sum function add(uint a, uint b) internal pure returns (uint) { require(safeToAdd(a, b)); return a + b; } /// @dev Returns difference if no overflow occurred /// @param a Minuend /// @param b Subtrahend /// @return Difference function sub(uint a, uint b) internal pure returns (uint) { require(safeToSub(a, b)); return a - b; } /// @dev Returns product if no overflow occurred /// @param a First factor /// @param b Second factor /// @return Product function mul(uint a, uint b) internal pure returns (uint) { require(safeToMul(a, b)); return a * b; } /// @dev Returns whether an add operation causes an overflow /// @param a First addend /// @param b Second addend /// @return Did no overflow occur? function safeToAdd(int a, int b) internal pure returns (bool) { return (b >= 0 && a + b >= a) || (b < 0 && a + b < a); } /// @dev Returns whether a subtraction operation causes an underflow /// @param a Minuend /// @param b Subtrahend /// @return Did no underflow occur? function safeToSub(int a, int b) internal pure returns (bool) { return (b >= 0 && a - b <= a) || (b < 0 && a - b > a); } /// @dev Returns whether a multiply operation causes an overflow /// @param a First factor /// @param b Second factor /// @return Did no overflow occur? function safeToMul(int a, int b) internal pure returns (bool) { return (b == 0) || (a * b / b == a); } /// @dev Returns sum if no overflow occurred /// @param a First addend /// @param b Second addend /// @return Sum function add(int a, int b) internal pure returns (int) { require(safeToAdd(a, b)); return a + b; } /// @dev Returns difference if no overflow occurred /// @param a Minuend /// @param b Subtrahend /// @return Difference function sub(int a, int b) internal pure returns (int) { require(safeToSub(a, b)); return a - b; } /// @dev Returns product if no overflow occurred /// @param a First factor /// @param b Second factor /// @return Product function mul(int a, int b) internal pure returns (int) { require(safeToMul(a, b)); return a * b; } } // File: @gnosis.pm/util-contracts/contracts/Token.sol /// Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md pragma solidity ^0.4.21; /// @title Abstract token contract - Functions to be implemented by token contracts contract Token { /* * Events */ event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); /* * Public functions */ function transfer(address to, uint value) public returns (bool); function transferFrom(address from, address to, uint value) public returns (bool); function approve(address spender, uint value) public returns (bool); function balanceOf(address owner) public view returns (uint); function allowance(address owner, address spender) public view returns (uint); function totalSupply() public view returns (uint); } // File: @gnosis.pm/util-contracts/contracts/StandardToken.sol contract StandardTokenData { /* * Storage */ mapping (address => uint) balances; mapping (address => mapping (address => uint)) allowances; uint totalTokens; } /// @title Standard token contract with overflow protection contract StandardToken is Token, StandardTokenData { using Math for *; /* * Public functions */ /// @dev Transfers sender's tokens to a given address. Returns success /// @param to Address of token receiver /// @param value Number of tokens to transfer /// @return Was transfer successful? function transfer(address to, uint value) public returns (bool) { if ( !balances[msg.sender].safeToSub(value) || !balances[to].safeToAdd(value)) return false; balances[msg.sender] -= value; balances[to] += value; emit Transfer(msg.sender, to, value); return true; } /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success /// @param from Address from where tokens are withdrawn /// @param to Address to where tokens are sent /// @param value Number of tokens to transfer /// @return Was transfer successful? function transferFrom(address from, address to, uint value) public returns (bool) { if ( !balances[from].safeToSub(value) || !allowances[from][msg.sender].safeToSub(value) || !balances[to].safeToAdd(value)) return false; balances[from] -= value; allowances[from][msg.sender] -= value; balances[to] += value; emit Transfer(from, to, value); return true; } /// @dev Sets approved amount of tokens for spender. Returns success /// @param spender Address of allowed account /// @param value Number of approved tokens /// @return Was approval successful? function approve(address spender, uint value) public returns (bool) { allowances[msg.sender][spender] = value; emit Approval(msg.sender, spender, value); return true; } /// @dev Returns number of allowed tokens for given address /// @param owner Address of token owner /// @param spender Address of token spender /// @return Remaining allowance for spender function allowance(address owner, address spender) public view returns (uint) { return allowances[owner][spender]; } /// @dev Returns number of tokens owned by given address /// @param owner Address of token owner /// @return Balance of owner function balanceOf(address owner) public view returns (uint) { return balances[owner]; } /// @dev Returns total supply of tokens /// @return Total supply function totalSupply() public view returns (uint) { return totalTokens; } } // File: contracts/TokenOWLProxy.sol contract TokenOWLProxy is Proxy, StandardToken { using Math for *; string public constant name = "OWL Token"; string public constant symbol = "OWL"; uint8 public constant decimals = 18; struct masterCopyCountdownType { address masterCopy; uint timeWhenAvailable; } masterCopyCountdownType masterCopyCountdown; address public creator; address public minter; /// @dev Constructor of the contract OWL, which distributes tokens function TokenOWLProxy(address proxied) Proxy(proxied) public { creator = msg.sender; } }