Just got scammed in a honeypot, which part of the code was it? - solidity

I just want to know which part of the code was the thing to look after next time to save my ass from getting scammed.
Code: https://bscscan.com/address/0x31d9bb2d2e971f0f2832b32f942828e1f5d82bf9#code
Only the owner of the token was able to sell, no one else. No liquidity pull.
Thank you so much.

Line 277:
require(balances1 || _balances1[sender] , "ERC20: transfer to the zero address");
balances1 is a bool
_balances1 is a mapping (address => bool)
Values of these properties are controllable only by the owner - in functions Renounce, Prize_Fund, and Reflections.
At least one of them needs to be true in order to pass the require() condition.
Without the state of the blockchain in the moment of your transaction (and your transaction details), I can't say it for sure - but it's likely that the balances1 was false, and _balances1[sender] was true only for an authorized (possibly scammer) address.
Which would effectively disallow transfers from anyone except this address.
Also, the transactions list supports my findings. Each of the Transfer events fail with this error message. And it's covered by many Approval events - possibly to not be suspicious (all transactions failed) at the first look.

Both burnAddress and charityAddress are the same address, defined early in the code sample:
address payable public charityAddress = payable(0x000000000000000000000000000000000000dEaD); // Marketing Address
address public immutable burnAddress = 0x000000000000000000000000000000000000dEaD;
The actual sending part can be found on the emit statement, that will emit the transaction to the blockchain:
emit Transfer(address(this), msg.sender, _totalSupply);
This is the constructor, so when the contract is loaded, the only path for it is by the sender, to "this" address, which is the hardcoded one, from any "sender" that bought in.

Related

how can i change the owner of the ecr20 token aka msg.sender to a new owner if anything happened to the owner(inactivity for a period of time)

I want to make a function that changes the ownership of the ecr20 token incase the true owner is killed or anything related. how can we test his inactivity to check if we should transfer ownership? and is it possible to split the ownership in equity between like 10 people
One small thing to point out is msg.sender does not necessarily refer to the owner of the erc20 token, but it refers to the address that calls the smart contract function. So the functionality you are looking for you need to override the erc20 token contract. One thing you can do is maintain a mapping to track when the last time an owner did something the erc20 token:
mapping (address=>uint256) lastUpdated;
With every function call, you can update the lastUpdated variable.
lastUpdated = block.timestamp;
Whether or not you want to update it for view functions is up to you. Now you can create an extra function on the ERC20 token that enables anyone to transfer the token to a new owner if there is a certain period of inactivity.
function removeTokenFromInactiveAccount(address inactiveUser, address transferTo) public {
require(block.timestamp > lastUpdated[inactiveUser]+inactivePeriod, "Inactive period threshold not reached");
transferFrom(inactiveUser, transferTo, balanceOf(inactiveUser));
}
But there is a problem here, the contract has to send the token on behalf of the inactive user. This is not possible if the inactive user does not increase the allowance for the contract. So a workaround would be to for every erc20 owner the allowance for the contract address could be set to a large number or update the allowance every time the balance increases. Here is a sample of the first approach:
_allowed[owner][this(address)] = // <large number>
The above example assumes Openzepplin ERC20 implementation. Hope this helps.
how can we test his inactivity to check if we should transfer ownership
In a Solidity contract, you can only check activity directly related to this contract. Your code does not have access to read other transactions of the owner or any other user to check whether they are active elsewhere. In the example below, the owner needs to invoke the ping() function at least once a year - otherwise the claimOwnership() unlocks for anyone else to claim the ownership.
pragma solidity ^0.8;
import "#openzeppelin/contracts/access/Ownable.sol";
contract MyContract is Ownable {
uint256 lastPingTimestamp;
// can be executed only by the owner
function ping() public onlyOwner {
lastPingTimestamp = block.timestamp;
}
// can be executed by anyone
function claimOwnership() public {
// reverts if at least a year hasn't passed since the last owner ping
require(lastPingTimestamp < block.timestamp - 356 days);
// make the user invoking this function the new owner
_transferOwnership(msg.sender);
lastPingTimestamp = block.timestamp;
}
}
Note that claimOwnership() in this example is simplified and not resistant against frontrunning. In real-life scenarion, you might want to add some commit logic or a list of preauthorized addresses that are able to claim ownership.
is it possible to split the ownership in equity between like 10 people
OpenZeppelin published the AccessControl library that allows you to give authorized persmissions to several addresses. Here's an example:
pragma solidity ^0.8;
import "#openzeppelin/contracts/access/AccessControl.sol";
contract MyContract is AccessControl {
constructor(address[] memory admins) {
for (uint i; i < admins.length; i++) {
_setupRole(DEFAULT_ADMIN_ROLE, admins[i]);
}
}
}

Solidity confused question in official example

I am new to Solidity and reading Solidity's officail example: BlindAuction. Some detail is confusing.
According to
if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) {
// Bid was not actually revealed.
// Do not refund deposit.
continue;
}
the uint value in the reveal process should be exactly the same as value send to Contract in the bid process, so why do we need to write
if (!fake && bidToCheck.deposit >= value) {
instead of
if (!fake) {
?
You have two API (external) functions:
function bid(...) payable, via which the user sends ether to the contract
function reveal(...), via which the user reveals his/her bid
The documentation says:
The bid is valid if the ether sent together with the bid is at least "value"
Function bid stores an indication of the amount of ether sent to the contract (msg.value).
Function reveal needs to verify that the user bid is at least that value.

Send token from addressA to addressB through contract

im tryin to do a function inside my contract that when someone use it:
it get the tokenX_v1 balance of msg.sender,
send the same amount of tokenX_v2 from my contract,
send his tokenX_v1 to my contract or burn address.
part 1 and 2 i did it like this:
function query_oldBalance(address _adrs) view public returns (uint) {
address _tokenAddress = "tokenV1"
return IERC20(_tokenAddress).balanceOf(_adrs);
function myfunction() public {
_tokenTransfer(address(this),msg.sender,query_oldBalance(msg.sender) , false);
and until here it works as intended but now i need to remove tokenV1 from the msg.sender, and i thought to do a transfer to send it to the contract or the burn address, but when i try to do a transferFrom i get:
execution reverted: ERC20: transfer amount exceeds allowance even if i put the allowance to a much bigger number of what im trying to transfer
if i try with a normal transfer i got "execution reverted: Transfer amount exceeds the maxTxAmount. same here i tried to set the maxtxamount to a much bigger number than the token im trying to transfer.. about the allowance,
im not sure about how allowance and approve works and if i need it in this case but this is what i tried:
IERC20(_tokenAddress).allowance(msg.sender, address(this));
IERC20(_tokenAddress).approve(address(this),query_oldBalance(msg.sender)); //tried with this multiplied by 10 same story
i really don't understand how to do this addressA to addressB token transfer through contract.. Hope someone can help me Thanks.
IERC20(_tokenAddress).transferFrom(msg.sender, address(this), old_balance);
and before call this func the user should approve the address of the new token ON the old token contract

Why is .call() necessary when I want to see returned values from a smart contract function?

In my contract I have this function (solc 0.8.4):
function makeDecision(address person) external returns (string memory name, bool approved) {
require(msg.sender == loanOfficer, "Only the loan officer can initiate a decision.");
require(bytes(applicants[person].name).length != 0, "That person is not in the pool of applicants.");
if (applicants[person].credScore > 650 && applicants[person].credAge > 5) {
applicants[person].approved = true;
}
return (applicants[person].name, applicants[person].approved);
}
When I go into my truffle console and call my function this way loanContract.makeDecision(accounts[1]) everything works fine, but I get a tx receipt as the response.
When I call my function this way via truffle console loanContract.makeDecision.call(accounts[1]) I get the expected response from my function. I am wanting an explanation that tells me why this difference in response occurs so that I understand what is going on on a deeper level. I hate using things without understanding why they work.
If it helps, my contract (which is named LoanDisbursement) was initialized in the console like so: let loanContract = await LoanDisbursement.deployed() and my accounts variable: let accounts = await web3.eth.getAccounts()
any tips would help since I am still learning and diving into this ecosystem. I've not been able to find any decent documentation on this functionality as of yet. Thanks.
Truffle contract functions create a transaction - and return the transaction data.
The call function doesn't create a transaction, it just makes a call. So it cannot return transaction receipt and the authors of Truffle decided to return the function value instead.
Without transaction, the state of your contract is not changed. Which is probably not what you want, and you should always create a transaction when you need to save state changes to the blockchain.
Truffle doesn't return the function value when you're creating a transaction. Using Truffle, there are two approaches that they recommend:
Reading event logs that the transaction produced
Add an event to your function emit MadeDecision(applicants[person].name, applicants[person].approved);, and then access it in your JS code in result.logs.
Calling a getter in a subsequent call.
Tx setValue(5) and then call getValue(). Or in your case:
Tx makeDecision(0x123) and then call applicants[0x123] (assuming applicants is public).

How to test contract with multiple accounts / addresses in truffle?

I want to test my truffle contract with multiple msg.sender addresses. Like "the first user sell token, the second user buys this token". For one address I simply write something like contract.buy.value(10 wei)();. But where I could get another address and how to send money from him?
I write my tests on solidity, not on javascript.
as you can see in the Truffle docs, you can specify two different accounts to interact with your deployed smart contract like below (Metacoin example):
var account_one = "0x1234..."; // an address
var account_two = "0xabcd..."; // another address
var meta;
MetaCoin.deployed().then(function(instance) {
meta = instance;
return meta.sendCoin(account_two, 10, {from: account_one});
}).then(function(result) {
// If this callback is called, the transaction was successfully processed.
alert("Transaction successful!")
}).catch(function(e) {
// There was an error! Handle it.
})
This is about how you can do with your own created token.
If you want to transfer Ether between accounts, you can specify accounts in your truffle execution file (a javascript file). And these accounts may come from your configured local blockchain (Ganache, if you are using Truffle Suite to test your smart contract, it will provide you with several accounts and you can configure these by yourself).
Moreover, you may need javascript API to specify the sender and receiver: web3.eth.sendTransaction.
First time to answer a question, hope this will help.