What is the usage of Context.sol within ERC-20? - blockchain

When releasing the ERC-20 token,
OZ(OpenZeppelin)'s util Context.sol is inherited.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/*
* #dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
I read that when using a meta-transaction solution such as EIP-2771, Context.sol is useful.
https://forum.openzeppelin.com/t/help-understanding-contract-context/10579
function _msgSender() internal view virtual override returns (address sender) {
if (isTrustedForwarder(msg.sender)) {
// The assembly code is more direct than the Solidity version using `abi.decode`.
assembly { sender := shr(96, calldataload(sub(calldatasize(), 20))) }
} else {
return super._msgSender();
}
}
But in the case of ERC-20, why shoud I use Context.sol's _msgSender()?
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
Doesn't make it more secure?
What is the usage of Context.sol within ERC-20?
Thank you in advance.

Context is needed to implement metatransactions, or gas free transactions for token transfers.
More about Context in Gas Station Network documentation.
If you do not plan to support this feature (hint: no one does today) you do not need to Context.

Related

ive done a code that changes ownership and transfer the balance of the old owner to the new one but it does not seem to work

// contracts/transferownership.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
contract transferownership is ERC20, Ownable {
uint256 lastpresence;
uint256 amount = balanceOf(msg.sender);
constructor(uint256 initialSupply) ERC20("interorm", "intr") {
_mint(msg.sender, initialSupply);
}
function presence() public onlyOwner {
lastpresence = block.timestamp;
}
function changeOwnership(address newowner) public {
require(lastpresence < block.timestamp - 356 days);
transfer(newowner, amount);
_transferOwnership(newowner);
lastpresence = block.timestamp;
}
}
//The transaction has been reverted to the initial state.
Reason provided by the contract: "ERC20: transfer amount exceeds balance".
Debug the transaction to get more information.
//basically the program should transfer the whole amount of money
and then change ownership but im getting this error
everytime i call the changeownership function
To fix it, simply declare the amount variable in the changeOwnership function. That is before you call the transfer method.
uint256 amount = balanceOf(msg.sender);
transfer(newowner, amount);
Ensure that you set the changeOwnership function as payable.
function changeOwnership(address newowner) payable public {
Explanation: When you debug the function, the way you have it originally, you will find that the value=0, this is because the amount declaration in the global variable is not called in the stack when the transfer method is called.
To make the amount available in the call stack, you will have to parse it in the function.

Is payble keyword neccessary even if I am not taking any ether/matic?

function sendGift(uint256 _mintAmount,address recipient) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount<= availableSupplyForSale);
//require(_amount >= cost * _mintAmount);
require(coinToken.allowance(msg.sender,address(this))>=cost * _mintAmount);
coinToken.transferFrom(msg.sender, address(this),cost * _mintAmount);
if(supply<currentSupply){
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(recipient, supply + i);
}
}
else{
uint256[] memory tokenIds = walletOfOwner(address(this));
for(uint256 i=1;i<=_mintAmount;i++)
transferFrom(address(this),recipient,tokenIds[i]);
}
}
Do I need to use payable here? Contract does not take any matic. It only takes custom token as payment .
(bool os, ) = payable(admin).call{value: address(this).balance}("");
require(os);
Also since I am not taking any matic, will this above line necessary for withdraw assets from contract as an owner? I have a sense that this above line only is useful to withdraw eth/polygon.
I am a new blockchain kid. Please help.
The payable modifier of a function is required when your function accepts native tokens (ETH, BNB, MATIC, ... depending on the network).
So in this case, you can safely remove it from the function header.
// removed `payable`
function sendGift(uint256 _mintAmount,address recipient) public {
The low-level .call() also doesn't require using payable to send native tokens.
payable(admin).call{value: address(this).balance}("");
However, if you used the high-level .transfer(), then you'd need to cast the admin variable type address to its extension type address payable using the typecasting function.
// will not work as it's type `address`
admin.transfer(address(this).balance);
// need to cast type `address` to type `address payable`
payable(admin).transfer(address(this).balance);
In order to withdraw tokens from your contract address, you need to invoke the transfer() function (defined in the ERC-20 standard) on the token contract. Do not confuse it with the native transfer() function of address payable, these are two separate things, just with the same name.
interface IERC20 {
function transfer(address, uint256) external returns (bool);
}
contract MyContract {
function withdrawToken() {
IERC20(tokenContractAddress).transfer(recipient, amount);
}
}

there is a problem in the gas requirement

I have been written a smart contract, I am trying to execute the following code but I have these problems:
1- "Gas requirement of function EKM.register_PK is infinite: If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
Pos: 32:0:"
2- "Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.
more
Pos: 30:2:"
My code:
pragma solidity >=0.8.13;
//SPDX-License-Identifier:MIT
contract EKM{
/**
* #dev VTA is a state variable
*/
address public VTA;
/**
* #dev mapping address as key to struct user with mapping name users
*/
mapping (uint => user) public users;
/**
* #dev assigning the contract deployer as the VTA
*/
constructor() {
VTA =msg.sender;
}
struct user {
string PKname;
string PKvehicle;
uint256 vP;
bool status;
}
event addPK(string name, string PKv, uint256 VPv) ;
function register_PK(uint ID_v, string memory PKname, string memory PKvehicle, uint256 vP) public returns(bool){
require(users[ID_v].status == true,"register the public key of the user");
if(msg.sender != VTA)
{revert();}
if(ID_v == 0)
{return false;}
else
{
ID_v++;
users[ID_v]= user(PKname,PKvehicle,vP,true);
//PKname=users[ID_v].PKname;
//PKvehicle=users[ID_v].PKvehicle;
// vP=users[ID_v].vP;
emit addPK(PKname, PKvehicle, vP);
return true;
}
}
}
what should I do?
Go to solidity static analysis ,and then gas and economy , untick all options except. This on local calls:
Invocation of local functions via 'this' and Delete dynamic array:
Use require/assert to ensure complete deletion. it will work

Where would a transaction take place in my Smart Contract

I am making a simple smart contract that is essentially a ledger that people can sign with a string (UI to come) and then pass onto a next person (using their ether address). I just wanted to create something that could be passed from person to person while recording its journey.
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time). Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
my solidity code so far:
pragma solidity ^0.4.4;
contract Pass{
mapping(address => bool) ownership;
mapping(address => string) notes;
constructor(address genesis) public {
ownership[genesis] = true; //this address starts with it
}
function checkOwnership(address p) public view returns(bool){
if(ownership[p]){
return true;
}
return false;
}
function sign(string signedNote) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
notes[msg.sender] = signedNote;
return 1;
}
return 0;
}
function pass(address recipient) public returns(uint){ // 1 on success 0 on fail
if(checkOwnership(msg.sender)){ //if msg.sender owns the note
ownership[msg.sender] = 0;
ownership[recipient] = 1;
return 1;
}
return 0;
}
function viewNotes(address participant) public returns(string){ // signed note on success nothing on fail
if(notes[participant] !== 0){
return (notes(participant));
}
}
}
The logic of 'transferring' the signing-ledger is all done within the smart contract, with it existing as a mapping and the key value of an address changing from 0 to 1 signifying ownership (1 person owning it at a time)
This is a common pattern known as the owner pattern. You can simplify this by simply keeping track of a single owner address and updating that, instead of using a mapping, since you only care about the current owner. Something as simple as:
address public owner;
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
constructor() {
owner = msg.sender;
}
function transferOwnership(address _owner) onlyOwner {
owner = _owner;
}
Open Zeppelin has a more complete implementation of ownership here.
Because there's no actual transfer of ether/actual monetary value, where would actual ethereum transactions be occurring in this contract?
Transactions do not require ether movement. You can call any public/external function on your contract with a 0 value transaction, and pass data to it. The transaction will execute on the blockchain like any other, and run the code you invoke within the contract.
Also to sign the ledger I verify that the public key signing it has 1 as its value in the mapping, but how would I check that that person owns that public key (using a private key)?
You are already checking is msg.sender matches the whitelisted address. For basic transactions, this means that the transaction has been signed by the address in msg.sender (msg.sender can also be a contract, if another contract calls yours. To check who actually signed the transaction in all scenarios, you must use tx.origin).

Transfer function not working as expected in solidity

Considering below code
mapping (address => uint256) public balanceOf;
event Transfer(address indexed from, address indexed to, uint256 value);
function _transfer(address _from, address _to, uint _value) internal {
require(_to != 0x0);
require(balanceOf[_from] >= _value);
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
Transfer(_from, _to, _value);
}
function sell(uint256 amount) public {
require(this.balance >= amount * sellPrice);
_transfer(msg.sender, this, amount);
msg.sender.transfer(amount * sellPrice);
}
function sendTokens(address _to, uint value) public {
_transfer(msg.sender,_to,value);
msg.sender.transfer(value * sellPrice);
}
function buy() payable public {
uint amount = (msg.value / buyPrice) * 1 wei;
_transfer(this, msg.sender, amount);
}
Here sell() and buy() function sends/receive tokens to/from contract but when function with almost same signature sendTokens() is called it is not able to send or are sending 0 tokens. Contract also has ethers and tokens. But it always consider tokens to send and receive. But sendTokens is not behaving same with almost same code.
Also I have an another question related to this. Every account has ethers and multiple tokens. Then how will it identify that here this specific tokens needs to be send or here ether is to be send and not any tokens.
Can anyone help. Thanks in advance.
Well there is no correction in the code. Perhaps Metamask and remix is not supporting this type of transaction at this moment. When I call this method from Web3js it worked. So couldn't find the exact reason but yes it worked at end.