How can I send tokens to a token holders from inside a smart contract with solidity?
It means how can send reward to token holders?
Have a list of addresses and loop through them while calling native erc transfer method. You can't really iterate through a mapping without knowing the access keys (if you're thinking about pulling addresses from smth like balances).
I am assuming you want to send Ether to another Smart Contract or an EOA (e.g. Metamask). You can write a Smart Contract such as the below and use the Remix Ethereum (an IDE) to send Ether to an external party. Use the public function - transferEther.
//SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.6.0 < 0.9.0;
contract Sample{
address public owner;
constructor() {
owner = msg.sender;
}
receive() external payable {
}
fallback() external payable {
}
function getBalance() public view returns (uint){
return address(this).balance;
}
// this function is for sending the wei/ether OUT from this smart contract (address) to another contract/external account.
function transferEther(address payable recipient, uint amount) public returns(bool){
require(owner == msg.sender, "transfer failed because you are not the owner."); //
if (amount <= getBalance()) {
recipient.transfer(amount);
return true;
} else {
return false;
}
}
}
Related
So, I'm learning advanced smart contract development. Two days ago, I learned about Reentrancy attacks and then I also created two contracts Protocol.sol (vulnerable contract) + Hacker.sol (attacker contract) to put my knowledge to the test. I was able to perform everything smoothly, I was importing the Protocol.sol (ABI + address) contract in my Hacker.sol. Today, I learned that we can call another smart contract function without importing the ABI, just using the contract address via ".call" & delegate call.
So, again to put my knowledge to the test, I used Protocol.sol & Hacker.sol.
Protocol.sol:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract Protocol {
mapping(address => uint256) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw() public payable {
require(balances[msg.sender] > 0, "BRUH");
(bool success, ) = (msg.sender).call{value: 1 ether}("");
require(success);
balances[msg.sender] = 0;
}
function getBalance() public view returns(uint256) {
return address(this).balance;
}
}
Hacker.sol:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract Hacker {
function protocolDeposit(address protocol) public payable {
(bool success,) = protocol.call{value: msg.value}(abi.encodeWithSignature("deposit()"));
require(success, "call failed");
}
function attack(address protocol) public payable {
(bool hacked,) = protocol.call(abi.encodeWithSignature("withdraw()"));
require(hacked, "attack failed");
}
// fallback() external payable {
// (bool hacked,) = protocol.call(abi.encodeWithSignature("withdraw()"));
// require(hacked, "hack failed");
// }
function rektMoney() public view returns(uint256) {
return address(this).balance;
}
}
The problem, I am facing right now is calling withdraw() func. I am able to deposit ETH using Hacker.sol into Protocol.sol but I'm unable to call withdraw() using attack
Maybe it is because the withdraw func in the protocol.sol is also using call to transfer ETH.
How to ".call" a function of another contract which is using ".call" as well?
How I can solve this problem? Pls Help, Thanks in Advance
I need to implement receive or fallback function in order to receive money in the hacker contract.
fallback() external payable {}
Working now Alhumdulilah
I am trying to make a simple contract that can display your wallet balance and send ether to another wallet in Remix IDE. I want a user to be able to change the msg.value, how do I do that in Remix besides the Value in "deploy & run transactions" menu? Thanks
pragma solidity >=0.4.22 <0.9.0;
contract Ethereum {
address private owner = msg.sender;
constructor() {
}
function getBalance() public view returns (uint256) {
return owner.balance;
}
function sendViaCall(address payable _to) public payable {
(bool sent, bytes memory data) = _to.call{value: msg.value}("");
require(sent, "Failed to send Ether");
}
}
the withdraw function gets me an error and it shows send and transfer are only available for object of type address payable and not address...
Confusing!!
solidity
//SPDX-License-Identifier: MIT
//this line of code was created to fund account
//show the value of fund in the address
pragma solidity ^0.8.0;
// the fundMe contract should be able to accept payment
function withdraw()payable public {
msg.sender.transfer(address(this).balance);
}
}
In Solidity, there is a difference between a normal address and a payable address so the correct way to send Ether to the sender would be payable(msg.sender).transfer(address(this).balance); this converts the normal address to a payable address. For more details take a look at this
I think up until solidity ^0.8.0, msg.sender was payable. withdraw function should be called only by the owner of the contract and you do not need to make it payable.
address payable private owner;
// set the owner when the contract is created
constructor(){
owner=payable(msg.sender)
}
function withdraw() public {
require(msg.sender==owner,"only contract owner can call this");
owner.transfer(address(this).balance);
}
However, using transfer is not safe. Because .transfer() sends more gas than 2300. Thus making it possible for reentrancy. A better way would be:
function withdraw() public {
require(msg.sender==owner,"only contract owner can call this");
(bool success, ) = owner.call{value:address(this).balance}("");
// success should be true
require(success,"Withdraw failed")
}
What is the difference between msg.sender and address(this) in the below code?
**pragma solidity ^0.8.0;
contract Escrow{
address public payer;
address payable public payee;
address public lawyer;
uint public amount;
constructor(
address _payer,
address payable _payee,
uint _amount) {
payer = _payer;
payee = _payee;
lawyer = msg.sender;
amount = _amount;
}
function deposit() payable public {
require(msg.sender == payer, 'Sender must be the payer');
require(address(this).balance <= amount, 'Cant send more than escrow amount');
}
function release() public {
require(address(this).balance == amount, 'cannot release funds before full amount is sent');
require(msg.sender == lawyer, 'only lawyer can release funds');
payee.transfer(amount);
}
function balanceOf() view public returns(uint) {
return address(this).balance;
}
}**
msg.sender is the address of the contract caller.
address(this) is the address of the smart contract itself.
They are both addresses in Solidity, but there is a big difference between msg.sender and address(this).
Allow me to use a simplified Smart Contract below to highlight the difference. All screenshots are from the Remix-Ethereum IDE (click here).
pragma solidity ^0.8.0;
contract Escrow {
address public owner;
constructor() {
owner = msg.sender;
}
function depositNothing() public view {
require(msg.sender == owner, 'You are not the owner!');
}
function balanceOf() view public returns(uint) {
return address(this).balance;
}
}
msg.sender
We are talking about the ACCOUNT address from which the function in the Smart Contract was called. For example, suppose in the Remix Ethereum (IDE), the Escrow Smart Contract was deployed from the ACCOUNT address:
0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
In that case, the State Variable owner will have the same address mentioned above. This is because the constructor function was called from that address.
Now, suppose we change the ACCOUNT address to:
0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
We then call the function depositNothing from the Smart Contract which was deployed earlier. You will get the following error, however:
This is because the msg.sender in the depositNothing function equates to the second ACCOUNT address. This obviously does not equate to the first ACCOUNT Address - owner. The second argument in the require function was therefore returned along with the error.
address(this)
This is not the same as the ACCOUNT Address discussed earlier. This strictly refers to the address given to the Smart Contract when it is deployed to the Ethereum blockchain.
This can be found here:
0xd8b934580fcE35a11B58C6D73aDeE468a2833fa8
I have the following smart contract:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function getSenderAddress() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function getAddress() public view returns (address)
{
return address(this);
}
function getTokenAddress() public view returns (address)
{
return address(token);
}
function buy() payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 amountTobuy = msg.value;
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
// https://stackoverflow.com/questions/67341914/error-send-and-transfer-are-only-available-for-objects-of-type-address-payable
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
if I call the buy() method from truffle console, it executes without any exceptions:
truffle(development)> MyCoinDEX.buy({value: 1})
I verified that the account calling the buy() method receives the token. However, the balance of Ether in Ganache for the account calling the buy() method doesn't decrease. So essentially, the account is getting tokens for free.
What's going on here? How do I fix it?
I am not sure but it would be necessary to investigate about the balance of the contract account. The gas for token.transfer might be paid by the contract account balance, since the contract account is the transaction sender for token contract.
Or the balance decrement would be unnoticeable because it is too small.
I would be happy to know about the answer if you have found out.