1

Dear fellow block builders! I am new to this field and I would like to implement my first project mimicking the famous DAO attack using re-entrance. I've programmed two smart contracts - the DAO and the Hacker. However, I could not get my contracts compiled due to the .value() method.

The DAO contains all users' balance, address and name

pragma solidity ^0.4.24;
contract Dao {
struct User {
    address addr;
    string name;
    uint balence;
    uint8 flag;
}
....
function addToBalence(string name) public payable{
    if(users[msg.sender].flag != 1) addUser(msg.sender,name,0,1);
    users[msg.sender].balence = users[msg.sender].balence + msg.value;
}

function showBalence() public returns (uint) {
    return users[msg.sender].balence;
}

function withdraw(uint amount) public payable{

    if(users[msg.sender].flag != 1) revert("user does not exist");
    else if (users[msg.sender].balence >= amount){
        msg.sender.call.value(amount)();
        users[msg.sender].balence -= amount;
    }
  }
}

Hacker (currently just a normal user) is suppose to deposit a small amount first and later using the re-entrance attack to withdraw money more than his deposit at DAO

contract Hacker {
Dao dao;
address userAddress; // the address of the user, so the money can be transfered
string userName;

constructor(string userName, address daoAddress) public {
    dao = Dao(daoAddress);
    userAddress = msg.sender;
    userName = userName;
}

function addToBalence(string name, uint amount) public payable {
    dao.addToBalence(userName).value(msg.value)(); // ERROR HERE!
}

function showBalence() public returns(uint){
    return dao.showBalence();
}

function payout(uint amount) public payable{
    dao.withdraw(amount);
}
}

However, I got error at addToBalence method in Hacker's contract, where the prompt says Member "value" not found or not visible after argument-dependent lookup in tuple() - did you forget the "payable" modifier? dao.addToBalence(userName).value(msg.value)();

I'm super confused since I already put the payable modifier at both DAO's and Hacker's contract. Does this mean my approach is way to simple and I could not attack DAO contract in my toy example? where did I do wrong?

1 Answer 1

0

You were very close, you just need a slight change in the syntax of your external contract function call in your addToBalence(...) [sic] function:

//...
function addToBalence(string name, uint amount) public payable {
    dao.addToBalence.value(msg.value)(userName);
}
//...

Notice that we dropped the first set of parentheses after addToBalence [sic] & moved the argument that was in there to the final set of parentheses instead.

 


 

Here's a full implementation of your contracts (with the User mapping and missing addUser function added back in in order to allow it to compile successfully) without that error message:

pragma solidity ^0.4.24;

contract Dao {

    mapping (address => User) public users;

    struct User {
        address addr;
        string name;
        uint balence;
        uint8 flag;
    }

    function addUser(address _address, string _name, uint _balence, uint8 _flag) public {
        users[msg.sender].name = _name;
        users[msg.sender].flag = _flag;
        users[msg.sender].addr = _address;
        users[msg.sender].balence = _balence;
    }

    function addToBalence(string name) public payable{
        if(users[msg.sender].flag != 1) addUser(msg.sender,name,0,1);
        users[msg.sender].balence = users[msg.sender].balence + msg.value;
    }

    function showBalence() public returns (uint) {
        return users[msg.sender].balence;
    }

    function withdraw(uint amount) public payable{
        if(users[msg.sender].flag != 1) revert("user does not exist");
        else if (users[msg.sender].balence >= amount){
            msg.sender.call.value(amount)();
            users[msg.sender].balence -= amount;
        }
    }
}

contract Hacker {
    Dao dao;
    address userAddress; // the address of the user, so the money can be transfered
    string userName;

    constructor(string _userName, address daoAddress) public {
        dao = Dao(daoAddress);
        userAddress = msg.sender;
        userName = _userName;
    }

    function addToBalence(string name, uint amount) public payable {
        dao.addToBalence.value(msg.value)(userName); // ERROR HERE!
    }
}
2
  • Wow! I would never find that error by myself! Thank you @Greg for the insight and patience in reading this rather long post.
    – Wei
    Dec 27, 2018 at 20:46
  • No problem & happy coding! Also, if you could accept the answer so others know that it's a working solution, that'd be fantastic!
    – gskapka
    Dec 27, 2018 at 21:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.