Closed ednawnika closed 3 years ago
Im attaching the required contracts
// File: openzeppelin-solidity/contracts/GSN/Context.sol
pragma solidity ^0.5.0;
/*
This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) { return msg.sender; }
function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// File: openzeppelin-solidity/contracts/token/ERC20/IERC20.sol
pragma solidity ^0.5.0;
/**
the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /**
/**
account
.
*/
function balanceOf(address account) external view returns (uint256);/**
amount
tokens from the caller's account to recipient
./**
spender
will beowner
through {transferFrom}. This is/**
amount
as the allowance of spender
over the caller's tokens./**
amount
tokens from sender
to recipient
using theamount
is then deducted from the caller's/**
value
tokens are moved from one account (from
) toto
).value
may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);/**
spender
for an owner
is set byvalue
is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.5.0;
/**
SafeMath
restores this intuition by reverting the transaction when anclass of bugs, so it's recommended to use it always. */ library SafeMath { /**
+
operator.return c; }
/**
-
operator./**
-
operator.Available since v2.4.0. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b;
return c; }
/**
*
operator.uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow");
return c; }
/**
/
operator. Note: this function uses arevert
opcode (which leaves remaining gas untouched) while Solidity/**
/
operator. Note: this function uses arevert
opcode (which leaves remaining gas untouched) while SolidityAvailable since v2.4.0. / function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b c + a % b); // There is no case in which this doesn't hold
return c; }
/**
%
operator. This function uses a revert
/**
%
operator. This function uses a revert
// File: openzeppelin-solidity/contracts/token/ERC20/ERC20.sol
pragma solidity ^0.5.0;
/**
false
on failure. This behavior is nonetheless conventionalallowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
/**
/**
/**
recipient
cannot be the zero address.amount
.
*/
function transfer(address recipient, uint256 amount) public returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}/**
/**
spender
cannot be the zero address.
*/
function approve(address spender, uint256 amount) public returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}/**
sender
and recipient
cannot be the zero address.sender
must have a balance of at least amount
.sender
's tokens of at leastamount
.
*/
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}/**
spender
by the caller.spender
cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}/**
spender
by the caller.spender
cannot be the zero address.spender
must have allowance for the caller of at leastsubtractedValue
.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}/**
amount
from sender
to recipient
.sender
cannot be the zero address.recipient
cannot be the zero address.sender
must have a balance of at least amount
.
*/
function _transfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); }
/** @dev Creates amount
tokens and assigns them to account
, increasing
from
set to the zero address.to
cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal {
require(account != address(0), "ERC20: mint to the zero address");_totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); }
/**
amount
tokens from account
, reducing theto
set to the zero address.account
cannot be the zero address.account
must have at least amount
tokens.
*/
function _burn(address account, uint256 amount) internal {
require(account != address(0), "ERC20: burn from the zero address");_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); }
/**
amount
as the allowance of spender
over the owner
s tokens.approve
, and can be used toowner
cannot be the zero address.spender
cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");_allowances[owner][spender] = amount; emit Approval(owner, spender, amount); }
/**
amount
tokens from account
.amount
is then deducted// File: openzeppelin-solidity/contracts/access/Roles.sol
pragma solidity ^0.5.0;
/**
@dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; }
/**
/**
/**
// File: openzeppelin-solidity/contracts/access/roles/MinterRole.sol
pragma solidity ^0.5.0;
contract MinterRole is Context { using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor () internal {
_addMinter(_msgSender());
}
modifier onlyMinter() {
require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(_msgSender());
}
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
// File: original_contracts/EIP712Base.sol
pragma solidity 0.5.17;
contract EIP712Base {
struct EIP712Domain {
string name;
string version;
uint256 chainId;
address verifyingContract;
}
bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(bytes("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"));
bytes32 internal domainSeperator;
uint256 private _chainid;
constructor(string memory name, string memory version, uint256 chainid) public {
_chainid = chainid;
domainSeperator = keccak256(abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(bytes(name)),
keccak256(bytes(version)),
getChainID(),
address(this)
));
}
function getChainID() public view returns (uint256 id) {
return _chainid;
}
function getDomainSeperator() private view returns(bytes32) {
return domainSeperator;
}
/**
* Accept message hash and returns hash message in EIP712 compatible form
* So that it can be used to recover signer from signature signed using EIP712 formatted data
* https://eips.ethereum.org/EIPS/eip-712
* "\\x19" makes the encoding deterministic
* "\\x01" is the version byte to make it compatible to EIP-191
*/
function toTypedMessageHash(bytes32 messageHash) internal view returns(bytes32) {
return keccak256(abi.encodePacked("\x19\x01", getDomainSeperator(), messageHash));
}
}
// File: original_contracts/EIP712MetaTransaction.sol
pragma solidity 0.5.17;
contract EIP712MetaTransaction is EIP712Base { using SafeMath for uint256; bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256( bytes( "MetaTransaction(uint256 nonce,address from,bytes functionSignature)" ) );
event MetaTransactionExecuted(
address userAddress,
address payable relayerAddress,
bytes functionSignature
);
mapping(address => uint256) nonces;
/*
* Meta transaction structure.
* No point of including value field here as if user is doing value transfer then he has the funds to pay for gas
* He should call the desired function directly in that case.
*/
struct MetaTransaction {
uint256 nonce;
address from;
bytes functionSignature;
}
constructor(string memory name, string memory version, uint256 chainid)
public
EIP712Base(name, version, chainid)
{}
function executeMetaTransaction(
address userAddress,
bytes memory functionSignature,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) public payable returns (bytes memory) {
MetaTransaction memory metaTx = MetaTransaction({
nonce: nonces[userAddress],
from: userAddress,
functionSignature: functionSignature
});
require(
verify(userAddress, metaTx, sigR, sigS, sigV),
"Signer and signature do not match"
);
// Append userAddress and relayer address at the end to extract it from calling context
(bool success, bytes memory returnData) = address(this).call(
abi.encodePacked(functionSignature, userAddress)
);
require(success, "Function call not successfull");
nonces[userAddress] = nonces[userAddress].add(1);
emit MetaTransactionExecuted(
userAddress,
msg.sender,
functionSignature
);
return returnData;
}
function hashMetaTransaction(MetaTransaction memory metaTx)
internal
view
returns (bytes32)
{
return
keccak256(
abi.encode(
META_TRANSACTION_TYPEHASH,
metaTx.nonce,
metaTx.from,
keccak256(metaTx.functionSignature)
)
);
}
function getNonce(address user) public view returns (uint256 nonce) {
nonce = nonces[user];
}
function verify(
address signer,
MetaTransaction memory metaTx,
bytes32 sigR,
bytes32 sigS,
uint8 sigV
) internal view returns (bool) {
return
signer ==
ecrecover(
toTypedMessageHash(hashMetaTransaction(metaTx)),
sigV,
sigR,
sigS
);
}
function _msgSender() internal view returns (address payable sender) {
if(msg.sender == address(this)) {
bytes memory array = msg.data;
uint256 index = msg.data.length;
assembly {
// Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
}
} else {
sender = msg.sender;
}
return sender;
}
}
// File: original_contracts/interfaces/IFeeSettings.sol
pragma solidity 0.5.17;
interface IFeeSettings {
function getFeeWallet() external view returns(address);
function getFeePercentage() external view returns(uint256);
function getMinimumFee() external view returns(uint256);
function changeFeeWallet(address feeWallet) external;
function changeFeePercentage(uint256 feePercentage) external;
function changeMinimuFee(uint256 minimumFee) external;
}
// File: original_contracts/Token.sol
pragma solidity 0.5.17;
contract Token is ERC20, MinterRole, EIP712MetaTransaction {
string public name;
string public symbol;
uint8 public decimals;
mapping(address=>uint256) public userLastActivityBlock;
//Number of blocks after which points will be expired for the user, if no activity is done within that time period
uint256 public expiryThreshold;
IFeeSettings public feeSettings;
event MintWithId(
address indexed minter,
address indexed account,
uint256 amount,
string id
);
event BurnWithId(
address indexed burner,
uint256 amount,
string id
);
event ExpiryThresholdChanged(
uint256 newTHreshold
);
event FeeTaken(address indexed receiver, uint256 amount);
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals,
address _feeSettings,
uint256 chainid
)
public
EIP712MetaTransaction("Afrofuture", "0.1", chainid)
{
name = _name;
symbol = _symbol;
decimals = _decimals;
feeSettings = IFeeSettings(_feeSettings);
}
function changeExpiryThreshold(uint256 threshold) external onlyMinter {
expiryThreshold = threshold;
emit ExpiryThresholdChanged(threshold);
}
function mintWithId(
address account,
uint256 amount,
string calldata id
)
external
onlyMinter
returns (bool)
{
checkAndBurnExpiredTokens(account);
userLastActivityBlock[account] = block.number;
_mint(account, amount);
_takeFee(amount);
emit MintWithId(
_msgSender(),
account,
amount,
id
);
return true;
}
function burnWithId(
uint256 amount,
string calldata id
)
external
{
bool expired = checkAndBurnExpiredTokens(_msgSender());
if(expired) {
return;
}
userLastActivityBlock[_msgSender()] = block.number;
_burn(_msgSender(), amount);
emit BurnWithId(
_msgSender(),
amount,
id
);
}
function checkAndBurnExpiredTokens(address user) public returns(bool) {
if (isExpired(user)) {
_burn(user, balanceOf(user));
emit BurnWithId(
user,
balanceOf(user),
"EXPIRED"
);
return true;
}
else {
return false;
}
}
function isExpired(address user) public returns(bool) {
if ( expiryThreshold > 0 && balanceOf(user) > 0 && userLastActivityBlock[user].add(expiryThreshold) < block.number) {
return true;
}
else {
return false;
}
}
function _transfer(
address sender,
address recipient,
uint256 amount
)
internal
{
checkAndBurnExpiredTokens(sender);
checkAndBurnExpiredTokens(recipient);
userLastActivityBlock[sender] = block.number;
userLastActivityBlock[recipient] = block.number;
super._transfer(sender, recipient, amount);
}
function _takeFee(uint256 amount) private {
if(amount == 0){
return;
}
uint256 fee = amount.mul(feeSettings.getFeePercentage()).div(10000);
if (fee < feeSettings.getMinimumFee()) {
fee = feeSettings.getMinimumFee();
}
if(fee > 0) {
_mint(feeSettings.getFeeWallet(), fee);
emit FeeTaken(feeSettings.getFeeWallet(), fee);
}
}
}
Token: AFTR Token type ERC20 Ethereum address 0x56dfa98f363edb99240b63f8a5141d8b64cfaf6e Polygon address 0x228a22bf6da9353Abbe37a31cf85c02dfC432456 Decimals 8 Mintable false