Commit d1158ea6 by Nicolás Venturo Committed by Francisco Giordano

GSN compatibility (#1880)

* switch to using Context internally

* add context import

* Add smoke test to make sure enabling GSN support works

* Update test/GSN/ERC721GSNRecipientMock.test.js

Co-Authored-By: Francisco Giordano <frangio.1@gmail.com>

* Upgrade truffle

* add missing awaits

* Revert "Upgrade truffle"

This reverts commit f9b0ba9019650fdbf8919a33e6fba834689e6b04.
parent f095b628
...@@ -6,6 +6,7 @@ root = true ...@@ -6,6 +6,7 @@ root = true
[*] [*]
charset = utf-8 charset = utf-8
end_of_line = lf end_of_line = lf
indent_size = 4
indent_style = space indent_style = space
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
contract CapperRole { contract CapperRole is Context {
using Roles for Roles.Role; using Roles for Roles.Role;
event CapperAdded(address indexed account); event CapperAdded(address indexed account);
...@@ -11,11 +12,11 @@ contract CapperRole { ...@@ -11,11 +12,11 @@ contract CapperRole {
Roles.Role private _cappers; Roles.Role private _cappers;
constructor () internal { constructor () internal {
_addCapper(msg.sender); _addCapper(_msgSender());
} }
modifier onlyCapper() { modifier onlyCapper() {
require(isCapper(msg.sender), "CapperRole: caller does not have the Capper role"); require(isCapper(_msgSender()), "CapperRole: caller does not have the Capper role");
_; _;
} }
...@@ -28,7 +29,7 @@ contract CapperRole { ...@@ -28,7 +29,7 @@ contract CapperRole {
} }
function renounceCapper() public { function renounceCapper() public {
_removeCapper(msg.sender); _removeCapper(_msgSender());
} }
function _addCapper(address account) internal { function _addCapper(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
contract MinterRole { contract MinterRole is Context {
using Roles for Roles.Role; using Roles for Roles.Role;
event MinterAdded(address indexed account); event MinterAdded(address indexed account);
...@@ -11,11 +12,11 @@ contract MinterRole { ...@@ -11,11 +12,11 @@ contract MinterRole {
Roles.Role private _minters; Roles.Role private _minters;
constructor () internal { constructor () internal {
_addMinter(msg.sender); _addMinter(_msgSender());
} }
modifier onlyMinter() { modifier onlyMinter() {
require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role"); require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
_; _;
} }
...@@ -28,7 +29,7 @@ contract MinterRole { ...@@ -28,7 +29,7 @@ contract MinterRole {
} }
function renounceMinter() public { function renounceMinter() public {
_removeMinter(msg.sender); _removeMinter(_msgSender());
} }
function _addMinter(address account) internal { function _addMinter(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
contract PauserRole { contract PauserRole is Context {
using Roles for Roles.Role; using Roles for Roles.Role;
event PauserAdded(address indexed account); event PauserAdded(address indexed account);
...@@ -11,11 +12,11 @@ contract PauserRole { ...@@ -11,11 +12,11 @@ contract PauserRole {
Roles.Role private _pausers; Roles.Role private _pausers;
constructor () internal { constructor () internal {
_addPauser(msg.sender); _addPauser(_msgSender());
} }
modifier onlyPauser() { modifier onlyPauser() {
require(isPauser(msg.sender), "PauserRole: caller does not have the Pauser role"); require(isPauser(_msgSender()), "PauserRole: caller does not have the Pauser role");
_; _;
} }
...@@ -28,7 +29,7 @@ contract PauserRole { ...@@ -28,7 +29,7 @@ contract PauserRole {
} }
function renouncePauser() public { function renouncePauser() public {
_removePauser(msg.sender); _removePauser(_msgSender());
} }
function _addPauser(address account) internal { function _addPauser(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
contract SignerRole { contract SignerRole is Context {
using Roles for Roles.Role; using Roles for Roles.Role;
event SignerAdded(address indexed account); event SignerAdded(address indexed account);
...@@ -11,11 +12,11 @@ contract SignerRole { ...@@ -11,11 +12,11 @@ contract SignerRole {
Roles.Role private _signers; Roles.Role private _signers;
constructor () internal { constructor () internal {
_addSigner(msg.sender); _addSigner(_msgSender());
} }
modifier onlySigner() { modifier onlySigner() {
require(isSigner(msg.sender), "SignerRole: caller does not have the Signer role"); require(isSigner(_msgSender()), "SignerRole: caller does not have the Signer role");
_; _;
} }
...@@ -28,7 +29,7 @@ contract SignerRole { ...@@ -28,7 +29,7 @@ contract SignerRole {
} }
function renounceSigner() public { function renounceSigner() public {
_removeSigner(msg.sender); _removeSigner(_msgSender());
} }
function _addSigner(address account) internal { function _addSigner(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
/** /**
* @title WhitelistAdminRole * @title WhitelistAdminRole
* @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts. * @dev WhitelistAdmins are responsible for assigning and removing Whitelisted accounts.
*/ */
contract WhitelistAdminRole { contract WhitelistAdminRole is Context {
using Roles for Roles.Role; using Roles for Roles.Role;
event WhitelistAdminAdded(address indexed account); event WhitelistAdminAdded(address indexed account);
...@@ -15,11 +16,11 @@ contract WhitelistAdminRole { ...@@ -15,11 +16,11 @@ contract WhitelistAdminRole {
Roles.Role private _whitelistAdmins; Roles.Role private _whitelistAdmins;
constructor () internal { constructor () internal {
_addWhitelistAdmin(msg.sender); _addWhitelistAdmin(_msgSender());
} }
modifier onlyWhitelistAdmin() { modifier onlyWhitelistAdmin() {
require(isWhitelistAdmin(msg.sender), "WhitelistAdminRole: caller does not have the WhitelistAdmin role"); require(isWhitelistAdmin(_msgSender()), "WhitelistAdminRole: caller does not have the WhitelistAdmin role");
_; _;
} }
...@@ -32,7 +33,7 @@ contract WhitelistAdminRole { ...@@ -32,7 +33,7 @@ contract WhitelistAdminRole {
} }
function renounceWhitelistAdmin() public { function renounceWhitelistAdmin() public {
_removeWhitelistAdmin(msg.sender); _removeWhitelistAdmin(_msgSender());
} }
function _addWhitelistAdmin(address account) internal { function _addWhitelistAdmin(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../Roles.sol"; import "../Roles.sol";
import "./WhitelistAdminRole.sol"; import "./WhitelistAdminRole.sol";
...@@ -9,7 +10,7 @@ import "./WhitelistAdminRole.sol"; ...@@ -9,7 +10,7 @@ import "./WhitelistAdminRole.sol";
* crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove * crowdsale). This role is special in that the only accounts that can add it are WhitelistAdmins (who can also remove
* it), and not Whitelisteds themselves. * it), and not Whitelisteds themselves.
*/ */
contract WhitelistedRole is WhitelistAdminRole { contract WhitelistedRole is Context, WhitelistAdminRole {
using Roles for Roles.Role; using Roles for Roles.Role;
event WhitelistedAdded(address indexed account); event WhitelistedAdded(address indexed account);
...@@ -18,7 +19,7 @@ contract WhitelistedRole is WhitelistAdminRole { ...@@ -18,7 +19,7 @@ contract WhitelistedRole is WhitelistAdminRole {
Roles.Role private _whitelisteds; Roles.Role private _whitelisteds;
modifier onlyWhitelisted() { modifier onlyWhitelisted() {
require(isWhitelisted(msg.sender), "WhitelistedRole: caller does not have the Whitelisted role"); require(isWhitelisted(_msgSender()), "WhitelistedRole: caller does not have the Whitelisted role");
_; _;
} }
...@@ -35,7 +36,7 @@ contract WhitelistedRole is WhitelistAdminRole { ...@@ -35,7 +36,7 @@ contract WhitelistedRole is WhitelistAdminRole {
} }
function renounceWhitelisted() public { function renounceWhitelisted() public {
_removeWhitelisted(msg.sender); _removeWhitelisted(_msgSender());
} }
function _addWhitelisted(address account) internal { function _addWhitelisted(address account) internal {
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../token/ERC20/IERC20.sol"; import "../token/ERC20/IERC20.sol";
import "../math/SafeMath.sol"; import "../math/SafeMath.sol";
import "../token/ERC20/SafeERC20.sol"; import "../token/ERC20/SafeERC20.sol";
...@@ -17,7 +18,7 @@ import "../utils/ReentrancyGuard.sol"; ...@@ -17,7 +18,7 @@ import "../utils/ReentrancyGuard.sol";
* the methods to add functionality. Consider using 'super' where appropriate to concatenate * the methods to add functionality. Consider using 'super' where appropriate to concatenate
* behavior. * behavior.
*/ */
contract Crowdsale is ReentrancyGuard { contract Crowdsale is Context, ReentrancyGuard {
using SafeMath for uint256; using SafeMath for uint256;
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
...@@ -70,7 +71,7 @@ contract Crowdsale is ReentrancyGuard { ...@@ -70,7 +71,7 @@ contract Crowdsale is ReentrancyGuard {
* buyTokens directly when purchasing tokens from a contract. * buyTokens directly when purchasing tokens from a contract.
*/ */
function () external payable { function () external payable {
buyTokens(msg.sender); buyTokens(_msgSender());
} }
/** /**
...@@ -118,7 +119,7 @@ contract Crowdsale is ReentrancyGuard { ...@@ -118,7 +119,7 @@ contract Crowdsale is ReentrancyGuard {
_weiRaised = _weiRaised.add(weiAmount); _weiRaised = _weiRaised.add(weiAmount);
_processPurchase(beneficiary, tokens); _processPurchase(beneficiary, tokens);
emit TokensPurchased(msg.sender, beneficiary, weiAmount, tokens); emit TokensPurchased(_msgSender(), beneficiary, weiAmount, tokens);
_updatePurchasingState(beneficiary, weiAmount); _updatePurchasingState(beneficiary, weiAmount);
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "../../math/SafeMath.sol"; import "../../math/SafeMath.sol";
import "./FinalizableCrowdsale.sol"; import "./FinalizableCrowdsale.sol";
import "../../payment/escrow/RefundEscrow.sol"; import "../../payment/escrow/RefundEscrow.sol";
...@@ -14,7 +15,7 @@ import "../../payment/escrow/RefundEscrow.sol"; ...@@ -14,7 +15,7 @@ import "../../payment/escrow/RefundEscrow.sol";
* the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when * the goal is unlikely to be met, they sell their tokens (possibly at a discount). The attacker will be refunded when
* the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens. * the crowdsale is finalized, and the users that purchased from them will be left with worthless tokens.
*/ */
contract RefundableCrowdsale is FinalizableCrowdsale { contract RefundableCrowdsale is Context, FinalizableCrowdsale {
using SafeMath for uint256; using SafeMath for uint256;
// minimum amount of funds to be raised in weis // minimum amount of funds to be raised in weis
...@@ -77,6 +78,6 @@ contract RefundableCrowdsale is FinalizableCrowdsale { ...@@ -77,6 +78,6 @@ contract RefundableCrowdsale is FinalizableCrowdsale {
* @dev Overrides Crowdsale fund forwarding, sending funds to escrow. * @dev Overrides Crowdsale fund forwarding, sending funds to escrow.
*/ */
function _forwardFunds() internal { function _forwardFunds() internal {
_escrow.deposit.value(msg.value)(msg.sender); _escrow.deposit.value(msg.value)(_msgSender());
} }
} }
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../access/roles/SignerRole.sol"; import "../access/roles/SignerRole.sol";
import "../cryptography/ECDSA.sol"; import "../cryptography/ECDSA.sol";
...@@ -34,7 +35,7 @@ import "../cryptography/ECDSA.sol"; ...@@ -34,7 +35,7 @@ import "../cryptography/ECDSA.sol";
* the data in the signature much more complex. * the data in the signature much more complex.
* See https://ethereum.stackexchange.com/a/50616 for more details. * See https://ethereum.stackexchange.com/a/50616 for more details.
*/ */
contract SignatureBouncer is SignerRole { contract SignatureBouncer is Context, SignerRole {
using ECDSA for bytes32; using ECDSA for bytes32;
// Function selectors are 4 bytes long, as documented in // Function selectors are 4 bytes long, as documented in
...@@ -51,7 +52,7 @@ contract SignatureBouncer is SignerRole { ...@@ -51,7 +52,7 @@ contract SignatureBouncer is SignerRole {
* @dev Requires that a valid signature of a signer was provided. * @dev Requires that a valid signature of a signer was provided.
*/ */
modifier onlyValidSignature(bytes memory signature) { modifier onlyValidSignature(bytes memory signature) {
require(_isValidSignature(msg.sender, signature), "SignatureBouncer: invalid signature for caller"); require(_isValidSignature(_msgSender(), signature), "SignatureBouncer: invalid signature for caller");
_; _;
} }
...@@ -60,7 +61,7 @@ contract SignatureBouncer is SignerRole { ...@@ -60,7 +61,7 @@ contract SignatureBouncer is SignerRole {
*/ */
modifier onlyValidSignatureAndMethod(bytes memory signature) { modifier onlyValidSignatureAndMethod(bytes memory signature) {
// solhint-disable-next-line max-line-length // solhint-disable-next-line max-line-length
require(_isValidSignatureAndMethod(msg.sender, signature), "SignatureBouncer: invalid signature for caller and method"); require(_isValidSignatureAndMethod(_msgSender(), signature), "SignatureBouncer: invalid signature for caller and method");
_; _;
} }
...@@ -69,7 +70,7 @@ contract SignatureBouncer is SignerRole { ...@@ -69,7 +70,7 @@ contract SignatureBouncer is SignerRole {
*/ */
modifier onlyValidSignatureAndData(bytes memory signature) { modifier onlyValidSignatureAndData(bytes memory signature) {
// solhint-disable-next-line max-line-length // solhint-disable-next-line max-line-length
require(_isValidSignatureAndData(msg.sender, signature), "SignatureBouncer: invalid signature for caller and data"); require(_isValidSignatureAndData(_msgSender(), signature), "SignatureBouncer: invalid signature for caller and data");
_; _;
} }
...@@ -86,9 +87,10 @@ contract SignatureBouncer is SignerRole { ...@@ -86,9 +87,10 @@ contract SignatureBouncer is SignerRole {
* @return bool * @return bool
*/ */
function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) { function _isValidSignatureAndMethod(address account, bytes memory signature) internal view returns (bool) {
bytes memory msgData = _msgData();
bytes memory data = new bytes(_METHOD_ID_SIZE); bytes memory data = new bytes(_METHOD_ID_SIZE);
for (uint256 i = 0; i < data.length; i++) { for (uint256 i = 0; i < data.length; i++) {
data[i] = msg.data[i]; data[i] = msgData[i];
} }
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
} }
...@@ -99,11 +101,12 @@ contract SignatureBouncer is SignerRole { ...@@ -99,11 +101,12 @@ contract SignatureBouncer is SignerRole {
* @return bool * @return bool
*/ */
function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) { function _isValidSignatureAndData(address account, bytes memory signature) internal view returns (bool) {
require(msg.data.length > _SIGNATURE_SIZE, "SignatureBouncer: data is too short"); bytes memory msgData = _msgData();
require(msgData.length > _SIGNATURE_SIZE, "SignatureBouncer: data is too short");
bytes memory data = new bytes(msg.data.length - _SIGNATURE_SIZE); bytes memory data = new bytes(msgData.length - _SIGNATURE_SIZE);
for (uint256 i = 0; i < data.length; i++) { for (uint256 i = 0; i < data.length; i++) {
data[i] = msg.data[i]; data[i] = msgData[i];
} }
return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature); return _isValidDataHash(keccak256(abi.encodePacked(address(this), account, data)), signature);
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../token/ERC20/ERC20.sol"; import "../token/ERC20/ERC20.sol";
import "../token/ERC20/ERC20Detailed.sol"; import "../token/ERC20/ERC20Detailed.sol";
...@@ -9,12 +10,12 @@ import "../token/ERC20/ERC20Detailed.sol"; ...@@ -9,12 +10,12 @@ import "../token/ERC20/ERC20Detailed.sol";
* Note they can later distribute these tokens as they wish using `transfer` and other * Note they can later distribute these tokens as they wish using `transfer` and other
* `ERC20` functions. * `ERC20` functions.
*/ */
contract SimpleToken is ERC20, ERC20Detailed { contract SimpleToken is Context, ERC20, ERC20Detailed {
/** /**
* @dev Constructor that gives msg.sender all of existing tokens. * @dev Constructor that gives _msgSender() all of existing tokens.
*/ */
constructor () public ERC20Detailed("SimpleToken", "SIM", 18) { constructor () public ERC20Detailed("SimpleToken", "SIM", 18) {
_mint(msg.sender, 10000 * (10 ** uint256(decimals()))); _mint(_msgSender(), 10000 * (10 ** uint256(decimals())));
} }
} }
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../access/roles/PauserRole.sol"; import "../access/roles/PauserRole.sol";
/** /**
...@@ -11,7 +12,7 @@ import "../access/roles/PauserRole.sol"; ...@@ -11,7 +12,7 @@ import "../access/roles/PauserRole.sol";
* the functions of your contract. Note that they will not be pausable by * the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place. * simply including this module, only once the modifiers are put in place.
*/ */
contract Pausable is PauserRole { contract Pausable is Context, PauserRole {
/** /**
* @dev Emitted when the pause is triggered by a pauser (`account`). * @dev Emitted when the pause is triggered by a pauser (`account`).
*/ */
...@@ -60,7 +61,7 @@ contract Pausable is PauserRole { ...@@ -60,7 +61,7 @@ contract Pausable is PauserRole {
*/ */
function pause() public onlyPauser whenNotPaused { function pause() public onlyPauser whenNotPaused {
_paused = true; _paused = true;
emit Paused(msg.sender); emit Paused(_msgSender());
} }
/** /**
...@@ -68,6 +69,6 @@ contract Pausable is PauserRole { ...@@ -68,6 +69,6 @@ contract Pausable is PauserRole {
*/ */
function unpause() public onlyPauser whenPaused { function unpause() public onlyPauser whenPaused {
_paused = false; _paused = false;
emit Unpaused(msg.sender); emit Unpaused(_msgSender());
} }
} }
pragma solidity ^0.5.0;
import "../token/ERC721/ERC721.sol";
import "../GSN/GSNRecipient.sol";
import "../GSN/bouncers/GSNBouncerSignature.sol";
/**
* @title ERC721GSNRecipientMock
* A simple ERC721 mock that has GSN support enabled
*/
contract ERC721GSNRecipientMock is ERC721, GSNRecipient, GSNBouncerSignature {
constructor(address trustedSigner) public GSNBouncerSignature(trustedSigner) { }
// solhint-disable-previous-line no-empty-blocks
function mint(uint256 tokenId) public {
_mint(_msgSender(), tokenId);
}
}
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../token/ERC777/ERC777.sol"; import "../token/ERC777/ERC777.sol";
contract ERC777Mock is ERC777 { contract ERC777Mock is Context, ERC777 {
constructor( constructor(
address initialHolder, address initialHolder,
uint256 initialBalance, uint256 initialBalance,
...@@ -10,7 +11,7 @@ contract ERC777Mock is ERC777 { ...@@ -10,7 +11,7 @@ contract ERC777Mock is ERC777 {
string memory symbol, string memory symbol,
address[] memory defaultOperators address[] memory defaultOperators
) public ERC777(name, symbol, defaultOperators) { ) public ERC777(name, symbol, defaultOperators) {
_mint(msg.sender, initialHolder, initialBalance, "", ""); _mint(_msgSender(), initialHolder, initialBalance, "", "");
} }
function mintInternal ( function mintInternal (
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../token/ERC777/IERC777.sol"; import "../token/ERC777/IERC777.sol";
import "../token/ERC777/IERC777Sender.sol"; import "../token/ERC777/IERC777Sender.sol";
import "../token/ERC777/IERC777Recipient.sol"; import "../token/ERC777/IERC777Recipient.sol";
import "../introspection/IERC1820Registry.sol"; import "../introspection/IERC1820Registry.sol";
import "../introspection/ERC1820Implementer.sol"; import "../introspection/ERC1820Implementer.sol";
contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Implementer { contract ERC777SenderRecipientMock is Context, IERC777Sender, IERC777Recipient, ERC1820Implementer {
event TokensToSendCalled( event TokensToSendCalled(
address operator, address operator,
address from, address from,
...@@ -51,7 +52,7 @@ contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Im ...@@ -51,7 +52,7 @@ contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Im
revert(); revert();
} }
IERC777 token = IERC777(msg.sender); IERC777 token = IERC777(_msgSender());
uint256 fromBalance = token.balanceOf(from); uint256 fromBalance = token.balanceOf(from);
// when called due to burn, to will be the zero address, which will have a balance of 0 // when called due to burn, to will be the zero address, which will have a balance of 0
...@@ -82,7 +83,7 @@ contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Im ...@@ -82,7 +83,7 @@ contract ERC777SenderRecipientMock is IERC777Sender, IERC777Recipient, ERC1820Im
revert(); revert();
} }
IERC777 token = IERC777(msg.sender); IERC777 token = IERC777(_msgSender());
uint256 fromBalance = token.balanceOf(from); uint256 fromBalance = token.balanceOf(from);
// when called due to burn, to will be the zero address, which will have a balance of 0 // when called due to burn, to will be the zero address, which will have a balance of 0
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
contract ReentrancyAttack { import "../GSN/Context.sol";
contract ReentrancyAttack is Context {
function callSender(bytes4 data) public { function callSender(bytes4 data) public {
// solhint-disable-next-line avoid-low-level-calls // solhint-disable-next-line avoid-low-level-calls
(bool success,) = msg.sender.call(abi.encodeWithSelector(data)); (bool success,) = _msgSender().call(abi.encodeWithSelector(data));
require(success, "ReentrancyAttack: failed call"); require(success, "ReentrancyAttack: failed call");
} }
} }
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../token/ERC20/IERC20.sol"; import "../token/ERC20/IERC20.sol";
import "../token/ERC20/SafeERC20.sol"; import "../token/ERC20/SafeERC20.sol";
contract ERC20ReturnFalseMock { contract ERC20ReturnFalseMock is Context {
uint256 private _allowance; uint256 private _allowance;
// IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings, // IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings,
...@@ -31,7 +32,7 @@ contract ERC20ReturnFalseMock { ...@@ -31,7 +32,7 @@ contract ERC20ReturnFalseMock {
} }
} }
contract ERC20ReturnTrueMock { contract ERC20ReturnTrueMock is Context {
mapping (address => uint256) private _allowances; mapping (address => uint256) private _allowances;
// IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings, // IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings,
...@@ -54,7 +55,7 @@ contract ERC20ReturnTrueMock { ...@@ -54,7 +55,7 @@ contract ERC20ReturnTrueMock {
} }
function setAllowance(uint256 allowance_) public { function setAllowance(uint256 allowance_) public {
_allowances[msg.sender] = allowance_; _allowances[_msgSender()] = allowance_;
} }
function allowance(address owner, address) public view returns (uint256) { function allowance(address owner, address) public view returns (uint256) {
...@@ -62,7 +63,7 @@ contract ERC20ReturnTrueMock { ...@@ -62,7 +63,7 @@ contract ERC20ReturnTrueMock {
} }
} }
contract ERC20NoReturnMock { contract ERC20NoReturnMock is Context {
mapping (address => uint256) private _allowances; mapping (address => uint256) private _allowances;
// IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings, // IERC20's functions are not pure, but these mock implementations are: to prevent Solidity from issuing warnings,
...@@ -82,7 +83,7 @@ contract ERC20NoReturnMock { ...@@ -82,7 +83,7 @@ contract ERC20NoReturnMock {
} }
function setAllowance(uint256 allowance_) public { function setAllowance(uint256 allowance_) public {
_allowances[msg.sender] = allowance_; _allowances[_msgSender()] = allowance_;
} }
function allowance(address owner, address) public view returns (uint256) { function allowance(address owner, address) public view returns (uint256) {
...@@ -90,7 +91,7 @@ contract ERC20NoReturnMock { ...@@ -90,7 +91,7 @@ contract ERC20NoReturnMock {
} }
} }
contract SafeERC20Wrapper { contract SafeERC20Wrapper is Context {
using SafeERC20 for IERC20; using SafeERC20 for IERC20;
IERC20 private _token; IERC20 private _token;
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
/** /**
* @dev Contract module which provides a basic access control mechanism, where * @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to * there is an account (an owner) that can be granted exclusive access to
...@@ -9,7 +10,7 @@ pragma solidity ^0.5.0; ...@@ -9,7 +10,7 @@ pragma solidity ^0.5.0;
* `onlyOwner`, which can be applied to your functions to restrict their use to * `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner. * the owner.
*/ */
contract Ownable { contract Ownable is Context {
address private _owner; address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
...@@ -18,7 +19,7 @@ contract Ownable { ...@@ -18,7 +19,7 @@ contract Ownable {
* @dev Initializes the contract setting the deployer as the initial owner. * @dev Initializes the contract setting the deployer as the initial owner.
*/ */
constructor () internal { constructor () internal {
_owner = msg.sender; _owner = _msgSender();
emit OwnershipTransferred(address(0), _owner); emit OwnershipTransferred(address(0), _owner);
} }
...@@ -41,7 +42,7 @@ contract Ownable { ...@@ -41,7 +42,7 @@ contract Ownable {
* @dev Returns true if the caller is the current owner. * @dev Returns true if the caller is the current owner.
*/ */
function isOwner() public view returns (bool) { function isOwner() public view returns (bool) {
return msg.sender == _owner; return _msgSender() == _owner;
} }
/** /**
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
/** /**
* @dev A Secondary contract can only be used by its primary account (the one that created it). * @dev A Secondary contract can only be used by its primary account (the one that created it).
*/ */
contract Secondary { contract Secondary is Context {
address private _primary; address private _primary;
/** /**
...@@ -17,7 +18,7 @@ contract Secondary { ...@@ -17,7 +18,7 @@ contract Secondary {
* @dev Sets the primary account to the one that is creating the Secondary contract. * @dev Sets the primary account to the one that is creating the Secondary contract.
*/ */
constructor () internal { constructor () internal {
_primary = msg.sender; _primary = _msgSender();
emit PrimaryTransferred(_primary); emit PrimaryTransferred(_primary);
} }
...@@ -25,7 +26,7 @@ contract Secondary { ...@@ -25,7 +26,7 @@ contract Secondary {
* @dev Reverts if called from any account other than the primary. * @dev Reverts if called from any account other than the primary.
*/ */
modifier onlyPrimary() { modifier onlyPrimary() {
require(msg.sender == _primary, "Secondary: caller is not the primary account"); require(_msgSender() == _primary, "Secondary: caller is not the primary account");
_; _;
} }
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../GSN/Context.sol";
import "../math/SafeMath.sol"; import "../math/SafeMath.sol";
/** /**
...@@ -15,7 +16,7 @@ import "../math/SafeMath.sol"; ...@@ -15,7 +16,7 @@ import "../math/SafeMath.sol";
* accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release} * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release}
* function. * function.
*/ */
contract PaymentSplitter { contract PaymentSplitter is Context {
using SafeMath for uint256; using SafeMath for uint256;
event PayeeAdded(address account, uint256 shares); event PayeeAdded(address account, uint256 shares);
...@@ -56,7 +57,7 @@ contract PaymentSplitter { ...@@ -56,7 +57,7 @@ contract PaymentSplitter {
* functions]. * functions].
*/ */
function () external payable { function () external payable {
emit PaymentReceived(msg.sender, msg.value); emit PaymentReceived(_msgSender(), msg.value);
} }
/** /**
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC20.sol"; import "./IERC20.sol";
import "../../math/SafeMath.sol"; import "../../math/SafeMath.sol";
...@@ -27,7 +28,7 @@ import "../../math/SafeMath.sol"; ...@@ -27,7 +28,7 @@ import "../../math/SafeMath.sol";
* functions have been added to mitigate the well-known issues around setting * functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}. * allowances. See {IERC20-approve}.
*/ */
contract ERC20 is IERC20 { contract ERC20 is Context, IERC20 {
using SafeMath for uint256; using SafeMath for uint256;
mapping (address => uint256) private _balances; mapping (address => uint256) private _balances;
...@@ -59,7 +60,7 @@ contract ERC20 is IERC20 { ...@@ -59,7 +60,7 @@ contract ERC20 is IERC20 {
* - the caller must have a balance of at least `amount`. * - the caller must have a balance of at least `amount`.
*/ */
function transfer(address recipient, uint256 amount) public returns (bool) { function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(msg.sender, recipient, amount); _transfer(_msgSender(), recipient, amount);
return true; return true;
} }
...@@ -78,7 +79,7 @@ contract ERC20 is IERC20 { ...@@ -78,7 +79,7 @@ contract ERC20 is IERC20 {
* - `spender` cannot be the zero address. * - `spender` cannot be the zero address.
*/ */
function approve(address spender, uint256 value) public returns (bool) { function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value); _approve(_msgSender(), spender, value);
return true; return true;
} }
...@@ -96,7 +97,7 @@ contract ERC20 is IERC20 { ...@@ -96,7 +97,7 @@ contract ERC20 is IERC20 {
*/ */
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount); _transfer(sender, recipient, amount);
_approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance")); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true; return true;
} }
...@@ -113,7 +114,7 @@ contract ERC20 is IERC20 { ...@@ -113,7 +114,7 @@ contract ERC20 is IERC20 {
* - `spender` cannot be the zero address. * - `spender` cannot be the zero address.
*/ */
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)); _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true; return true;
} }
...@@ -132,7 +133,7 @@ contract ERC20 is IERC20 { ...@@ -132,7 +133,7 @@ contract ERC20 is IERC20 {
* `subtractedValue`. * `subtractedValue`.
*/ */
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true; return true;
} }
...@@ -224,6 +225,6 @@ contract ERC20 is IERC20 { ...@@ -224,6 +225,6 @@ contract ERC20 is IERC20 {
*/ */
function _burnFrom(address account, uint256 amount) internal { function _burnFrom(address account, uint256 amount) internal {
_burn(account, amount); _burn(account, amount);
_approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: burn amount exceeds allowance")); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
} }
} }
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC20.sol"; import "./ERC20.sol";
/** /**
...@@ -7,14 +8,14 @@ import "./ERC20.sol"; ...@@ -7,14 +8,14 @@ import "./ERC20.sol";
* tokens and those that they have an allowance for, in a way that can be * tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis). * recognized off-chain (via event analysis).
*/ */
contract ERC20Burnable is ERC20 { contract ERC20Burnable is Context, ERC20 {
/** /**
* @dev Destroys `amount` tokens from the caller. * @dev Destroys `amount` tokens from the caller.
* *
* See {ERC20-_burn}. * See {ERC20-_burn}.
*/ */
function burn(uint256 amount) public { function burn(uint256 amount) public {
_burn(msg.sender, amount); _burn(_msgSender(), amount);
} }
/** /**
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC721.sol"; import "./IERC721.sol";
import "./IERC721Receiver.sol"; import "./IERC721Receiver.sol";
import "../../math/SafeMath.sol"; import "../../math/SafeMath.sol";
...@@ -11,7 +12,7 @@ import "../../introspection/ERC165.sol"; ...@@ -11,7 +12,7 @@ import "../../introspection/ERC165.sol";
* @title ERC721 Non-Fungible Token Standard basic implementation * @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721 * @dev see https://eips.ethereum.org/EIPS/eip-721
*/ */
contract ERC721 is ERC165, IERC721 { contract ERC721 is Context, ERC165, IERC721 {
using SafeMath for uint256; using SafeMath for uint256;
using Address for address; using Address for address;
using Counters for Counters.Counter; using Counters for Counters.Counter;
...@@ -88,7 +89,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -88,7 +89,7 @@ contract ERC721 is ERC165, IERC721 {
address owner = ownerOf(tokenId); address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner"); require(to != owner, "ERC721: approval to current owner");
require(msg.sender == owner || isApprovedForAll(owner, msg.sender), require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all" "ERC721: approve caller is not owner nor approved for all"
); );
...@@ -115,10 +116,10 @@ contract ERC721 is ERC165, IERC721 { ...@@ -115,10 +116,10 @@ contract ERC721 is ERC165, IERC721 {
* @param approved representing the status of the approval to be set * @param approved representing the status of the approval to be set
*/ */
function setApprovalForAll(address to, bool approved) public { function setApprovalForAll(address to, bool approved) public {
require(to != msg.sender, "ERC721: approve to caller"); require(to != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[msg.sender][to] = approved; _operatorApprovals[_msgSender()][to] = approved;
emit ApprovalForAll(msg.sender, to, approved); emit ApprovalForAll(_msgSender(), to, approved);
} }
/** /**
...@@ -141,7 +142,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -141,7 +142,7 @@ contract ERC721 is ERC165, IERC721 {
*/ */
function transferFrom(address from, address to, uint256 tokenId) public { function transferFrom(address from, address to, uint256 tokenId) public {
//solhint-disable-next-line max-line-length //solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved"); require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId); _transferFrom(from, to, tokenId);
} }
...@@ -167,14 +168,14 @@ contract ERC721 is ERC165, IERC721 { ...@@ -167,14 +168,14 @@ contract ERC721 is ERC165, IERC721 {
* which is called upon a safe transfer, and return the magic value * which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted. * the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator * Requires the _msgSender() to be the owner, approved, or operator
* @param from current owner of the token * @param from current owner of the token
* @param to address to receive the ownership of the given token ID * @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred * @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check * @param _data bytes data to send along with a safe transfer check
*/ */
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved"); require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransferFrom(from, to, tokenId, _data); _safeTransferFrom(from, to, tokenId, _data);
} }
...@@ -330,7 +331,7 @@ contract ERC721 is ERC165, IERC721 { ...@@ -330,7 +331,7 @@ contract ERC721 is ERC165, IERC721 {
return true; return true;
} }
bytes4 retval = IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data); bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data);
return (retval == _ERC721_RECEIVED); return (retval == _ERC721_RECEIVED);
} }
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC721.sol"; import "./ERC721.sol";
/** /**
* @title ERC721 Burnable Token * @title ERC721 Burnable Token
* @dev ERC721 Token that can be irreversibly burned (destroyed). * @dev ERC721 Token that can be irreversibly burned (destroyed).
*/ */
contract ERC721Burnable is ERC721 { contract ERC721Burnable is Context, ERC721 {
/** /**
* @dev Burns a specific ERC721 token. * @dev Burns a specific ERC721 token.
* @param tokenId uint256 id of the ERC721 token to be burned. * @param tokenId uint256 id of the ERC721 token to be burned.
*/ */
function burn(uint256 tokenId) public { function burn(uint256 tokenId) public {
//solhint-disable-next-line max-line-length //solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721Burnable: caller is not owner nor approved"); require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
_burn(tokenId); _burn(tokenId);
} }
} }
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC721Enumerable.sol"; import "./IERC721Enumerable.sol";
import "./ERC721.sol"; import "./ERC721.sol";
import "../../introspection/ERC165.sol"; import "../../introspection/ERC165.sol";
...@@ -8,7 +9,7 @@ import "../../introspection/ERC165.sol"; ...@@ -8,7 +9,7 @@ import "../../introspection/ERC165.sol";
* @title ERC-721 Non-Fungible Token with optional enumeration extension logic * @title ERC-721 Non-Fungible Token with optional enumeration extension logic
* @dev See https://eips.ethereum.org/EIPS/eip-721 * @dev See https://eips.ethereum.org/EIPS/eip-721
*/ */
contract ERC721Enumerable is ERC165, ERC721, IERC721Enumerable { contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs // Mapping from owner to list of owned token IDs
mapping(address => uint256[]) private _ownedTokens; mapping(address => uint256[]) private _ownedTokens;
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./ERC721.sol"; import "./ERC721.sol";
import "./IERC721Metadata.sol"; import "./IERC721Metadata.sol";
import "../../introspection/ERC165.sol"; import "../../introspection/ERC165.sol";
contract ERC721Metadata is ERC165, ERC721, IERC721Metadata { contract ERC721Metadata is Context, ERC165, ERC721, IERC721Metadata {
// Token name // Token name
string private _name; string private _name;
......
pragma solidity ^0.5.0; pragma solidity ^0.5.0;
import "../../GSN/Context.sol";
import "./IERC777.sol"; import "./IERC777.sol";
import "./IERC777Recipient.sol"; import "./IERC777Recipient.sol";
import "./IERC777Sender.sol"; import "./IERC777Sender.sol";
...@@ -23,7 +24,7 @@ import "../../introspection/IERC1820Registry.sol"; ...@@ -23,7 +24,7 @@ import "../../introspection/IERC1820Registry.sol";
* are no special restrictions in the amount of tokens that created, moved, or * are no special restrictions in the amount of tokens that created, moved, or
* destroyed. This makes integration with ERC20 applications seamless. * destroyed. This makes integration with ERC20 applications seamless.
*/ */
contract ERC777 is IERC777, IERC20 { contract ERC777 is Context, IERC777, IERC20 {
using SafeMath for uint256; using SafeMath for uint256;
using Address for address; using Address for address;
...@@ -134,7 +135,7 @@ contract ERC777 is IERC777, IERC20 { ...@@ -134,7 +135,7 @@ contract ERC777 is IERC777, IERC20 {
* Also emits a {Transfer} event for ERC20 compatibility. * Also emits a {Transfer} event for ERC20 compatibility.
*/ */
function send(address recipient, uint256 amount, bytes calldata data) external { function send(address recipient, uint256 amount, bytes calldata data) external {
_send(msg.sender, msg.sender, recipient, amount, data, "", true); _send(_msgSender(), _msgSender(), recipient, amount, data, "", true);
} }
/** /**
...@@ -148,7 +149,7 @@ contract ERC777 is IERC777, IERC20 { ...@@ -148,7 +149,7 @@ contract ERC777 is IERC777, IERC20 {
function transfer(address recipient, uint256 amount) external returns (bool) { function transfer(address recipient, uint256 amount) external returns (bool) {
require(recipient != address(0), "ERC777: transfer to the zero address"); require(recipient != address(0), "ERC777: transfer to the zero address");
address from = msg.sender; address from = _msgSender();
_callTokensToSend(from, from, recipient, amount, "", ""); _callTokensToSend(from, from, recipient, amount, "", "");
...@@ -165,7 +166,7 @@ contract ERC777 is IERC777, IERC20 { ...@@ -165,7 +166,7 @@ contract ERC777 is IERC777, IERC20 {
* Also emits a {Transfer} event for ERC20 compatibility. * Also emits a {Transfer} event for ERC20 compatibility.
*/ */
function burn(uint256 amount, bytes calldata data) external { function burn(uint256 amount, bytes calldata data) external {
_burn(msg.sender, msg.sender, amount, data, ""); _burn(_msgSender(), _msgSender(), amount, data, "");
} }
/** /**
...@@ -184,30 +185,30 @@ contract ERC777 is IERC777, IERC20 { ...@@ -184,30 +185,30 @@ contract ERC777 is IERC777, IERC20 {
* @dev See {IERC777-authorizeOperator}. * @dev See {IERC777-authorizeOperator}.
*/ */
function authorizeOperator(address operator) external { function authorizeOperator(address operator) external {
require(msg.sender != operator, "ERC777: authorizing self as operator"); require(_msgSender() != operator, "ERC777: authorizing self as operator");
if (_defaultOperators[operator]) { if (_defaultOperators[operator]) {
delete _revokedDefaultOperators[msg.sender][operator]; delete _revokedDefaultOperators[_msgSender()][operator];
} else { } else {
_operators[msg.sender][operator] = true; _operators[_msgSender()][operator] = true;
} }
emit AuthorizedOperator(operator, msg.sender); emit AuthorizedOperator(operator, _msgSender());
} }
/** /**
* @dev See {IERC777-revokeOperator}. * @dev See {IERC777-revokeOperator}.
*/ */
function revokeOperator(address operator) external { function revokeOperator(address operator) external {
require(operator != msg.sender, "ERC777: revoking self as operator"); require(operator != _msgSender(), "ERC777: revoking self as operator");
if (_defaultOperators[operator]) { if (_defaultOperators[operator]) {
_revokedDefaultOperators[msg.sender][operator] = true; _revokedDefaultOperators[_msgSender()][operator] = true;
} else { } else {
delete _operators[msg.sender][operator]; delete _operators[_msgSender()][operator];
} }
emit RevokedOperator(operator, msg.sender); emit RevokedOperator(operator, _msgSender());
} }
/** /**
...@@ -231,8 +232,8 @@ contract ERC777 is IERC777, IERC20 { ...@@ -231,8 +232,8 @@ contract ERC777 is IERC777, IERC20 {
) )
external external
{ {
require(isOperatorFor(msg.sender, sender), "ERC777: caller is not an operator for holder"); require(isOperatorFor(_msgSender(), sender), "ERC777: caller is not an operator for holder");
_send(msg.sender, sender, recipient, amount, data, operatorData, true); _send(_msgSender(), sender, recipient, amount, data, operatorData, true);
} }
/** /**
...@@ -241,8 +242,8 @@ contract ERC777 is IERC777, IERC20 { ...@@ -241,8 +242,8 @@ contract ERC777 is IERC777, IERC20 {
* Emits {Burned} and {Transfer} events. * Emits {Burned} and {Transfer} events.
*/ */
function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external { function operatorBurn(address account, uint256 amount, bytes calldata data, bytes calldata operatorData) external {
require(isOperatorFor(msg.sender, account), "ERC777: caller is not an operator for holder"); require(isOperatorFor(_msgSender(), account), "ERC777: caller is not an operator for holder");
_burn(msg.sender, account, amount, data, operatorData); _burn(_msgSender(), account, amount, data, operatorData);
} }
/** /**
...@@ -262,7 +263,7 @@ contract ERC777 is IERC777, IERC20 { ...@@ -262,7 +263,7 @@ contract ERC777 is IERC777, IERC20 {
* Note that accounts cannot have allowance issued by their operators. * Note that accounts cannot have allowance issued by their operators.
*/ */
function approve(address spender, uint256 value) external returns (bool) { function approve(address spender, uint256 value) external returns (bool) {
address holder = msg.sender; address holder = _msgSender();
_approve(holder, spender, value); _approve(holder, spender, value);
return true; return true;
} }
...@@ -280,7 +281,7 @@ contract ERC777 is IERC777, IERC20 { ...@@ -280,7 +281,7 @@ contract ERC777 is IERC777, IERC20 {
require(recipient != address(0), "ERC777: transfer to the zero address"); require(recipient != address(0), "ERC777: transfer to the zero address");
require(holder != address(0), "ERC777: transfer from the zero address"); require(holder != address(0), "ERC777: transfer from the zero address");
address spender = msg.sender; address spender = _msgSender();
_callTokensToSend(spender, holder, recipient, amount, "", ""); _callTokensToSend(spender, holder, recipient, amount, "", "");
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
}, },
"homepage": "https://github.com/OpenZeppelin/openzeppelin-contracts", "homepage": "https://github.com/OpenZeppelin/openzeppelin-contracts",
"devDependencies": { "devDependencies": {
"@openzeppelin/gsn-helpers": "^0.1.4", "@openzeppelin/gsn-helpers": "^0.1.5",
"@openzeppelin/gsn-provider": "^0.1.4", "@openzeppelin/gsn-provider": "^0.1.4",
"chai": "^4.2.0", "chai": "^4.2.0",
"concurrently": "^4.1.0", "concurrently": "^4.1.0",
......
const { constants, expectEvent } = require('openzeppelin-test-helpers');
const { ZERO_ADDRESS } = constants;
const gsn = require('@openzeppelin/gsn-helpers');
const { fixSignature } = require('../helpers/sign');
const { utils: { toBN } } = require('web3');
const ERC721GSNRecipientMock = artifacts.require('ERC721GSNRecipientMock');
contract('ERC721GSNRecipient (integration)', function ([_, signer, sender]) {
const tokenId = '42';
beforeEach(async function () {
this.token = await ERC721GSNRecipientMock.new(signer);
});
async function testMintToken (token, from, tokenId, options = {}) {
const { tx } = await token.mint(tokenId, { from, ...options });
await expectEvent.inTransaction(tx, ERC721GSNRecipientMock, 'Transfer', { from: ZERO_ADDRESS, to: from, tokenId });
}
context('when called directly', function () {
it('sender can mint tokens', async function () {
await testMintToken(this.token, sender, tokenId);
});
});
context('when relay-called', function () {
beforeEach(async function () {
await gsn.fundRecipient(web3, { recipient: this.token.address });
});
it('sender can mint tokens', async function () {
const approveFunction = async (data) =>
fixSignature(
await web3.eth.sign(
web3.utils.soliditySha3(
// eslint-disable-next-line max-len
data.relayerAddress, data.from, data.encodedFunctionCall, toBN(data.txFee), toBN(data.gasPrice), toBN(data.gas), toBN(data.nonce), data.relayHubAddress, this.token.address
), signer
)
);
await testMintToken(this.token, sender, tokenId, { useGSN: true, approveFunction });
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment