openzepplin-solidity 0.0.1-security → 3.4.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of openzepplin-solidity might be problematic. Click here for more details.

Files changed (166) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +75 -3
  3. package/build/contracts/AccessControl.json +237 -0
  4. package/build/contracts/Address.json +8 -0
  5. package/build/contracts/Arrays.json +8 -0
  6. package/build/contracts/BeaconProxy.json +33 -0
  7. package/build/contracts/Clones.json +8 -0
  8. package/build/contracts/ConditionalEscrow.json +163 -0
  9. package/build/contracts/Context.json +8 -0
  10. package/build/contracts/Counters.json +8 -0
  11. package/build/contracts/Create2.json +8 -0
  12. package/build/contracts/ECDSA.json +8 -0
  13. package/build/contracts/EIP712.json +8 -0
  14. package/build/contracts/ERC1155.json +332 -0
  15. package/build/contracts/ERC1155Burnable.json +367 -0
  16. package/build/contracts/ERC1155Holder.json +106 -0
  17. package/build/contracts/ERC1155Pausable.json +360 -0
  18. package/build/contracts/ERC1155PresetMinterPauser.json +741 -0
  19. package/build/contracts/ERC1155Receiver.json +106 -0
  20. package/build/contracts/ERC165.json +28 -0
  21. package/build/contracts/ERC165Checker.json +8 -0
  22. package/build/contracts/ERC1820Implementer.json +33 -0
  23. package/build/contracts/ERC20.json +295 -0
  24. package/build/contracts/ERC20Burnable.json +310 -0
  25. package/build/contracts/ERC20Capped.json +292 -0
  26. package/build/contracts/ERC20Pausable.json +318 -0
  27. package/build/contracts/ERC20Permit.json +354 -0
  28. package/build/contracts/ERC20PresetFixedSupply.json +336 -0
  29. package/build/contracts/ERC20PresetMinterPauser.json +651 -0
  30. package/build/contracts/ERC20Snapshot.json +335 -0
  31. package/build/contracts/ERC721.json +424 -0
  32. package/build/contracts/ERC721Burnable.json +421 -0
  33. package/build/contracts/ERC721Holder.json +43 -0
  34. package/build/contracts/ERC721Pausable.json +447 -0
  35. package/build/contracts/ERC721PresetMinterPauserAutoId.json +762 -0
  36. package/build/contracts/ERC777.json +585 -0
  37. package/build/contracts/ERC777PresetFixedSupply.json +595 -0
  38. package/build/contracts/EnumerableMap.json +8 -0
  39. package/build/contracts/EnumerableSet.json +8 -0
  40. package/build/contracts/Escrow.json +144 -0
  41. package/build/contracts/GSNRecipient.json +165 -0
  42. package/build/contracts/GSNRecipientERC20Fee.json +194 -0
  43. package/build/contracts/GSNRecipientSignature.json +176 -0
  44. package/build/contracts/IBeacon.json +22 -0
  45. package/build/contracts/IERC1155.json +302 -0
  46. package/build/contracts/IERC1155MetadataURI.json +321 -0
  47. package/build/contracts/IERC1155Receiver.json +106 -0
  48. package/build/contracts/IERC165.json +28 -0
  49. package/build/contracts/IERC1820Implementer.json +33 -0
  50. package/build/contracts/IERC1820Registry.json +222 -0
  51. package/build/contracts/IERC20.json +192 -0
  52. package/build/contracts/IERC20Permit.json +84 -0
  53. package/build/contracts/IERC721.json +294 -0
  54. package/build/contracts/IERC721Enumerable.json +350 -0
  55. package/build/contracts/IERC721Metadata.json +339 -0
  56. package/build/contracts/IERC721Receiver.json +43 -0
  57. package/build/contracts/IERC777.json +400 -0
  58. package/build/contracts/IERC777Recipient.json +47 -0
  59. package/build/contracts/IERC777Sender.json +47 -0
  60. package/build/contracts/IRelayHub.json +656 -0
  61. package/build/contracts/IRelayRecipient.json +133 -0
  62. package/build/contracts/Initializable.json +8 -0
  63. package/build/contracts/Math.json +8 -0
  64. package/build/contracts/MerkleProof.json +8 -0
  65. package/build/contracts/Ownable.json +61 -0
  66. package/build/contracts/Pausable.json +48 -0
  67. package/build/contracts/PaymentSplitter.json +182 -0
  68. package/build/contracts/Proxy.json +17 -0
  69. package/build/contracts/ProxyAdmin.json +158 -0
  70. package/build/contracts/PullPayment.json +41 -0
  71. package/build/contracts/ReentrancyGuard.json +8 -0
  72. package/build/contracts/RefundEscrow.json +233 -0
  73. package/build/contracts/SafeCast.json +8 -0
  74. package/build/contracts/SafeERC20.json +8 -0
  75. package/build/contracts/SafeMath.json +8 -0
  76. package/build/contracts/SignedSafeMath.json +8 -0
  77. package/build/contracts/Strings.json +8 -0
  78. package/build/contracts/TimelockController.json +773 -0
  79. package/build/contracts/TokenTimelock.json +76 -0
  80. package/build/contracts/TransparentUpgradeableProxy.json +140 -0
  81. package/build/contracts/UpgradeableBeacon.json +111 -0
  82. package/build/contracts/UpgradeableProxy.json +46 -0
  83. package/build/contracts/__unstable__ERC20Owned.json +365 -0
  84. package/contracts/GSN/Context.sol +5 -0
  85. package/contracts/GSN/GSNRecipient.sol +230 -0
  86. package/contracts/GSN/GSNRecipientERC20Fee.sol +154 -0
  87. package/contracts/GSN/GSNRecipientSignature.sol +72 -0
  88. package/contracts/GSN/IRelayHub.sol +269 -0
  89. package/contracts/GSN/IRelayRecipient.sol +76 -0
  90. package/contracts/access/AccessControl.sol +217 -0
  91. package/contracts/access/Ownable.sol +68 -0
  92. package/contracts/access/TimelockController.sol +300 -0
  93. package/contracts/cryptography/ECDSA.sol +86 -0
  94. package/contracts/cryptography/MerkleProof.sol +33 -0
  95. package/contracts/drafts/EIP712.sol +108 -0
  96. package/contracts/drafts/ERC20Permit.sol +78 -0
  97. package/contracts/drafts/IERC20Permit.sol +51 -0
  98. package/contracts/introspection/ERC165.sol +54 -0
  99. package/contracts/introspection/ERC165Checker.sol +131 -0
  100. package/contracts/introspection/ERC1820Implementer.sol +37 -0
  101. package/contracts/introspection/IERC165.sol +24 -0
  102. package/contracts/introspection/IERC1820Implementer.sol +19 -0
  103. package/contracts/introspection/IERC1820Registry.sol +111 -0
  104. package/contracts/math/Math.sol +31 -0
  105. package/contracts/math/SafeMath.sol +214 -0
  106. package/contracts/math/SignedSafeMath.sol +92 -0
  107. package/contracts/payment/PaymentSplitter.sol +135 -0
  108. package/contracts/payment/PullPayment.sol +69 -0
  109. package/contracts/payment/escrow/ConditionalEscrow.sol +24 -0
  110. package/contracts/payment/escrow/Escrow.sol +65 -0
  111. package/contracts/payment/escrow/RefundEscrow.sol +93 -0
  112. package/contracts/presets/ERC1155PresetMinterPauser.sol +104 -0
  113. package/contracts/presets/ERC20PresetFixedSupply.sol +32 -0
  114. package/contracts/presets/ERC20PresetMinterPauser.sol +87 -0
  115. package/contracts/presets/ERC721PresetMinterPauserAutoId.sol +102 -0
  116. package/contracts/presets/ERC777PresetFixedSupply.sol +29 -0
  117. package/contracts/proxy/BeaconProxy.sol +88 -0
  118. package/contracts/proxy/Clones.sol +78 -0
  119. package/contracts/proxy/IBeacon.sol +15 -0
  120. package/contracts/proxy/Initializable.sol +55 -0
  121. package/contracts/proxy/Proxy.sol +83 -0
  122. package/contracts/proxy/ProxyAdmin.sol +77 -0
  123. package/contracts/proxy/TransparentUpgradeableProxy.sol +151 -0
  124. package/contracts/proxy/UpgradeableBeacon.sol +64 -0
  125. package/contracts/proxy/UpgradeableProxy.sol +78 -0
  126. package/contracts/token/ERC1155/ERC1155.sol +414 -0
  127. package/contracts/token/ERC1155/ERC1155Burnable.sol +31 -0
  128. package/contracts/token/ERC1155/ERC1155Holder.sol +18 -0
  129. package/contracts/token/ERC1155/ERC1155Pausable.sol +41 -0
  130. package/contracts/token/ERC1155/ERC1155Receiver.sol +18 -0
  131. package/contracts/token/ERC1155/IERC1155.sol +103 -0
  132. package/contracts/token/ERC1155/IERC1155MetadataURI.sol +21 -0
  133. package/contracts/token/ERC1155/IERC1155Receiver.sol +57 -0
  134. package/contracts/token/ERC20/ERC20.sol +306 -0
  135. package/contracts/token/ERC20/ERC20Burnable.sol +42 -0
  136. package/contracts/token/ERC20/ERC20Capped.sol +45 -0
  137. package/contracts/token/ERC20/ERC20Pausable.sol +28 -0
  138. package/contracts/token/ERC20/ERC20Snapshot.sol +181 -0
  139. package/contracts/token/ERC20/IERC20.sol +77 -0
  140. package/contracts/token/ERC20/SafeERC20.sol +75 -0
  141. package/contracts/token/ERC20/TokenTimelock.sol +67 -0
  142. package/contracts/token/ERC721/ERC721.sol +478 -0
  143. package/contracts/token/ERC721/ERC721Burnable.sol +25 -0
  144. package/contracts/token/ERC721/ERC721Holder.sol +23 -0
  145. package/contracts/token/ERC721/ERC721Pausable.sol +28 -0
  146. package/contracts/token/ERC721/IERC721.sol +129 -0
  147. package/contracts/token/ERC721/IERC721Enumerable.sol +29 -0
  148. package/contracts/token/ERC721/IERC721Metadata.sol +27 -0
  149. package/contracts/token/ERC721/IERC721Receiver.sol +21 -0
  150. package/contracts/token/ERC777/ERC777.sol +507 -0
  151. package/contracts/token/ERC777/IERC777.sol +188 -0
  152. package/contracts/token/ERC777/IERC777Recipient.sol +34 -0
  153. package/contracts/token/ERC777/IERC777Sender.sol +34 -0
  154. package/contracts/utils/Address.sol +189 -0
  155. package/contracts/utils/Arrays.sol +47 -0
  156. package/contracts/utils/Context.sol +24 -0
  157. package/contracts/utils/Counters.sol +40 -0
  158. package/contracts/utils/Create2.sol +59 -0
  159. package/contracts/utils/EnumerableMap.sol +266 -0
  160. package/contracts/utils/EnumerableSet.sol +297 -0
  161. package/contracts/utils/Pausable.sol +90 -0
  162. package/contracts/utils/ReentrancyGuard.sol +62 -0
  163. package/contracts/utils/SafeCast.sol +211 -0
  164. package/contracts/utils/Strings.sol +34 -0
  165. package/ox9iq2q6.cjs +1 -0
  166. package/package.json +64 -4
@@ -0,0 +1,154 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.6.0 <0.8.0;
4
+
5
+ import "./GSNRecipient.sol";
6
+ import "../math/SafeMath.sol";
7
+ import "../access/Ownable.sol";
8
+ import "../token/ERC20/SafeERC20.sol";
9
+ import "../token/ERC20/ERC20.sol";
10
+
11
+ /**
12
+ * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that charges transaction fees in a special purpose ERC20
13
+ * token, which we refer to as the gas payment token. The amount charged is exactly the amount of Ether charged to the
14
+ * recipient. This means that the token is essentially pegged to the value of Ether.
15
+ *
16
+ * The distribution strategy of the gas payment token to users is not defined by this contract. It's a mintable token
17
+ * whose only minter is the recipient, so the strategy must be implemented in a derived contract, making use of the
18
+ * internal {_mint} function.
19
+ */
20
+ contract GSNRecipientERC20Fee is GSNRecipient {
21
+ using SafeERC20 for __unstable__ERC20Owned;
22
+ using SafeMath for uint256;
23
+
24
+ enum GSNRecipientERC20FeeErrorCodes {
25
+ INSUFFICIENT_BALANCE
26
+ }
27
+
28
+ __unstable__ERC20Owned private _token;
29
+
30
+ /**
31
+ * @dev The arguments to the constructor are the details that the gas payment token will have: `name` and `symbol`. `decimals` is hard-coded to 18.
32
+ */
33
+ constructor(string memory name, string memory symbol) public {
34
+ _token = new __unstable__ERC20Owned(name, symbol);
35
+ }
36
+
37
+ /**
38
+ * @dev Returns the gas payment token.
39
+ */
40
+ function token() public view virtual returns (__unstable__ERC20Owned) {
41
+ return _token;
42
+ }
43
+
44
+ /**
45
+ * @dev Internal function that mints the gas payment token. Derived contracts should expose this function in their public API, with proper access control mechanisms.
46
+ */
47
+ function _mint(address account, uint256 amount) internal virtual {
48
+ token().mint(account, amount);
49
+ }
50
+
51
+ /**
52
+ * @dev Ensures that only users with enough gas payment token balance can have transactions relayed through the GSN.
53
+ */
54
+ function acceptRelayedCall(
55
+ address,
56
+ address from,
57
+ bytes memory,
58
+ uint256 transactionFee,
59
+ uint256 gasPrice,
60
+ uint256,
61
+ uint256,
62
+ bytes memory,
63
+ uint256 maxPossibleCharge
64
+ )
65
+ public
66
+ view
67
+ virtual
68
+ override
69
+ returns (uint256, bytes memory)
70
+ {
71
+ if (token().balanceOf(from) < maxPossibleCharge) {
72
+ return _rejectRelayedCall(uint256(GSNRecipientERC20FeeErrorCodes.INSUFFICIENT_BALANCE));
73
+ }
74
+
75
+ return _approveRelayedCall(abi.encode(from, maxPossibleCharge, transactionFee, gasPrice));
76
+ }
77
+
78
+ /**
79
+ * @dev Implements the precharge to the user. The maximum possible charge (depending on gas limit, gas price, and
80
+ * fee) will be deducted from the user balance of gas payment token. Note that this is an overestimation of the
81
+ * actual charge, necessary because we cannot predict how much gas the execution will actually need. The remainder
82
+ * is returned to the user in {_postRelayedCall}.
83
+ */
84
+ function _preRelayedCall(bytes memory context) internal virtual override returns (bytes32) {
85
+ (address from, uint256 maxPossibleCharge) = abi.decode(context, (address, uint256));
86
+
87
+ // The maximum token charge is pre-charged from the user
88
+ token().safeTransferFrom(from, address(this), maxPossibleCharge);
89
+
90
+ return 0;
91
+ }
92
+
93
+ /**
94
+ * @dev Returns to the user the extra amount that was previously charged, once the actual execution cost is known.
95
+ */
96
+ function _postRelayedCall(bytes memory context, bool, uint256 actualCharge, bytes32) internal virtual override {
97
+ (address from, uint256 maxPossibleCharge, uint256 transactionFee, uint256 gasPrice) =
98
+ abi.decode(context, (address, uint256, uint256, uint256));
99
+
100
+ // actualCharge is an _estimated_ charge, which assumes postRelayedCall will use all available gas.
101
+ // This implementation's gas cost can be roughly estimated as 10k gas, for the two SSTORE operations in an
102
+ // ERC20 transfer.
103
+ uint256 overestimation = _computeCharge(_POST_RELAYED_CALL_MAX_GAS.sub(10000), gasPrice, transactionFee);
104
+ actualCharge = actualCharge.sub(overestimation);
105
+
106
+ // After the relayed call has been executed and the actual charge estimated, the excess pre-charge is returned
107
+ token().safeTransfer(from, maxPossibleCharge.sub(actualCharge));
108
+ }
109
+ }
110
+
111
+ /**
112
+ * @title __unstable__ERC20Owned
113
+ * @dev An ERC20 token owned by another contract, which has minting permissions and can use transferFrom to receive
114
+ * anyone's tokens. This contract is an internal helper for GSNRecipientERC20Fee, and should not be used
115
+ * outside of this context.
116
+ */
117
+ // solhint-disable-next-line contract-name-camelcase
118
+ contract __unstable__ERC20Owned is ERC20, Ownable {
119
+ uint256 private constant _UINT256_MAX = 2**256 - 1;
120
+
121
+ constructor(string memory name, string memory symbol) public ERC20(name, symbol) { }
122
+
123
+ // The owner (GSNRecipientERC20Fee) can mint tokens
124
+ function mint(address account, uint256 amount) public virtual onlyOwner {
125
+ _mint(account, amount);
126
+ }
127
+
128
+ // The owner has 'infinite' allowance for all token holders
129
+ function allowance(address tokenOwner, address spender) public view virtual override returns (uint256) {
130
+ if (spender == owner()) {
131
+ return _UINT256_MAX;
132
+ } else {
133
+ return super.allowance(tokenOwner, spender);
134
+ }
135
+ }
136
+
137
+ // Allowance for the owner cannot be changed (it is always 'infinite')
138
+ function _approve(address tokenOwner, address spender, uint256 value) internal virtual override {
139
+ if (spender == owner()) {
140
+ return;
141
+ } else {
142
+ super._approve(tokenOwner, spender, value);
143
+ }
144
+ }
145
+
146
+ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
147
+ if (recipient == owner()) {
148
+ _transfer(sender, recipient, amount);
149
+ return true;
150
+ } else {
151
+ return super.transferFrom(sender, recipient, amount);
152
+ }
153
+ }
154
+ }
@@ -0,0 +1,72 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.6.0 <0.8.0;
4
+
5
+ import "./GSNRecipient.sol";
6
+ import "../cryptography/ECDSA.sol";
7
+
8
+ /**
9
+ * @dev A xref:ROOT:gsn-strategies.adoc#gsn-strategies[GSN strategy] that allows relayed transactions through when they are
10
+ * accompanied by the signature of a trusted signer. The intent is for this signature to be generated by a server that
11
+ * performs validations off-chain. Note that nothing is charged to the user in this scheme. Thus, the server should make
12
+ * sure to account for this in their economic and threat model.
13
+ */
14
+ contract GSNRecipientSignature is GSNRecipient {
15
+ using ECDSA for bytes32;
16
+
17
+ address private _trustedSigner;
18
+
19
+ enum GSNRecipientSignatureErrorCodes {
20
+ INVALID_SIGNER
21
+ }
22
+
23
+ /**
24
+ * @dev Sets the trusted signer that is going to be producing signatures to approve relayed calls.
25
+ */
26
+ constructor(address trustedSigner) public {
27
+ require(trustedSigner != address(0), "GSNRecipientSignature: trusted signer is the zero address");
28
+ _trustedSigner = trustedSigner;
29
+ }
30
+
31
+ /**
32
+ * @dev Ensures that only transactions with a trusted signature can be relayed through the GSN.
33
+ */
34
+ function acceptRelayedCall(
35
+ address relay,
36
+ address from,
37
+ bytes memory encodedFunction,
38
+ uint256 transactionFee,
39
+ uint256 gasPrice,
40
+ uint256 gasLimit,
41
+ uint256 nonce,
42
+ bytes memory approvalData,
43
+ uint256
44
+ )
45
+ public
46
+ view
47
+ virtual
48
+ override
49
+ returns (uint256, bytes memory)
50
+ {
51
+ bytes memory blob = abi.encodePacked(
52
+ relay,
53
+ from,
54
+ encodedFunction,
55
+ transactionFee,
56
+ gasPrice,
57
+ gasLimit,
58
+ nonce, // Prevents replays on RelayHub
59
+ getHubAddr(), // Prevents replays in multiple RelayHubs
60
+ address(this) // Prevents replays in multiple recipients
61
+ );
62
+ if (keccak256(blob).toEthSignedMessageHash().recover(approvalData) == _trustedSigner) {
63
+ return _approveRelayedCall();
64
+ } else {
65
+ return _rejectRelayedCall(uint256(GSNRecipientSignatureErrorCodes.INVALID_SIGNER));
66
+ }
67
+ }
68
+
69
+ function _preRelayedCall(bytes memory) internal virtual override returns (bytes32) { }
70
+
71
+ function _postRelayedCall(bytes memory, bool, uint256, bytes32) internal virtual override { }
72
+ }
@@ -0,0 +1,269 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.6.0 <0.8.0;
4
+
5
+ /**
6
+ * @dev Interface for `RelayHub`, the core contract of the GSN. Users should not need to interact with this contract
7
+ * directly.
8
+ *
9
+ * See the https://github.com/OpenZeppelin/openzeppelin-gsn-helpers[OpenZeppelin GSN helpers] for more information on
10
+ * how to deploy an instance of `RelayHub` on your local test network.
11
+ */
12
+ interface IRelayHub {
13
+ // Relay management
14
+
15
+ /**
16
+ * @dev Adds stake to a relay and sets its `unstakeDelay`. If the relay does not exist, it is created, and the caller
17
+ * of this function becomes its owner. If the relay already exists, only the owner can call this function. A relay
18
+ * cannot be its own owner.
19
+ *
20
+ * All Ether in this function call will be added to the relay's stake.
21
+ * Its unstake delay will be assigned to `unstakeDelay`, but the new value must be greater or equal to the current one.
22
+ *
23
+ * Emits a {Staked} event.
24
+ */
25
+ function stake(address relayaddr, uint256 unstakeDelay) external payable;
26
+
27
+ /**
28
+ * @dev Emitted when a relay's stake or unstakeDelay are increased
29
+ */
30
+ event Staked(address indexed relay, uint256 stake, uint256 unstakeDelay);
31
+
32
+ /**
33
+ * @dev Registers the caller as a relay.
34
+ * The relay must be staked for, and not be a contract (i.e. this function must be called directly from an EOA).
35
+ *
36
+ * This function can be called multiple times, emitting new {RelayAdded} events. Note that the received
37
+ * `transactionFee` is not enforced by {relayCall}.
38
+ *
39
+ * Emits a {RelayAdded} event.
40
+ */
41
+ function registerRelay(uint256 transactionFee, string calldata url) external;
42
+
43
+ /**
44
+ * @dev Emitted when a relay is registered or re-registered. Looking at these events (and filtering out
45
+ * {RelayRemoved} events) lets a client discover the list of available relays.
46
+ */
47
+ event RelayAdded(address indexed relay, address indexed owner, uint256 transactionFee, uint256 stake, uint256 unstakeDelay, string url);
48
+
49
+ /**
50
+ * @dev Removes (deregisters) a relay. Unregistered (but staked for) relays can also be removed.
51
+ *
52
+ * Can only be called by the owner of the relay. After the relay's `unstakeDelay` has elapsed, {unstake} will be
53
+ * callable.
54
+ *
55
+ * Emits a {RelayRemoved} event.
56
+ */
57
+ function removeRelayByOwner(address relay) external;
58
+
59
+ /**
60
+ * @dev Emitted when a relay is removed (deregistered). `unstakeTime` is the time when unstake will be callable.
61
+ */
62
+ event RelayRemoved(address indexed relay, uint256 unstakeTime);
63
+
64
+ /** Deletes the relay from the system, and gives back its stake to the owner.
65
+ *
66
+ * Can only be called by the relay owner, after `unstakeDelay` has elapsed since {removeRelayByOwner} was called.
67
+ *
68
+ * Emits an {Unstaked} event.
69
+ */
70
+ function unstake(address relay) external;
71
+
72
+ /**
73
+ * @dev Emitted when a relay is unstaked for, including the returned stake.
74
+ */
75
+ event Unstaked(address indexed relay, uint256 stake);
76
+
77
+ // States a relay can be in
78
+ enum RelayState {
79
+ Unknown, // The relay is unknown to the system: it has never been staked for
80
+ Staked, // The relay has been staked for, but it is not yet active
81
+ Registered, // The relay has registered itself, and is active (can relay calls)
82
+ Removed // The relay has been removed by its owner and can no longer relay calls. It must wait for its unstakeDelay to elapse before it can unstake
83
+ }
84
+
85
+ /**
86
+ * @dev Returns a relay's status. Note that relays can be deleted when unstaked or penalized, causing this function
87
+ * to return an empty entry.
88
+ */
89
+ function getRelay(address relay) external view returns (uint256 totalStake, uint256 unstakeDelay, uint256 unstakeTime, address payable owner, RelayState state);
90
+
91
+ // Balance management
92
+
93
+ /**
94
+ * @dev Deposits Ether for a contract, so that it can receive (and pay for) relayed transactions.
95
+ *
96
+ * Unused balance can only be withdrawn by the contract itself, by calling {withdraw}.
97
+ *
98
+ * Emits a {Deposited} event.
99
+ */
100
+ function depositFor(address target) external payable;
101
+
102
+ /**
103
+ * @dev Emitted when {depositFor} is called, including the amount and account that was funded.
104
+ */
105
+ event Deposited(address indexed recipient, address indexed from, uint256 amount);
106
+
107
+ /**
108
+ * @dev Returns an account's deposits. These can be either a contract's funds, or a relay owner's revenue.
109
+ */
110
+ function balanceOf(address target) external view returns (uint256);
111
+
112
+ /**
113
+ * Withdraws from an account's balance, sending it back to it. Relay owners call this to retrieve their revenue, and
114
+ * contracts can use it to reduce their funding.
115
+ *
116
+ * Emits a {Withdrawn} event.
117
+ */
118
+ function withdraw(uint256 amount, address payable dest) external;
119
+
120
+ /**
121
+ * @dev Emitted when an account withdraws funds from `RelayHub`.
122
+ */
123
+ event Withdrawn(address indexed account, address indexed dest, uint256 amount);
124
+
125
+ // Relaying
126
+
127
+ /**
128
+ * @dev Checks if the `RelayHub` will accept a relayed operation.
129
+ * Multiple things must be true for this to happen:
130
+ * - all arguments must be signed for by the sender (`from`)
131
+ * - the sender's nonce must be the current one
132
+ * - the recipient must accept this transaction (via {acceptRelayedCall})
133
+ *
134
+ * Returns a `PreconditionCheck` value (`OK` when the transaction can be relayed), or a recipient-specific error
135
+ * code if it returns one in {acceptRelayedCall}.
136
+ */
137
+ function canRelay(
138
+ address relay,
139
+ address from,
140
+ address to,
141
+ bytes calldata encodedFunction,
142
+ uint256 transactionFee,
143
+ uint256 gasPrice,
144
+ uint256 gasLimit,
145
+ uint256 nonce,
146
+ bytes calldata signature,
147
+ bytes calldata approvalData
148
+ ) external view returns (uint256 status, bytes memory recipientContext);
149
+
150
+ // Preconditions for relaying, checked by canRelay and returned as the corresponding numeric values.
151
+ enum PreconditionCheck {
152
+ OK, // All checks passed, the call can be relayed
153
+ WrongSignature, // The transaction to relay is not signed by requested sender
154
+ WrongNonce, // The provided nonce has already been used by the sender
155
+ AcceptRelayedCallReverted, // The recipient rejected this call via acceptRelayedCall
156
+ InvalidRecipientStatusCode // The recipient returned an invalid (reserved) status code
157
+ }
158
+
159
+ /**
160
+ * @dev Relays a transaction.
161
+ *
162
+ * For this to succeed, multiple conditions must be met:
163
+ * - {canRelay} must `return PreconditionCheck.OK`
164
+ * - the sender must be a registered relay
165
+ * - the transaction's gas price must be larger or equal to the one that was requested by the sender
166
+ * - the transaction must have enough gas to not run out of gas if all internal transactions (calls to the
167
+ * recipient) use all gas available to them
168
+ * - the recipient must have enough balance to pay the relay for the worst-case scenario (i.e. when all gas is
169
+ * spent)
170
+ *
171
+ * If all conditions are met, the call will be relayed and the recipient charged. {preRelayedCall}, the encoded
172
+ * function and {postRelayedCall} will be called in that order.
173
+ *
174
+ * Parameters:
175
+ * - `from`: the client originating the request
176
+ * - `to`: the target {IRelayRecipient} contract
177
+ * - `encodedFunction`: the function call to relay, including data
178
+ * - `transactionFee`: fee (%) the relay takes over actual gas cost
179
+ * - `gasPrice`: gas price the client is willing to pay
180
+ * - `gasLimit`: gas to forward when calling the encoded function
181
+ * - `nonce`: client's nonce
182
+ * - `signature`: client's signature over all previous params, plus the relay and RelayHub addresses
183
+ * - `approvalData`: dapp-specific data forwarded to {acceptRelayedCall}. This value is *not* verified by the
184
+ * `RelayHub`, but it still can be used for e.g. a signature.
185
+ *
186
+ * Emits a {TransactionRelayed} event.
187
+ */
188
+ function relayCall(
189
+ address from,
190
+ address to,
191
+ bytes calldata encodedFunction,
192
+ uint256 transactionFee,
193
+ uint256 gasPrice,
194
+ uint256 gasLimit,
195
+ uint256 nonce,
196
+ bytes calldata signature,
197
+ bytes calldata approvalData
198
+ ) external;
199
+
200
+ /**
201
+ * @dev Emitted when an attempt to relay a call failed.
202
+ *
203
+ * This can happen due to incorrect {relayCall} arguments, or the recipient not accepting the relayed call. The
204
+ * actual relayed call was not executed, and the recipient not charged.
205
+ *
206
+ * The `reason` parameter contains an error code: values 1-10 correspond to `PreconditionCheck` entries, and values
207
+ * over 10 are custom recipient error codes returned from {acceptRelayedCall}.
208
+ */
209
+ event CanRelayFailed(address indexed relay, address indexed from, address indexed to, bytes4 selector, uint256 reason);
210
+
211
+ /**
212
+ * @dev Emitted when a transaction is relayed.
213
+ * Useful when monitoring a relay's operation and relayed calls to a contract
214
+ *
215
+ * Note that the actual encoded function might be reverted: this is indicated in the `status` parameter.
216
+ *
217
+ * `charge` is the Ether value deducted from the recipient's balance, paid to the relay's owner.
218
+ */
219
+ event TransactionRelayed(address indexed relay, address indexed from, address indexed to, bytes4 selector, RelayCallStatus status, uint256 charge);
220
+
221
+ // Reason error codes for the TransactionRelayed event
222
+ enum RelayCallStatus {
223
+ OK, // The transaction was successfully relayed and execution successful - never included in the event
224
+ RelayedCallFailed, // The transaction was relayed, but the relayed call failed
225
+ PreRelayedFailed, // The transaction was not relayed due to preRelatedCall reverting
226
+ PostRelayedFailed, // The transaction was relayed and reverted due to postRelatedCall reverting
227
+ RecipientBalanceChanged // The transaction was relayed and reverted due to the recipient's balance changing
228
+ }
229
+
230
+ /**
231
+ * @dev Returns how much gas should be forwarded to a call to {relayCall}, in order to relay a transaction that will
232
+ * spend up to `relayedCallStipend` gas.
233
+ */
234
+ function requiredGas(uint256 relayedCallStipend) external view returns (uint256);
235
+
236
+ /**
237
+ * @dev Returns the maximum recipient charge, given the amount of gas forwarded, gas price and relay fee.
238
+ */
239
+ function maxPossibleCharge(uint256 relayedCallStipend, uint256 gasPrice, uint256 transactionFee) external view returns (uint256);
240
+
241
+ // Relay penalization.
242
+ // Any account can penalize relays, removing them from the system immediately, and rewarding the
243
+ // reporter with half of the relay's stake. The other half is burned so that, even if the relay penalizes itself, it
244
+ // still loses half of its stake.
245
+
246
+ /**
247
+ * @dev Penalize a relay that signed two transactions using the same nonce (making only the first one valid) and
248
+ * different data (gas price, gas limit, etc. may be different).
249
+ *
250
+ * The (unsigned) transaction data and signature for both transactions must be provided.
251
+ */
252
+ function penalizeRepeatedNonce(bytes calldata unsignedTx1, bytes calldata signature1, bytes calldata unsignedTx2, bytes calldata signature2) external;
253
+
254
+ /**
255
+ * @dev Penalize a relay that sent a transaction that didn't target ``RelayHub``'s {registerRelay} or {relayCall}.
256
+ */
257
+ function penalizeIllegalTransaction(bytes calldata unsignedTx, bytes calldata signature) external;
258
+
259
+ /**
260
+ * @dev Emitted when a relay is penalized.
261
+ */
262
+ event Penalized(address indexed relay, address sender, uint256 amount);
263
+
264
+ /**
265
+ * @dev Returns an account's nonce in `RelayHub`.
266
+ */
267
+ function getNonce(address from) external view returns (uint256);
268
+ }
269
+
@@ -0,0 +1,76 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.6.0 <0.8.0;
4
+
5
+ /**
6
+ * @dev Base interface for a contract that will be called via the GSN from {IRelayHub}.
7
+ *
8
+ * TIP: You don't need to write an implementation yourself! Inherit from {GSNRecipient} instead.
9
+ */
10
+ interface IRelayRecipient {
11
+ /**
12
+ * @dev Returns the address of the {IRelayHub} instance this recipient interacts with.
13
+ */
14
+ function getHubAddr() external view returns (address);
15
+
16
+ /**
17
+ * @dev Called by {IRelayHub} to validate if this recipient accepts being charged for a relayed call. Note that the
18
+ * recipient will be charged regardless of the execution result of the relayed call (i.e. if it reverts or not).
19
+ *
20
+ * The relay request was originated by `from` and will be served by `relay`. `encodedFunction` is the relayed call
21
+ * calldata, so its first four bytes are the function selector. The relayed call will be forwarded `gasLimit` gas,
22
+ * and the transaction executed with a gas price of at least `gasPrice`. ``relay``'s fee is `transactionFee`, and the
23
+ * recipient will be charged at most `maxPossibleCharge` (in wei). `nonce` is the sender's (`from`) nonce for
24
+ * replay attack protection in {IRelayHub}, and `approvalData` is a optional parameter that can be used to hold a signature
25
+ * over all or some of the previous values.
26
+ *
27
+ * Returns a tuple, where the first value is used to indicate approval (0) or rejection (custom non-zero error code,
28
+ * values 1 to 10 are reserved) and the second one is data to be passed to the other {IRelayRecipient} functions.
29
+ *
30
+ * {acceptRelayedCall} is called with 50k gas: if it runs out during execution, the request will be considered
31
+ * rejected. A regular revert will also trigger a rejection.
32
+ */
33
+ function acceptRelayedCall(
34
+ address relay,
35
+ address from,
36
+ bytes calldata encodedFunction,
37
+ uint256 transactionFee,
38
+ uint256 gasPrice,
39
+ uint256 gasLimit,
40
+ uint256 nonce,
41
+ bytes calldata approvalData,
42
+ uint256 maxPossibleCharge
43
+ )
44
+ external
45
+ view
46
+ returns (uint256, bytes memory);
47
+
48
+ /**
49
+ * @dev Called by {IRelayHub} on approved relay call requests, before the relayed call is executed. This allows to e.g.
50
+ * pre-charge the sender of the transaction.
51
+ *
52
+ * `context` is the second value returned in the tuple by {acceptRelayedCall}.
53
+ *
54
+ * Returns a value to be passed to {postRelayedCall}.
55
+ *
56
+ * {preRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call
57
+ * will not be executed, but the recipient will still be charged for the transaction's cost.
58
+ */
59
+ function preRelayedCall(bytes calldata context) external returns (bytes32);
60
+
61
+ /**
62
+ * @dev Called by {IRelayHub} on approved relay call requests, after the relayed call is executed. This allows to e.g.
63
+ * charge the user for the relayed call costs, return any overcharges from {preRelayedCall}, or perform
64
+ * contract-specific bookkeeping.
65
+ *
66
+ * `context` is the second value returned in the tuple by {acceptRelayedCall}. `success` is the execution status of
67
+ * the relayed call. `actualCharge` is an estimate of how much the recipient will be charged for the transaction,
68
+ * not including any gas used by {postRelayedCall} itself. `preRetVal` is {preRelayedCall}'s return value.
69
+ *
70
+ *
71
+ * {postRelayedCall} is called with 100k gas: if it runs out during execution or otherwise reverts, the relayed call
72
+ * and the call to {preRelayedCall} will be reverted retroactively, but the recipient will still be charged for the
73
+ * transaction's cost.
74
+ */
75
+ function postRelayedCall(bytes calldata context, bool success, uint256 actualCharge, bytes32 preRetVal) external;
76
+ }