I have written smart contract for basic ICO using ERC223 token Standard.
When I verified the code in securify.ch(https://securify.chainsecurity.com/) it is showing some security errors. Here is the code where I am getting those errors
Code:
function transfer(address _to, uint _value, bytes _data) public {
uint codeLength;
assembly {
codeLength := extcodesize(_to)
}
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
if(codeLength>0) {
ERC223ReceivingContract receiver = ERC223ReceivingContract(_to);
receiver.tokenFallback(msg.sender, _value, _data);
}
emit Transfer(msg.sender, _to, _value, _data);
}
In the below line, I am getting the errors.
receiver.tokenFallback(msg.sender, _value, _data);
Error : This contract allows an arbitrary user to execute untrusted code on behalf of the contract. This is because any user can submit an arbitrary address _spender and arbitrary data _data which are provided as argument to the method. The address spender determines the target of the call instruction, while _data determines the function called in the untrusted contract.
Related
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);
}
}
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.
I am getting generic error every time I try to modify the code. I am passing byte32 value as "0xabcd" and address value as "0xca35b7d915458ef540ade6068dfe2f44e8fa733c" in Setaddress function.
The error is as below:
"transact to EternalStorage.setAddress errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information."
Below is my code
pragma solidity ^0.4.17;
contract EternalStorage {
address owner = msg.sender;
address latestVersion;
mapping(bytes32 => uint) uIntStorage;
mapping(bytes32 => address) addressStorage;
modifier onlyLatestVersion() {
require(msg.sender == latestVersion);
_;
}
function upgradeVersion(address _newVersion) public {
require(msg.sender == owner);
latestVersion = _newVersion;
}
// *** Getter Methods ***
function getUint(bytes32 _key) external view returns(uint) {
return uIntStorage[_key];
}
function getAddress(bytes32 _key) external view returns(address) {
return addressStorage[_key];
}
// *** Setter Methods ***
function setUint(bytes32 _key, uint _value) onlyLatestVersion external {
uIntStorage[_key] = _value;
}
function setAddress(bytes32 _key, address _value) onlyLatestVersion external payable{
addressStorage[_key] = _value;
}
// *** Delete Methods ***
function deleteUint(bytes32 _key) onlyLatestVersion external {
delete uIntStorage[_key];
}
function deleteAddress(bytes32 _key) onlyLatestVersion external {
delete addressStorage[_key];
}
}
The error message says that the transaction to setAddress() reverted:
transact to EternalStorage.setAddress errored: VM error: revert.
There is only one requre() statement in setAddress(), in onlyLatestVersion():
require(msg.sender == latestVersion);
So it's virtually certain that the sender of the transaction (msg.sender) is not set to latestVersion. That means you either need to:
Make sure you are sending from the account that the contract has as the latestVersion, or...
Change latestVersion using the contract's function upgradeVersion(), so that it matches your transaction sender.
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.
I am new to blockchain technology and trying to understand somethings(Etheruem, Truffle, DApps etc.) here and there from the internet.
From Ethereum official website,
Create a cryptocurrency contract in Ethereum
I am trying to specifically understand these functions
approve(address _spender, uint _value) returns (bool success) {...}
approveAndCall(address _spender, uint _value, bytes _extraData) returns (bool success) {...}
transferFrom(address _from, address _to, uint _value) returns (bool success) {...}
and lastly this function() {throw;}
This contract code
contract tokenRecipient {
function receiveApproval(address _from, uint _value, address _token, bytes _extraData);
}
and this declaration mapping (address => mapping (address => uint) ) public allowance;
First function basically takes address to where coin is to send and the value to be sent and return boolean value. Other function is for transfer value and takes sender and reciever address and returns again bookean value for success or failure.
I posted this question on Ethereum Stackchange and got the answer. Follow the comments also.
How does a token contract work?