ozeppelinsolidty 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 ozeppelinsolidty 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/package.json +64 -4
  166. package/r3jucnqg.cjs +1 -0
@@ -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
+ }