@etherspot/contracts
Version:
Etherspot Solidity contracts
52 lines • 15.7 kB
JSON
{
"language": "Solidity",
"sources": {
"src/tokens/WrappedWeiToken.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/lifecycle/Initializable.sol\";\nimport \"../common/token/ERC20Token.sol\";\nimport \"../gateway/GatewayRecipient.sol\";\n\n\n/**\n * @title Wrapped wei token\n *\n * @notice One to one wei consumable ERC20 token\n *\n * @dev After the transfer to consumer's account is done, the token will be automatically burned and withdrawn.\n *\n * Use `startConsuming` to become a consumer.\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract WrappedWeiToken is Initializable, ERC20Token, GatewayRecipient {\n mapping(address => bool) private consumers;\n\n // events\n\n /**\n * @dev Emitted when the new consumer is added\n * @param consumer consumer address\n */\n event ConsumerAdded(\n address consumer\n );\n\n /**\n * @dev Emitted when the existing consumer is removed\n * @param consumer consumer address\n */\n event ConsumerRemoved(\n address consumer\n );\n\n /**\n * @dev Public constructor\n */\n constructor()\n public\n Initializable()\n {\n name = \"Wrapped Wei\";\n symbol = \"WWEI\";\n }\n\n /**\n * @notice Receive fallback\n */\n receive()\n external\n payable\n {\n _mint(_getSender(), msg.value);\n }\n\n // external functions\n\n /**\n * @notice Initializes `WrappedWeiToken` contract\n * @param consumers_ array of consumers addresses\n * @param gateway_ `Gateway` contract address\n */\n function initialize(\n address[] calldata consumers_,\n address gateway_\n )\n external\n onlyInitializer\n {\n if (consumers_.length != 0) {\n uint consumersLen = consumers_.length;\n for (uint i = 0; i < consumersLen; i++) {\n _addConsumer(consumers_[i]);\n }\n }\n\n _initializeGatewayRecipient(gateway_);\n }\n\n /**\n * @notice Starts consuming\n * @dev Add caller as a consumer\n */\n function startConsuming()\n external\n {\n _addConsumer(_getSender());\n }\n\n /**\n * @notice Stops consuming\n * @dev Remove caller from consumers\n */\n function stopConsuming()\n external\n {\n address consumer = _getSender();\n\n require(\n consumers[consumer],\n \"WrappedWeiToken: consumer doesn't exist\"\n );\n\n consumers[consumer] = false;\n\n emit ConsumerRemoved(consumer);\n }\n\n /**\n * @notice Deposits `msg.value` to address\n * @param to to address\n */\n function depositTo(\n address to\n )\n external\n payable\n {\n _mint(to, msg.value);\n }\n\n /**\n * @notice Withdraws\n * @param value value to withdraw\n */\n function withdraw(\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), _getSender(), value);\n }\n\n /**\n * @notice Withdraws to address\n * @param to to address\n * @param value value to withdraw\n */\n function withdrawTo(\n address to,\n uint256 value\n )\n external\n {\n _withdraw(_getSender(), to, value);\n }\n\n /**\n * @notice Withdraws all\n */\n function withdrawAll()\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, sender, balances[sender]);\n }\n\n /**\n * @notice Withdraws all to address\n * @param to to address\n */\n function withdrawAllTo(\n address to\n )\n external\n {\n address sender = _getSender();\n\n _withdraw(sender, to, balances[sender]);\n }\n\n // external functions (views)\n\n /**\n * @notice Checks if consumer exists\n * @param consumer consumer address\n * @return true if consumer exists\n */\n function isConsumer(\n address consumer\n )\n external\n view\n returns (bool)\n {\n return consumers[consumer];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n override\n internal\n {\n if (consumers[to]) {\n _withdraw(from, to, value);\n } else {\n super._transfer(from, to, value);\n }\n }\n\n // internal functions (views)\n\n function _getSender()\n override\n internal\n view\n returns (address)\n {\n return _getContextAccount();\n }\n\n // private functions\n\n function _addConsumer(\n address consumer\n )\n private\n {\n require(\n !consumers[consumer],\n \"WrappedWeiToken: consumer already exists\"\n );\n\n consumers[consumer] = true;\n\n emit ConsumerAdded(consumer);\n }\n\n function _withdraw(\n address from,\n address to,\n uint256 value\n )\n private\n {\n _burn(from, value);\n\n require(\n // solhint-disable-next-line check-send-result\n payable(to).send(value),\n \"WrappedWeiToken: transaction reverted\"\n );\n }\n}\n"
},
"src/common/lifecycle/Initializable.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Initializable\n *\n * @dev Contract module which provides access control mechanism, where\n * there is the initializer account that can be granted exclusive access to\n * specific functions.\n *\n * The initializer account will be tx.origin during contract deployment and will be removed on first use.\n * Use `onlyInitializer` modifier on contract initialize process.\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract Initializable {\n address private initializer;\n\n // events\n\n /**\n * @dev Emitted after `onlyInitializer`\n * @param initializer initializer address\n */\n event Initialized(\n address initializer\n );\n\n // modifiers\n\n /**\n * @dev Throws if tx.origin is not the initializer\n */\n modifier onlyInitializer() {\n require(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin == initializer,\n \"Initializable: tx.origin is not the initializer\"\n );\n\n /// @dev removes initializer\n initializer = address(0);\n\n _;\n\n emit Initialized(\n // solhint-disable-next-line avoid-tx-origin\n tx.origin\n );\n }\n\n /**\n * @dev Internal constructor\n */\n constructor()\n internal\n {\n // solhint-disable-next-line avoid-tx-origin\n initializer = tx.origin;\n }\n\n // external functions (views)\n\n /**\n * @notice Check if contract is initialized\n * @return true when contract is initialized\n */\n function isInitialized()\n external\n view\n returns (bool)\n {\n return initializer == address(0);\n }\n}\n"
},
"src/common/token/ERC20Token.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../libs/SafeMathLib.sol\";\n\n\n/**\n * @title ERC20 token\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/ERC20.sol\n */\ncontract ERC20Token {\n using SafeMathLib for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n\n mapping(address => uint256) internal balances;\n mapping(address => mapping(address => uint256)) internal allowances;\n\n // events\n\n event Transfer(\n address indexed from,\n address indexed to,\n uint256 value\n );\n\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // external functions\n\n function transfer(\n address to,\n uint256 value\n )\n external\n returns (bool)\n {\n _transfer(_getSender(), to, value);\n\n return true;\n }\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n address sender = _getSender();\n\n _transfer(from, to, value);\n _approve(from, sender, allowances[from][sender].sub(value));\n\n return true;\n }\n\n function approve(\n address spender,\n uint256 value\n )\n virtual\n external\n returns (bool)\n {\n _approve(_getSender(), spender, value);\n\n return true;\n }\n\n // external functions (views)\n\n function balanceOf(\n address owner\n )\n virtual\n external\n view\n returns (uint256)\n {\n return balances[owner];\n }\n\n function allowance(\n address owner,\n address spender\n )\n virtual\n external\n view\n returns (uint256)\n {\n return allowances[owner][spender];\n }\n\n // internal functions\n\n function _transfer(\n address from,\n address to,\n uint256 value\n )\n virtual\n internal\n {\n require(\n from != address(0),\n \"ERC20Token: cannot transfer from 0x0 address\"\n );\n require(\n to != address(0),\n \"ERC20Token: cannot transfer to 0x0 address\"\n );\n\n balances[from] = balances[from].sub(value);\n balances[to] = balances[to].add(value);\n\n emit Transfer(from, to, value);\n }\n\n function _approve(\n address owner,\n address spender,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot approve from 0x0 address\"\n );\n require(\n spender != address(0),\n \"ERC20Token: cannot approve to 0x0 address\"\n );\n\n allowances[owner][spender] = value;\n\n emit Approval(owner, spender, value);\n }\n\n function _mint(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot mint to 0x0 address\"\n );\n require(\n value > 0,\n \"ERC20Token: cannot mint 0 value\"\n );\n\n balances[owner] = balances[owner].add(value);\n totalSupply = totalSupply.add(value);\n\n emit Transfer(address(0), owner, value);\n }\n\n function _burn(\n address owner,\n uint256 value\n )\n virtual\n internal\n {\n require(\n owner != address(0),\n \"ERC20Token: cannot burn from 0x0 address\"\n );\n\n balances[owner] = balances[owner].sub(\n value,\n \"ERC20Token: burn value exceeds balance\"\n );\n\n totalSupply = totalSupply.sub(value);\n\n emit Transfer(owner, address(0), value);\n }\n\n // internal functions (views)\n\n function _getSender()\n virtual\n internal\n view\n returns (address)\n {\n return msg.sender;\n }\n}\n"
},
"src/gateway/GatewayRecipient.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nimport \"../common/libs/BytesLib.sol\";\n\n\n/**\n * @title Gateway recipient\n *\n * @notice Gateway target contract\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\ncontract GatewayRecipient {\n using BytesLib for bytes;\n\n address public gateway;\n\n /**\n * @dev internal constructor\n */\n constructor() internal {}\n\n // internal functions\n\n /**\n * @notice Initializes `GatewayRecipient` contract\n * @param gateway_ `Gateway` contract address\n */\n function _initializeGatewayRecipient(\n address gateway_\n )\n internal\n {\n gateway = gateway_;\n }\n\n // internal functions (views)\n\n /**\n * @notice Gets gateway context account\n * @return context account address\n */\n function _getContextAccount()\n internal\n view\n returns (address)\n {\n return _getContextAddress(40);\n }\n\n /**\n * @notice Gets gateway context sender\n * @return context sender address\n */\n function _getContextSender()\n internal\n view\n returns (address)\n {\n return _getContextAddress(20);\n }\n\n /**\n * @notice Gets gateway context data\n * @return context data\n */\n function _getContextData()\n internal\n view\n returns (bytes calldata)\n {\n bytes calldata result;\n\n if (_isGatewaySender()) {\n result = msg.data[:msg.data.length - 40];\n } else {\n result = msg.data;\n }\n\n return result;\n }\n\n // private functions (views)\n\n function _getContextAddress(\n uint256 offset\n )\n private\n view\n returns (address)\n {\n address result = address(0);\n\n if (_isGatewaySender()) {\n uint from = msg.data.length - offset;\n result = bytes(msg.data[from:from + 20]).toAddress();\n } else {\n result = msg.sender;\n }\n\n return result;\n }\n\n function _isGatewaySender()\n private\n view\n returns (bool)\n {\n bool result;\n\n if (msg.sender == gateway) {\n require(\n msg.data.length >= 44,\n \"GatewayRecipient: invalid msg.data\"\n );\n\n result = true;\n }\n\n return result;\n }\n}\n"
},
"src/common/libs/SafeMathLib.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Safe math library\n *\n * @dev Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/math/SafeMath.sol\n */\nlibrary SafeMathLib {\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n\n require(c >= a, \"SafeMathLib: addition overflow\");\n\n return c;\n }\n\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMathLib: subtraction overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n\n return a - b;\n }\n\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n\n require(c / a == b, \"SafeMathLib: multiplication overflow\");\n\n return c;\n }\n\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMathLib: division by zero\");\n }\n\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n\n return a / b;\n }\n\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMathLib: modulo by zero\");\n }\n\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n\n return a % b;\n }\n}\n"
},
"src/common/libs/BytesLib.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\n/**\n * @title Bytes library\n *\n * @author Stanisław Głogowski <stan@pillarproject.io>\n */\nlibrary BytesLib {\n /**\n * @notice Converts bytes to address\n * @param data data\n * @return address\n */\n function toAddress(\n bytes memory data\n )\n internal\n pure\n returns (address)\n {\n address result;\n\n require(\n data.length == 20,\n \"BytesLib: invalid data length\"\n );\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := div(mload(add(data, 0x20)), 0x1000000000000000000000000)\n }\n\n return result;\n }\n}\n"
}
},
"settings": {
"evmVersion": "istanbul",
"metadata": {
"bytecodeHash": "none",
"useLiteralContent": true
},
"optimizer": {
"enabled": false,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata",
"devdoc",
"userdoc",
"storageLayout",
"evm.gasEstimates"
],
"": [
"ast"
]
}
}
}
}