I'm fresh on solidity, when I use remix to test my contract, I want to transfer some eth from my account to the smart contract. I have tried this code, but it seems to transfer the eth from the contract but not my account.
function addStaker (uint _stakeAmount) public membership(master, msg.sender) returns(bool) {
if(!members[msg.sender].alreadyExist) {
Member memory newMember = Member(msg.sender, true);
members[msg.sender] = newMember;
bool sent = payable(address(this)).send(_stakeAmount);
require(sent, "invalid balance");
return true;
} else {
return false;
}
}
How could I transfer eth from my account to the smart contract?
A smart contract is not able to pull a contract-specified amount of ETH from an address. The amount needs to always be specified and signed by the sender.
The contract can only validate the sent amount:
function addStaker() public payable {
require(msg.value == 1 ether);
}
How to chose the amount depends on the wallet software you're using. In case of Remix, there's the "Value" input in the "Deploy & Run Transactions" tab, where you specify the amount of ETH sent with the transaction.
If you want to implement a defi contract (since your function name is addStaker) that accepts staked coins from ERC20 tokens, the implementation is different. But if you just want to send money to contract from your metamask account, you have to mark the function payable.
function pay() public payable {
// msg.value is the amount of wei sent with the message to the contract.
// with this you are setting a minimum amount
require(msg.value > .01 ether);
// add your logic
}
Related
I want to build an NFT that I can paid with an ERC-20 token to mint it. I'm using currently the Mumbai testnet on polygon, and I'm using the Dummy ERC20 token to test it out.
This is currently my constructor:
ERC20 token;
constructor() ERC721("Token", "TKN") {
token = ERC20(0xfe4F5145f6e09952a5ba9e956ED0C25e3Fa4c7F1);
}
And this is my mint function:
function mint() public returns (uint256) {
uint256 tokenId = _tokenIds.current();
require(tokenId <= MAX_TOKEN_ID);
token.approve(address(this), NFT_PRICE);
token.transfer(address(this), NFT_PRICE);
_mint(msg.sender, tokenId);
_setTokenURI(tokenId, TOKEN_URI);
_tokenIds.increment();
return tokenId;
}
If I remove those 2 lines the code works fine, it mints the NFT:
token.approve(address(this), NFT_PRICE);
token.transfer(address(this), NFT_PRICE);
But as soon as I add it, the code breaks, it gives me the following gas estimation error:
The transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": 3, "message": "execution reverted: ERC20: transfer amount exceeds balance", "data": "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002645524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63650000000000000000000000000000000000000000000000000000" }
As a troubleshooting step I've also added this inside my mint function to make sure I'm calling from my own wallet:
sender = msg.sender;
And created this function:
function tokenBalance(address addr) public view returns (uint256) {
return token.balanceOf(addr);
}
And if I grab the token balance of the sender address it gives me the value:
0: uint256: 2000000000000000000
It's because the logic is wrong. That approve function you call inside your mint function is useless: the spender needs to call the approve function from the the contract of your dummy ERC20.
And then you can call the transferFrom(msg.sender, address(this), NFT_PRICE) from your mint function.
contract Bank {
address public admin;
constructor() {
admin = msg.sender;
}
mapping (address => uint) balance;
mapping (address => bool) AccountActive;
function closeAccount() public payable{
AccountActive[msg.sender] = false;
//trasfer all the money from an account closed to the admin
payable(admin).transfer(balance[msg.sender]);
}
function viewbalance() public view returns(uint) {
return balance[msg.sender];
}}
when inserting a value before deployment, I get this error, and if I don't do it in this way the balance is 0, why? (sorry for this noob question)
This error is because you can not use an address ether balance from a smart contract. What I mean is that a smart contract cannot transfer ether from one address to another, because it would be really dangerous.
What you can do is to transfer the msg.value, which is the ether sent as the value of the transaction.
By the way, you should check for correct indentation and symbols placement. Those can lead to errors too.
The issue is here:
payable(admin).transfer(balance[msg.sender]);
You want to transfer money from the admin but the admin has no balance. So you need to send money. For this write this function:
function depositMoneyToAdmin() payable public {
// since it is payable, the money that you send would be stored in msg.value
(bool success,) = admin.call{value: msg.value}("");
// then add the owner's balance to the mapping so when u call viewBalance, you get the balance of owner
balance[admin]+=msg.value;
require(success,"Transfer failed!");
}
Avoid using transfer.
https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
I am playing with Ethereum smart contracts and noticed some strange behavior of some transactions.
Transaction is visible and it states that tokens are sent to an address but when I check balance on Metamask it's not here (Token contract is added to MetaMask). What could be the reason of such contract behavior?
This is example transaction: https://ropsten.etherscan.io/tx/0xf3316c497fd47ee79be57be7b91cb96cc0414003a155d8ff8bc83b3a090594c9
200,000 tokens is sent to https://ropsten.etherscan.io/address/0x9DEF8C013eb590aFf09c8c76F9A74A3055fAA177#tokentxns and it's displayed on ropsten network explorer, but I can't see them or manipulate on MetaMask.
This is part of my smart contract which does transfer, I marked line with comment "invisible" which does not work for me:
function transfer(address to, uint256 value) public returns (bool) {
require(value <= _balances[msg.sender]);
require(to != address(0));
uint256 tokensToBurn = findOnePercent(value);
uint256 tokensToStack = findOnePercent(value);
uint256 tokenstoDeduct = tokensToBurn.add(tokensToStack);
uint256 tokensToTransfer = value.sub(tokenstoDeduct);
_balances[msg.sender] = _balances[msg.sender].sub(value);
_balances[to] = _balances[to].add(tokensToTransfer);
_totalSupply = _totalSupply.sub(tokenstoDeduct);
emit Transfer(msg.sender, to, tokensToTransfer); // visible on metaMask
emit Transfer(msg.sender, address(0), tokensToBurn); // burned
emit Transfer(msg.sender, address(VAULT_ADDRESS), tokensToStack); // invisible on metaMask
return true;
}
This is screenshot of address wallet: 0x9DEF8C013eb590aFf09c8c76F9A74A3055fAA177
Please advise what I could do wrong here.
[meanwhile I submitted ticket to MetaMask, maybe it's a defect on wallet extension]
You need to add the contract address to your Metamask instance.
In the account detail, click on "Add token"
Paste the conctract address to the address field in the "Custom token" tab
Review the data, click "Next", and you you can see the token balance in your wallet.
I am using the below code in solidity to transfer ether from one account to another.
I am calling this from the owner's account.
But my ether gets deducted from owners and goes to contract address instead of the receiver/payee account.
function PayCredit(address payable payee, uint money, uint invoiceNum) public payable{
require(msg.sender==owner, "only owner can invoke it");
payee.transfer(address(this).balance);
claims[payee][invoiceNum].isPayed = true;
}
You are sending your ether's to contract address , change address(this) to address .
I would suggest you good practice of sending ether's to other account. Solidity transaction support value as argument and this is good place for sending ether(WEI) to other account . below code snippet will send 12 WEI to other account.
pragma solidity >=0.4.22 <0.6.0;
contract AB {
uint256 num1;
address owner;
constructor() public{
owner = msg.sender;
}
function sendBal(address payable receiver) payable external onlyOwner {
uint256 amount = msg.value;
receiver.transfer(amount);
}
I am developing smart contract based on openzeppelin-solidity and I want to write an easy Crowdsale contract, only I did is inherit Contract.sol:
// FloatFlowerTokenCrowdsale.sol
pragma solidity 0.4.23;
import "openzeppelin-solidity/contracts/crowdsale/Crowdsale.sol";
contract FloatFlowerTokenCrowdsale is Crowdsale{
constructor(ERC20 _token) public Crowdsale(1000, msg.sender, _token)
{
}
}
Here is my FloatFlowerToken.sol
// FloatFlowerToken.sol
pragma solidity 0.4.23;
import "openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol";
contract FloatFlowerToken is StandardToken {
string public name = "FLOATFLOWER TOKEN";
string public symbol = "FFT";
uint8 public decimals = 18;
constructor() public {
totalSupply_ = 36000000;
balances[msg.sender] = totalSupply_;
}
}
And this is my 2_deploy_contract.js
const FloatFlowerToken = artifacts.require('./FloatFlowerToken.sol');
const FloatFlowerTokenCrowdsale =
artifacts.require('./FloatFlowerTokenCrowdsale.sol');
module.exports = function(deployer, network, accounts) {
return deployer
.then(() => {
return deployer.deploy(FloatFlowerToken);
})
.then(() => {
return deployer.deploy(FloatFlowerTokenCrowdsale, FloatFlowerToken.address);
})
};
After I execute the truffle test and I got the error Error: VM Exception while processing transaction: revert
And here is my test code:
it('one ETH should buy 1000 FLOATFLOWER TOKEN in Crowdsale', function(done) {
FloatFlowerTokenCrowdsale.deployed().then(async function(instance) {
const data = await instance.sendTransaction({from: accounts[7], value: web3.toWei(1, "ether")}, function(error, txhash) {
console.log(error);
});
const tokenAddress = await instance.token.call();
const FloatFlowerToken = FloatFlowerToken.at(tokenAddress);
const tokenAmount = await FloatFlowerToken.balanceOf(accounts[7]);
assert.equal(tokenAmount.toNumber(), 1000000000000000000000, 'The sender didn\'t receive the tokens as crowdsale rate.');
})
})
I don't know how to check the error log and to know which line cause this problem.
You have 2 issues:
First, the units you're working with aren't correct. You've initialized your crowdsale to sell 1000 tokens for every Wei sent. From the documentation in the Zeppelin contract:
#param _rate Number of token units a buyer gets per wei
#param _wallet Address where collected funds will be forwarded to
#param _token Address of the token being sold
You're passing in 1 ether in your transaction, which means you're attempting to buy 1000 * (10^18) token units, but you've only allocated 36000000 total supply. You need to increase your total supply and/or lower your rate.
Second, only token owners can do a transfer unless an approve has been done first. When you deploy the token contract, all of the tokens are owned by msg.sender. However, when someone makes a purchase through your crowdsale contract, the request to do the transfer is coming from the address of the crowdsale contract, not the token owner when your token contract was deployed. The simplest way around this is after deploying your contracts, transfer enough tokens for the crowdsale from the address you used to create the token contract over to the address of the crowdsale contract.