Why Sender address emitted in event differs from saved in storage? - solidity

The wallet address that is sent through event differs from the one stored in contract
Hi, I have a contract that is deployed to development network through truffle.
I trigger function that looks like this:
struct Round {
bool isValue;
uint32 id;
RoundState state;
address[] addresses;
RoundBet[] bets;
mapping(address => bool) betUsers;
mapping(address => uint256) userBets;
uint256 winTicket;
uint256 amount;
uint256 lastTicket;
address winner;
}
.....
event roundBet(
address user,
uint256 amount,
uint256 start,
uint256 end
);
......
function test() payable public {
Round storage round = roundsHistory[currentRound];
require(round.isValue == true);
require(round.state == RoundState.started);
require(msg.value >= MIN_BET);
uint256 amount = msg.value - msg.value % MIN_STEP;
if(!round.betUsers[msg.sender]){
round.addresses.push(msg.sender);
round.betUsers[msg.sender] = true;
}
round.userBets[msg.sender] += amount;
uint256 sticket = round.lastTicket + 1;
uint256 eticket = sticket + amount;
uint256 length = round.bets.push(RoundBet(true, sticket, eticket, msg.sender, amount));
round.amount += amount;
round.lastTicket = eticket;
if(round.addresses.length == 2){
round.state = RoundState.running;
emit roundTimerStart(currentRound);
}
emit roundBet(msg.sender,amount, sticket, eticket);
}
AS you can see I emit roundBet event at the end of function call. The problem is that value of "user" of that event differs from msg.sender that is stored in round.addresses(values stored in round.addresses - is currect and the one emited - is wrong)

If you are using Metamask, keep in mind that it does not switch the account set as msg.sender to the contract, it seems to use the first account (0) to sign every transaction.
We encountered the same problem during a school project.

First of all about platform. It was tron not ethereum. May be in ethereum there is no such issue.
So what I did:
I do not pass address in event. I save it in internal structure
In event I do pass index of saved address in structure
I've wrote a separate method that returns address (and other usefull info) from internal structures by its index.
So by using this workaround I was able to get needed information from contract.

Related

Getting Block Hash of another contract

I've seen some problems with calling functions from other contracts but I believe my problem is fairly genuine to demand a separate question if only to be negated in its possibility.
So I am trying to call a contract within another contract. Is it possible to get the blockhash of a particular block number of the callee contract within my caller? If so how?
Every syntax I've attempted fails for some reason.
Contract A
enter code here
contract DiceGame {
uint256 public nonce = 0;
uint256 public prize = 0;
event Roll(address indexed player, uint256 roll);
event Winner(address winner, uint256 amount);
constructor() payable {
resetPrize();
}
function resetPrize() private {
prize = ((address(this).balance * 10) / 100);
}
function rollTheDice() public payable {
require(msg.value >= 0.002 ether, "Failed to send enough value");
bytes32 prevHash = blockhash(block.number - 1);
bytes32 hash = keccak256(abi.encodePacked(prevHash, address(this), nonce));
uint256 roll = uint256(hash) % 16;
console.log('\t'," Dice Game Roll:",roll);
nonce++;
prize += ((msg.value * 40) / 100);
emit Roll(msg.sender, roll);
if (roll > 2 ) {
return;
}
uint256 amount = prize;
(bool sent, ) = msg.sender.call{value: amount}("");
require(sent, "Failed to send Ether");
resetPrize();
emit Winner(msg.sender, amount);
}
receive() external payable { }
}
Contract B
enter code here
contract RiggedRoll is Ownable {
DiceGame public diceGame;
constructor(address payable diceGameAddress) {
diceGame = DiceGame(diceGameAddress);
}
//Add withdraw function to transfer ether from the rigged contract to an address
//Add riggedRoll() function to predict the randomness in the DiceGame contract and only roll when it's going to be a winner
function riggedRoll(bytes32 riggedHash) public payable {
riggedHash = address(diceGame).blockhash(block.number-1); //I am aware this syntax is broken but I am not able to find a legitimate one to access the data from contract A.
}
//Add receive() function so contract can receive Eth
receive() external payable { }
}
A contract doesn't know when it was last called, unless you explicitly store this information.
Then you can get the block hash using the native blockhash() function (accepts the block number as a parameter).
contract Target {
uint256 public lastCalledAtBlockNumber;
// The value is stored only if you invoke the function using a (read-write) transaction.
// If you invoke the function using a (read-only) call, then it's not stored.
function foo() external {
lastCalledAtBlockNumber = block.number;
}
}
bytes32 blockHash = blockhash(block.number);

PancackeswapV2Router swapExactETHForTokensSupportingFeeOnTransferTokens: 'Pancake: TRANSFER_FAILED' when "from" equals to "pancackeSwapV2pair"

PancakeSwap is driving me crazy!
I have this simple contract: when the token are transferred from someone different from the owner, instead of making the transer, swap the reveiced tokens with Bnb.
function _swapAsBnb(address from, address to, uint256 amount) private {
if(from != _owner && !lockSwap){
// I tranfer tokens to the contract address in order to make it able to swap them
_transfer(from, address(this), amount);
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = _uniswapV2Router.WETH();
_approve(address(this), address(_uniswapV2Router), tokenAmount);
// use the lock to avoid cycles during the swap
lockSwap = true;
_uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp);
lockSwap = false;
}
else{
_transfer(from, to, amount);
emit Transfer(from, to, amount);
}
}
function _transfer(address from, address to, uint256 amount) private {
require(from != address(0), "BEP20: transfer from the zero address");
require(balanceOf(from) >= amount, "BEP20: transfer amount exceeds balance");
unchecked {
_balances[from] -= amount;
}
_balances[to] += amount;
}
receive() external payable {}
The steps I made are:
Deploy the contract on BSC Testnet
Create a test pool at https://pancake.kiemtienonline360.com/ containing the pair WBNB:MyToken
I use another wallet in order to buy the token (don't worry, there is enough liquidity)
What I expect is the new wallet has no token, instead the contract address is supposed to have the just swapped Bnb.
However i receive the following error: 'Pancake: TRANSFER_FAILED'
I noticed this only happen when a wallet buy the token, not when it has been sold.
So the problem occurs when the 'from' argument is the pancakeswap pair it self (in fact, I can avoid the problem by checking that from != uniswapV2Pair address).

How to add method id in metamask

I have deployed smart contract using remix IDE, launched with Injected Web3 on Ropsten test network. I could call BuyTokens function within solidity IDE successfully, but when tried to buy tokens with metamask from other address transaction get reverted. I can see the difference between those operations on ropsten.etherscan explorer - the difference is in Input Data field.
Metamask transaction has value 0x and transaction via remix is:
Function: buyTokens() ***
MethodID: 0xd0febe4c
Code:
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract Token {
// Track how many tokens are owned by each address.
mapping (address => uint256) public balanceOf;
// Modify this section
string public name = "DemoCoin";
string public symbol = "DC";
uint8 public decimals = 8;
uint256 public totalSupply = 1000000000 * (uint256(10) ** decimals);
address public owner;
//uint scaler = 10e18; // == 1 ETH in wei
//uint public coinPrice = 20; //initial price => 20 cents
event Transfer(address indexed from, address indexed to, uint256 value);
constructor() {
// Initially assign all tokens to the contract's creator.
owner = msg.sender;
balanceOf[msg.sender] = totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
// Might be executed automaticlly
// https://blog.chronologic.network/schedule-your-transaction-now-using-mycrypto-and-myetherwallet-17b48166b412
// function changeCoinPrice() public {
// uint newCoinPrice;
// require(msg.sender == address(0));
// coinPrice = newCoinPrice;
// }
function buyTokens() public payable {
// msg.value in wei so 1ETH = 10e18
// lets set 0.20 cents for 1 token
uint paidAmount;
require(balanceOf[msg.sender] >= paidAmount);
require(balanceOf[owner] >= value);
uint tokens;
tokens = value/10e14;
balanceOf[owner] -= tokens;
balanceOf[msg.sender] += tokens;
emit Transfer(owner, msg.sender, tokens);
}
function msgSenderBalancce() public view returns (uint) {
return balanceOf[msg.sender];
}
function withDrawEth() public view {
require(msg.sender == owner);
}
}
Why these methods are called diffrently? And how to add method id in metamask? Or am I missing something and this should be handled in other way?
MetaMask has a very basic UI. It only allows transfers of ETH and standardized tokens, but it doesn't show any buttons to call other contract functions. It also doesn't allow creating any custom buttons in their UI.
You'll need to set the data field of the transaction to 0xd0febe4c (which effectively executes the buyTokens() function).
But - they also don't allow specifying the data field value manually in the UI, so you'll need to preset it using the Ethereum provider API.
Your web app connects to the user's MetaMask acccount. It opens a MetaMask window and the user needs to manually confirm the connect.
The web app sends a request to MetaMask specifying the transaction with data field value.
The user confirms the transaction (which now includes the data field value 0xd0febe4c) in their MetaMask UI.

How to add "transaction fee" to ERC20 or BEP20 smart contracts?

There's new tokens that "charge a transaction fee" aside the usual ETH gas fee. I'm talking about a transaction fee that subtracts from the token itself. Let's say 100 tokens are transferred. 1 token goes into a central account as "transaction fee". It's doable since coins like $GRUMPY have it but I can't find the function on the code that would allow me to do that.
intrested here too.
I have something simple see _transfer function below.
Problem is it will create 2 transactions and more Gas Fees to pay.
Dont know if you splitt and send the fee to the contract itself if this reduce fees.
This is just an idea not testet. Intrested in other solutions from the community.
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
address FeeReceiverAdr = 0xE037D395bB24C69bD0347F4e1652199BF60a41d1;
address payable FeeReceiver = payable(FeeReceiverAdr); // Correct since Solidity >= 0.6.0
_beforeTokenTransfer(sender, recipient, amount);
uint bpsfee = 1618;
uint bps = 100000;
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
_balances[sender] = senderBalance - amount;
_balances[recipient] += taxedValue;
_balances[FeeReceiver] += fee;
emit Transfer(sender, recipient, taxedValue);
emit Transfer(sender, FeeReceiver, fee);
}
I found a solution that may help! In case anyone was still looking around for clarity. Here is a code snippet for enabling ERC20 % distribution. Code has not been audited, so please use it at your own risk, but this should be enough to start experimenting.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract TransfertTokenAndPercentageToTargetAddress{
// pay 1% of all transactions to target address
//test address = testnet
address payable target = 0x326Da5Aa845675a1967e1F7E31A32a4412eD47DD;
// state variables for your token to track balances and to test
mapping (address => uint) public balanceOf;
uint public totalSupply;
// create a token and assign all the tokens to the creator to test
constructor(uint _totalSupply) public {
totalSupply = _totalSupply;
balanceOf[msg.sender] = totalSupply;
}
// the token transfer function with the addition of a 1% share that
// goes to the target address specified above
function transfer(address _to, uint amount) public {
// calculate the share of tokens for your target address
uint shareForX = amount/100;
// save the previous balance of the sender for later assertion
// verify that all works as intended
uint senderBalance = balanceOf[msg.sender];
// check the sender actually has enough tokens to transfer with function
// modifier
require(senderBalance >= amount, 'Not enough balance');
// reduce senders balance first to prevent the sender from sending more
// than he owns by submitting multiple transactions
balanceOf[msg.sender] -= amount;
// store the previous balance of the receiver for later assertion
// verify that all works as intended
uint receiverBalance = balanceOf[_to];
// add the amount of tokens to the receiver but deduct the share for the
// target address
balanceOf[_to] += amount-shareForX;
// add the share to the target address
balanceOf[target] += shareForX;
// check that everything works as intended, specifically checking that
// the sum of tokens in all accounts is the same before and after
// the transaction.
assert(balanceOf[msg.sender] + balanceOf[_to] + shareForX ==
senderBalance + receiverBalance);
}
}

Solidity code not transferring ether in Javascript VM environment

I am trying my hands on a program which transfers test ethers from one account to other on remix ide using javascript VM environment. I am unable to see funds getting transferred to beneficiary account.
I have put diagnostic code as well which prints the contract current balance but it always prints 0.
pragma solidity <=0.5.7;
contract MultiSigWallet{
address payable private owner;
address payable private beneficiary;
uint private minApprovers ;
uint private currentApprovals;
mapping(address => bool) approvedBy;
mapping(address =>bool) isApprover;
uint public contractBalance;
constructor (address payable _beneficiary, address [] memory _approvers, int32 _minApprovers) public payable{
require(_approvers.length > 0 && _minApprovers > 0,"At least one approver is required!");
require(_approvers.length >= minApprovers,"Number of minimum approvers cannot be more than total approvers count");
owner = msg.sender;
beneficiary = _beneficiary;
for(uint i = 0;i<_approvers.length;i++){
isApprover[_approvers[i]]= true;
}
}
function approve () public{
require(isApprover[msg.sender],"Not an Approver");
if(!approvedBy[msg.sender]){
approvedBy[msg.sender] = true;
currentApprovals++;
}
if(currentApprovals== minApprovers){
beneficiary.send(address(this).balance);
selfdestruct(owner);
}
}
function getContractBalance () public payable returns( uint){
contractBalance = address(this).balance;
}
function reject() public {
require(isApprover[msg.sender],"Not an approver!");
selfdestruct(owner);
}
}
if i provide beneficiary address as a1, list of approvers as a2,a3 and i invoke the constructor with a4 by putting 10 ethers in the value field, i can see 10 ether reduction in a4 balance.
Next after approving from accounts a2, a3, i am expecting the balance of a1 to swell by 10 ethers and balance of contract turns 0.
However i don't see a change in a1 balance and contract balance is always 0.
Can someone explain what i am doing wrong or if any gaps in my understanding?
You probably want to do something like minApprovers = _minApprovers in the constructor. Otherwise minApprovers is always 0, and your == check will always fail because the first successful call to approve will make currentApprovals == 1.